Fix double-free crash when creating empty NdbFilter

When ndb_filter_end processes an empty filter (no fields added), it calls
realloc(filter->elem_buf.start, 0) which frees the memory and returns NULL.
The existing code only updated the pointer if realloc
returned non-NULL, leaving elem_buf.start pointing to freed memory. This
caused a double-free crash when ndb_filter_destroy later called free() on
the dangling pointer.

Fix by explicitly setting filter->elem_buf.start to NULL when realloc
returns NULL due to zero-size allocation, and update the assertion to
allow NULL pointers for empty filters. ndb_filter_destroy already checks
for NULL before freeing.

Closes: https://github.com/damus-io/damus/issues/3634
Changelog-Fixed: Fix memory corruption crash when creating empty filters
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit is contained in:
Daniel D’Aquino
2026-02-17 04:55:07 -08:00
parent 546e9eec32
commit 59498e3256

View File

@@ -614,10 +614,20 @@ int ndb_filter_end(struct ndb_filter *filter)
memmove(filter->elem_buf.p, filter->data_buf.start, data_len);
// realloc the whole thing
rel = realloc(filter->elem_buf.start, elem_len + data_len);
if (rel)
filter->elem_buf.start = rel;
assert(filter->elem_buf.start);
size_t new_size = elem_len + data_len;
if (new_size == 0) {
// Avoid calling realloc with size 0 (implementation-defined behavior)
// Explicitly free and set to NULL
free(filter->elem_buf.start);
filter->elem_buf.start = NULL;
} else {
rel = realloc(filter->elem_buf.start, new_size);
if (rel) {
filter->elem_buf.start = rel;
}
// Assert allocation succeeded for non-zero size
assert(filter->elem_buf.start);
}
filter->elem_buf.end = filter->elem_buf.start + elem_len;
filter->elem_buf.p = filter->elem_buf.end;