From: Paul Floyd Date: Sun, 8 Feb 2026 16:57:30 +0000 (+0100) Subject: FreeBSD reallocarray: behaves like realloc on allocation failure X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b9e64b56cd6069ab0d47325e3353075f72d66215;p=thirdparty%2Fvalgrind.git FreeBSD reallocarray: behaves like realloc on allocation failure It was behaving like reallocf which frees the ptr if the allocation fails. That's wrong, it behaves like realloc which does not free ptr. Updated the one regression test. I also noticed that the error message always mentions realloc even for reallocf and reallocarray. --- diff --git a/coregrind/m_replacemalloc/vg_replace_malloc.c b/coregrind/m_replacemalloc/vg_replace_malloc.c index 12b01f678..5672eda09 100644 --- a/coregrind/m_replacemalloc/vg_replace_malloc.c +++ b/coregrind/m_replacemalloc/vg_replace_malloc.c @@ -1729,7 +1729,6 @@ extern int * __error(void) __attribute__((weak)); MALLOC_TRACE(" = %p\n", v ); \ if (v == NULL) { \ if (!(size*nmemb == 0U && info.clo_realloc_zero_bytes_frees == True)) {\ - VG_REPLACE_FUNCTION_EZU(10050,VG_Z_LIBC_SONAME,free)(ptrV); \ SET_ERRNO_ENOMEM; \ } \ } \ diff --git a/memcheck/tests/amd64-freebsd/reallocarray.c b/memcheck/tests/amd64-freebsd/reallocarray.c index ee3a94d87..24ed47072 100644 --- a/memcheck/tests/amd64-freebsd/reallocarray.c +++ b/memcheck/tests/amd64-freebsd/reallocarray.c @@ -2,29 +2,46 @@ #include #include #include +#include #include "../../memcheck.h" int main(void) { int *pi = NULL; + int *newpi; VALGRIND_DO_LEAK_CHECK; + /* should succeed */ pi = reallocarray(pi, 10U, sizeof(int)); + assert(pi); + fprintf(stderr, "Added leak check, expect 40 bytes still reachable\n"); VALGRIND_DO_ADDED_LEAK_CHECK; + /* on FreeBSD this does not free pi */ pi = reallocarray(pi, 0U, sizeof(int)); + assert(pi); + fprintf(stderr, "Added leak check, expect 1 byte still reachable\n"); VALGRIND_DO_ADDED_LEAK_CHECK; pi = reallocarray(pi, 10U, 0U); + assert(pi); free(pi); + fprintf(stderr, "Added leak check, expect all blocks freed\n"); VALGRIND_DO_CHANGED_LEAK_CHECK; pi = NULL; pi = reallocarray(pi, 10U, sizeof(int)); + assert(pi); + fprintf(stderr, "Added leak check, expect 40 bytes still reachable\n"); VALGRIND_DO_ADDED_LEAK_CHECK; errno = 0; - pi = reallocarray(pi, 1UL << 49, 1U); - assert(!pi); + /* this will fail in the mallloc lib, not enough memory */ + newpi = reallocarray(pi, 1UL << 49, 1U); + assert(!newpi); assert(errno == ENOMEM); + fprintf(stderr, "Added leak check, expect 40 bytes still reachable\n"); VALGRIND_DO_CHANGED_LEAK_CHECK; - pi = reallocarray(pi, SIZE_MAX/1000U, SIZE_MAX/1000U); - assert(!pi); + /* this will fail the reallocarray precondition */ + newpi = reallocarray(pi, SIZE_MAX/1000U, SIZE_MAX/1000U); + assert(!newpi); assert(errno == ENOMEM); + free(pi); + fprintf(stderr, "Added leak check, expect all blocks freed\n"); VALGRIND_DO_CHANGED_LEAK_CHECK; } diff --git a/memcheck/tests/amd64-freebsd/reallocarray.stderr.exp b/memcheck/tests/amd64-freebsd/reallocarray.stderr.exp index 2550709ab..c5dac41c5 100644 --- a/memcheck/tests/amd64-freebsd/reallocarray.stderr.exp +++ b/memcheck/tests/amd64-freebsd/reallocarray.stderr.exp @@ -1,6 +1,7 @@ All heap blocks were freed -- no leaks are possible +Added leak check, expect 40 bytes still reachable LEAK SUMMARY: definitely lost: 0 (+0) bytes in 0 (+0) blocks indirectly lost: 0 (+0) bytes in 0 (+0) blocks @@ -12,11 +13,12 @@ To see them, rerun with: --leak-check=full --show-leak-kinds=all realloc() with size 0 at 0x........: reallocarray (vg_replace_malloc.c:...) - by 0x........: main (reallocarray.c:13) + by 0x........: main (reallocarray.c:19) Address 0x........ is 0 bytes inside a block of size 40 alloc'd at 0x........: reallocarray (vg_replace_malloc.c:...) - by 0x........: main (reallocarray.c:11) + by 0x........: main (reallocarray.c:14) +Added leak check, expect 1 byte still reachable LEAK SUMMARY: definitely lost: 0 (+0) bytes in 0 (+0) blocks indirectly lost: 0 (+0) bytes in 0 (+0) blocks @@ -28,13 +30,15 @@ To see them, rerun with: --leak-check=full --show-leak-kinds=all realloc() with size 0 at 0x........: reallocarray (vg_replace_malloc.c:...) - by 0x........: main (reallocarray.c:15) + by 0x........: main (reallocarray.c:23) Address 0x........ is 0 bytes inside a block of size 1 alloc'd at 0x........: reallocarray (vg_replace_malloc.c:...) - by 0x........: main (reallocarray.c:13) + by 0x........: main (reallocarray.c:19) +Added leak check, expect all blocks freed All heap blocks were freed -- no leaks are possible +Added leak check, expect 40 bytes still reachable LEAK SUMMARY: definitely lost: 0 (+0) bytes in 0 (+0) blocks indirectly lost: 0 (+0) bytes in 0 (+0) blocks @@ -44,8 +48,17 @@ LEAK SUMMARY: Reachable blocks (those to which a pointer was found) are not shown. To see them, rerun with: --leak-check=full --show-leak-kinds=all -All heap blocks were freed -- no leaks are possible +Added leak check, expect 40 bytes still reachable +LEAK SUMMARY: + definitely lost: 0 (+0) bytes in 0 (+0) blocks + indirectly lost: 0 (+0) bytes in 0 (+0) blocks + possibly lost: 0 (+0) bytes in 0 (+0) blocks + still reachable: 40 (+0) bytes in 1 (+0) blocks + suppressed: 0 (+0) bytes in 0 (+0) blocks +Reachable blocks (those to which a pointer was found) are not shown. +To see them, rerun with: --leak-check=full --show-leak-kinds=all +Added leak check, expect all blocks freed All heap blocks were freed -- no leaks are possible