diff options
| author | René Scharfe <l.s.r@web.de> | 2024-12-28 10:48:00 +0100 |
|---|---|---|
| committer | Junio C Hamano <gitster@pobox.com> | 2024-12-28 08:00:44 -0800 |
| commit | 2cca185e85171c462166839cfd6ee57c09573160 (patch) | |
| tree | e768f5c93812fe2976a52319c0454d7c99b75248 /t/unit-tests | |
| parent | 8db127d43f5b0eff254a851f9c966b7b85d91992 (diff) | |
| download | git-2cca185e85171c462166839cfd6ee57c09573160.tar.gz | |
reftable: fix allocation count 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() avoids the leak by keeping the original pointer if
reallocation fails, but still increase the allocation count in such a
case as if it succeeded. That's OK, because the error handling code
just frees everything and doesn't look at names_cap anymore.
reftable_buf_add() does the same, but here it is a problem as it leaves
the reftable_buf in a broken state, with ->alloc being roughly twice as
big as the actually allocated memory, allowing out-of-bounds writes in
subsequent calls.
Reimplement REFTABLE_ALLOC_GROW to avoid leaks, keep allocation counts
in sync and still signal failures to callers while avoiding code
duplication in callers. Make it an expression that evaluates to 0 if no
reallocation is needed or it succeeded and 1 on failure while keeping
the original pointer and allocation counter values.
Adjust REFTABLE_ALLOC_GROW_OR_NULL to the new calling convention for
REFTABLE_ALLOC_GROW, but keep its support for non-size_t alloc variables
for now.
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 | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/t/unit-tests/t-reftable-basics.c b/t/unit-tests/t-reftable-basics.c index 5bf79c9976..990dc1a244 100644 --- a/t/unit-tests/t-reftable-basics.c +++ b/t/unit-tests/t-reftable-basics.c @@ -146,6 +146,32 @@ int cmd_main(int argc UNUSED, const char *argv[] UNUSED) check_int(in, ==, out); } + if_test ("REFTABLE_ALLOC_GROW works") { + int *arr = NULL, *old_arr; + size_t alloc = 0, old_alloc; + + check(!REFTABLE_ALLOC_GROW(arr, 1, alloc)); + check(arr != NULL); + check_uint(alloc, >=, 1); + arr[0] = 42; + + old_alloc = alloc; + old_arr = arr; + reftable_set_alloc(malloc, realloc_stub, free); + check(REFTABLE_ALLOC_GROW(arr, old_alloc + 1, alloc)); + check(arr == old_arr); + check_uint(alloc, ==, old_alloc); + + old_alloc = alloc; + reftable_set_alloc(malloc, realloc, free); + check(!REFTABLE_ALLOC_GROW(arr, old_alloc + 1, alloc)); + check(arr != NULL); + check_uint(alloc, >, old_alloc); + arr[alloc - 1] = 42; + + reftable_free(arr); + } + if_test ("REFTABLE_ALLOC_GROW_OR_NULL works") { int *arr = NULL; size_t alloc = 0, old_alloc; |
