From: Jeremy Harris Date: Sat, 16 Mar 2024 13:50:45 +0000 (+0000) Subject: Lookups: fix dbmnz crash on zero-length datum. Bug 3079 X-Git-Url: https://git.exim.org/exim.git/commitdiff_plain/a7e6ad0ba38cf088e841c321042f81966d846b4b Lookups: fix dbmnz crash on zero-length datum. Bug 3079 Broken-by: 6d2c02560e5c --- diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index 3dc0e5512..a6da95001 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -125,6 +125,9 @@ JH/24 Bug 3081: Fix a delivery process crash. When the router "errors_to" trip on the configuration data being readonly. Instead of modifying in-place, copy data. Found and fixed by Peter Benie. +JH/25 Bug 3079: Fix crash in dbmnz. When a key was present for zero-length + data a null pointer was followed. Find and testcase by Sebastian Bugge. + Exim version 4.97 ----------------- diff --git a/src/src/dbfn.c b/src/src/dbfn.c index 3c51162a4..460fd8bb7 100644 --- a/src/src/dbfn.c +++ b/src/src/dbfn.c @@ -239,12 +239,13 @@ Returns: a pointer to the retrieved record, or */ void * -dbfn_read_with_length(open_db *dbblock, const uschar *key, int *length) +dbfn_read_with_length(open_db * dbblock, const uschar * key, int * length) { -void *yield; +void * yield; EXIM_DATUM key_datum, result_datum; int klen = Ustrlen(key) + 1; uschar * key_copy = store_get(klen, key); +unsigned dlen; memcpy(key_copy, key, klen); @@ -260,9 +261,10 @@ if (!exim_dbget(dbblock->dbptr, &key_datum, &result_datum)) return NULL; /* Assume the data store could have been tainted. Properly, we should store the taint status with the data. */ -yield = store_get(exim_datum_size_get(&result_datum), GET_TAINTED); -memcpy(yield, exim_datum_data_get(&result_datum), exim_datum_size_get(&result_datum)); -if (length) *length = exim_datum_size_get(&result_datum); +dlen = exim_datum_size_get(&result_datum); +yield = store_get(dlen, GET_TAINTED); +memcpy(yield, exim_datum_data_get(&result_datum), dlen); +if (length) *length = dlen; exim_datum_free(&result_datum); /* Some DBM libs require freeing */ return yield; diff --git a/src/src/exim_dbutil.c b/src/src/exim_dbutil.c index 3f70c2fd5..4d213773b 100644 --- a/src/src/exim_dbutil.c +++ b/src/src/exim_dbutil.c @@ -407,12 +407,13 @@ Returns: a pointer to the retrieved record, or */ void * -dbfn_read_with_length(open_db *dbblock, const uschar *key, int *length) +dbfn_read_with_length(open_db * dbblock, const uschar * key, int * length) { -void *yield; +void * yield; EXIM_DATUM key_datum, result_datum; int klen = Ustrlen(key) + 1; uschar * key_copy = store_get(klen, key); +unsigned dlen; memcpy(key_copy, key, klen); @@ -426,9 +427,10 @@ if (!exim_dbget(dbblock->dbptr, &key_datum, &result_datum)) return NULL; /* Assume for now that anything stored could have been tainted. Properly we should store the taint status along with the data. */ -yield = store_get(exim_datum_size_get(&result_datum), GET_TAINTED); -memcpy(yield, exim_datum_data_get(&result_datum), exim_datum_size_get(&result_datum)); -if (length) *length = exim_datum_size_get(&result_datum); +dlen = exim_datum_size_get(&result_datum); +yield = store_get(dlen, GET_TAINTED); +memcpy(yield, exim_datum_data_get(&result_datum), dlen); +if (length) *length = dlen; exim_datum_free(&result_datum); /* Some DBM libs require freeing */ return yield; diff --git a/src/src/lookups/dbmdb.c b/src/src/lookups/dbmdb.c index aa930e654..96665b6e4 100644 --- a/src/src/lookups/dbmdb.c +++ b/src/src/lookups/dbmdb.c @@ -102,7 +102,8 @@ exim_datum_size_set(&key, length); if (exim_dbget(d, &key, &data)) { - *result = string_copyn(exim_datum_data_get(&data), exim_datum_size_get(&data)); + unsigned len = exim_datum_size_get(&data); + *result = len > 0 ? string_copyn(exim_datum_data_get(&data), len) : US""; exim_datum_free(&data); /* Some DBM libraries need a free() call */ return OK; } @@ -283,3 +284,5 @@ static lookup_info *_lookup_list[] = { &dbm_lookup_info, &dbmz_lookup_info, &dbm lookup_module_info dbmdb_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 3 }; /* End of lookups/dbmdb.c */ +/* vi: aw ai sw=2 +*/ diff --git a/test/aux-fixed/2302.emptydbmnzlookup b/test/aux-fixed/2302.emptydbmnzlookup new file mode 100644 index 000000000..9f64dc3fd Binary files /dev/null and b/test/aux-fixed/2302.emptydbmnzlookup differ diff --git a/test/confs/2302 b/test/confs/2302 new file mode 100644 index 000000000..de484356c --- /dev/null +++ b/test/confs/2302 @@ -0,0 +1,3 @@ +# Exim test configuration 2302 +.include DIR/aux-var/std_conf_prefix +# End diff --git a/test/scripts/2300-DBM/2302 b/test/scripts/2300-DBM/2302 new file mode 100644 index 000000000..4bdbc869e --- /dev/null +++ b/test/scripts/2300-DBM/2302 @@ -0,0 +1,4 @@ +# lookup dbmnz +# +exim -be '[${lookup{test}dbmnz{DIR/aux-fixed/TESTNUM.emptydbmnzlookup}}]' +**** diff --git a/test/stdout/2302 b/test/stdout/2302 new file mode 100644 index 000000000..fe51488c7 --- /dev/null +++ b/test/stdout/2302 @@ -0,0 +1 @@ +[]