Lookups: fix dbmnz crash on zero-length datum. Bug 3079
authorJeremy Harris <jgh146exb@wizmail.org>
Sat, 16 Mar 2024 13:50:45 +0000 (13:50 +0000)
committerJeremy Harris <jgh146exb@wizmail.org>
Sat, 16 Mar 2024 13:50:45 +0000 (13:50 +0000)
Broken-by: 6d2c02560e5c
doc/doc-txt/ChangeLog
src/src/dbfn.c
src/src/exim_dbutil.c
src/src/lookups/dbmdb.c
test/aux-fixed/2302.emptydbmnzlookup [new file with mode: 0644]
test/confs/2302 [new file with mode: 0644]
test/scripts/2300-DBM/2302 [new file with mode: 0644]
test/stdout/2302 [new file with mode: 0644]

index 3dc0e551256545889795c6da7bfd7a23748b0fe6..a6da950017214e262b5be3ee3a79e382d7ba8a7b 100644 (file)
@@ -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
 -----------------
index 3c51162a42a260b89be208e1b9d438f152ded1af..460fd8bb763f2d8f6587bfaa5db59d6a9db96e3d 100644 (file)
@@ -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;
index 3f70c2fd51023c1c561c8ee5efc9ec137e63426b..4d213773bf9203ac9b8554bbb3e8414193a37c8d 100644 (file)
@@ -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;
index aa930e6543ee097352c2f1656f73647a23bbf95e..96665b6e4e68d7204b29db0e1fb16409a1b8623a 100644 (file)
@@ -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 (file)
index 0000000..9f64dc3
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 (file)
index 0000000..de48435
--- /dev/null
@@ -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 (file)
index 0000000..4bdbc86
--- /dev/null
@@ -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 (file)
index 0000000..fe51488
--- /dev/null
@@ -0,0 +1 @@
+[]