Gitweb:
https://git.exim.org/exim.git/commitdiff/a7e6ad0ba38cf088e841c321042f81966d846b4b
Commit: a7e6ad0ba38cf088e841c321042f81966d846b4b
Parent: c71f869820b45b911cc8edbd0de88bbc9621fd5f
Author: Jeremy Harris <jgh146exb@???>
AuthorDate: Sat Mar 16 13:50:45 2024 +0000
Committer: Jeremy Harris <jgh146exb@???>
CommitDate: Sat Mar 16 13:50:45 2024 +0000
Lookups: fix dbmnz crash on zero-length datum. Bug 3079
Broken-by: 6d2c02560e5c
---
doc/doc-txt/ChangeLog | 3 +++
src/src/dbfn.c | 12 +++++++-----
src/src/exim_dbutil.c | 12 +++++++-----
src/src/lookups/dbmdb.c | 5 ++++-
test/aux-fixed/2302.emptydbmnzlookup | Bin 0 -> 12288 bytes
test/confs/2302 | 3 +++
test/scripts/2300-DBM/2302 | 4 ++++
test/stdout/2302 | 1 +
8 files changed, 29 insertions(+), 11 deletions(-)
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 @@
+[]
--
## subscription configuration (requires account):
##
https://lists.exim.org/mailman3/postorius/lists/exim-cvs.lists.exim.org/
## unsubscribe (doesn't require an account):
## exim-cvs-unsubscribe@???
## Exim details at
http://www.exim.org/
## Please use the Wiki with this list -
http://wiki.exim.org/