diff options
| author | René Scharfe <l.s.r@web.de> | 2024-12-28 10:47:05 +0100 |
|---|---|---|
| committer | Junio C Hamano <gitster@pobox.com> | 2024-12-28 08:00:44 -0800 |
| commit | 8db127d43f5b0eff254a851f9c966b7b85d91992 (patch) | |
| tree | 8c7cd2c2a66573512ade8f4e80f5af8e88fe1e4b /t/unit-tests | |
| parent | 76cf4f61c87855ebf0784b88aaf737d6b09f504b (diff) | |
| download | git-8db127d43f5b0eff254a851f9c966b7b85d91992.tar.gz | |
reftable: avoid leaks on realloc error
When realloc(3) fails, it returns NULL and keeps the original allocation
intact. REFTABLE_ALLOC_GROW overwrites both the original pointer and
the allocation count variable in that case, simultaneously leaking the
original allocation and misrepresenting the number of storable items.
parse_names() and reftable_buf_add() avoid leaking by restoring the
original pointer value on failure, but all other callers seem to be OK
with losing the old allocation. Add a new variant of the macro,
REFTABLE_ALLOC_GROW_OR_NULL, which plugs the leak and zeros the
allocation counter. Use it for those callers.
Signed-off-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 't/unit-tests')
| -rw-r--r-- | t/unit-tests/t-reftable-basics.c | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/t/unit-tests/t-reftable-basics.c b/t/unit-tests/t-reftable-basics.c index 65d50df091..5bf79c9976 100644 --- a/t/unit-tests/t-reftable-basics.c +++ b/t/unit-tests/t-reftable-basics.c @@ -20,6 +20,11 @@ static int integer_needle_lesseq(size_t i, void *_args) return args->needle <= args->haystack[i]; } +static void *realloc_stub(void *p UNUSED, size_t size UNUSED) +{ + return NULL; +} + int cmd_main(int argc UNUSED, const char *argv[] UNUSED) { if_test ("binary search with binsearch works") { @@ -141,5 +146,30 @@ int cmd_main(int argc UNUSED, const char *argv[] UNUSED) check_int(in, ==, out); } + if_test ("REFTABLE_ALLOC_GROW_OR_NULL works") { + int *arr = NULL; + size_t alloc = 0, old_alloc; + + REFTABLE_ALLOC_GROW_OR_NULL(arr, 1, alloc); + check(arr != NULL); + check_uint(alloc, >=, 1); + arr[0] = 42; + + old_alloc = alloc; + REFTABLE_ALLOC_GROW_OR_NULL(arr, old_alloc + 1, alloc); + check(arr != NULL); + check_uint(alloc, >, old_alloc); + arr[alloc - 1] = 42; + + old_alloc = alloc; + reftable_set_alloc(malloc, realloc_stub, free); + REFTABLE_ALLOC_GROW_OR_NULL(arr, old_alloc + 1, alloc); + check(arr == NULL); + check_uint(alloc, ==, 0); + reftable_set_alloc(malloc, realloc, free); + + reftable_free(arr); + } + return test_done(); } |
