From: Paul Floyd Date: Sat, 11 Jan 2025 16:39:44 +0000 (+0100) Subject: Bug 233298 - Reflect MEMPOOL_FREE in heap summary X-Git-Tag: VALGRIND_3_27_0~160 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=f31d2dbe3fffad8501fd1ae44d3224535b29ad2d;p=thirdparty%2Fvalgrind.git Bug 233298 - Reflect MEMPOOL_FREE in heap summary There was one missing free increment for autoref pools. Also added testcases based on memcheck mempool2 and leak-autorefpool. Original patch contributed by 8dcc <8dcc.git@gmail.com> This is an update on a patch from 2010: https://bugsfiles.kde.org/attachment.cgi?id=42491 --- diff --git a/NEWS b/NEWS index 24a34af19..de11c3c0f 100644 --- a/NEWS +++ b/NEWS @@ -51,6 +51,7 @@ are not entered into bugzilla tend to get forgotten about or ignored. 126256 (fnop) vex x86->IR: unhandled instruction bytes: 0xD9 0xD0 0x31 0xC0 228343 none/tests/darwin/bug228343 fails on OS X +233298 MEMPOOL_FREE not reflected in heap summary 253436 vex amd64->IR: unhandled instruction bytes: 0xF2 0xA6 (repne cmps) 258140 Valgrind on OS X always reports some memory "still reachable" 413369 unhandled amd64-darwin syscall: unix:151 (getpgid) diff --git a/memcheck/mc_malloc_wrappers.c b/memcheck/mc_malloc_wrappers.c index ae50923c4..737837dbb 100644 --- a/memcheck/mc_malloc_wrappers.c +++ b/memcheck/mc_malloc_wrappers.c @@ -782,6 +782,7 @@ static void free_mallocs_in_mempool_block (MC_Mempool* mp, VG_(HT_remove_at_Iter)(MC_(malloc_list)); die_and_free_mem(tid, mc, mp->rzB); + cmalloc_n_frees++; } } } @@ -1014,6 +1015,7 @@ void MC_(mempool_free)(Addr pool, Addr addr) die_and_free_mem ( tid, mc, mp->rzB ); if (MP_DETAILED_SANITY_CHECKS) check_mempool_sane(mp); + cmalloc_n_frees++; } @@ -1073,10 +1075,11 @@ void MC_(mempool_trim)(Addr pool, Addr addr, SizeT szB) MC_(record_free_error)(tid, (Addr)mc->data); VG_(free)(chunks); if (MP_DETAILED_SANITY_CHECKS) check_mempool_sane(mp); + cmalloc_n_frees++; return; } die_and_free_mem ( tid, mc, mp->rzB ); - + cmalloc_n_frees++; } else { /* The current chunk intersects the trim extent: remove, @@ -1088,6 +1091,7 @@ void MC_(mempool_trim)(Addr pool, Addr addr, SizeT szB) MC_(record_free_error)(tid, (Addr)mc->data); VG_(free)(chunks); if (MP_DETAILED_SANITY_CHECKS) check_mempool_sane(mp); + cmalloc_n_frees++; return; } @@ -1122,6 +1126,7 @@ void MC_(mempool_trim)(Addr pool, Addr addr, SizeT szB) mc->data = lo; mc->szB = (UInt) (hi - lo); VG_(HT_add_node)( mp->chunks, mc ); + cmalloc_n_frees++; } #undef EXTENT_CONTAINS diff --git a/memcheck/tests/freebsd/Makefile.am b/memcheck/tests/freebsd/Makefile.am index 96c57e21e..9b67fb299 100644 --- a/memcheck/tests/freebsd/Makefile.am +++ b/memcheck/tests/freebsd/Makefile.am @@ -4,7 +4,7 @@ include $(top_srcdir)/Makefile.tool-tests.am dist_noinst_SCRIPTS = filter_stderr filter_pts dump_stdout filter_sigwait \ filter_scalar filter_realpathat filter_fstat filter_eventfd2 \ toucher1 toucher2 filter_getfsstat filter_context filter_frame \ - filter_supp filter_kenv + filter_supp filter_kenv filter_heap_usage EXTRA_DIST = \ access.vgtest \ @@ -18,6 +18,8 @@ EXTRA_DIST = \ aligned_allocs_supp.vgtest \ aligned_allocs_supp.stderr.exp \ aligned_allocs_supp.supp \ + bug233298.vgtest \ + bug233298.stderr.exp \ bug464476.vgtest \ bug464476.stdout.exp \ bug464476_abs_symlink.vgtest \ @@ -73,6 +75,8 @@ EXTRA_DIST = \ kqueue.stdout.exp \ kqueuex.vgtest \ kqueuex.stdout.exp \ + leak-autofreepool-7.vgtest \ + leak-autofreepool-7.stderr.exp \ linkat.vgtest \ linkat.stderr.exp \ memalign.vgtest memalign.stderr.exp \ diff --git a/memcheck/tests/freebsd/bug233298.stderr.exp b/memcheck/tests/freebsd/bug233298.stderr.exp new file mode 100644 index 000000000..8b6098f15 --- /dev/null +++ b/memcheck/tests/freebsd/bug233298.stderr.exp @@ -0,0 +1 @@ + total heap usage: 6 allocs, 6 frees, XXX bytes allocated diff --git a/memcheck/tests/freebsd/bug233298.vgtest b/memcheck/tests/freebsd/bug233298.vgtest new file mode 100644 index 000000000..8de1581f2 --- /dev/null +++ b/memcheck/tests/freebsd/bug233298.vgtest @@ -0,0 +1,3 @@ +prog: ../mempool2 +vgopts: --leak-check=yes +stderr_filter: filter_heap_usage diff --git a/memcheck/tests/freebsd/filter_heap_usage b/memcheck/tests/freebsd/filter_heap_usage new file mode 100755 index 000000000..6a624e564 --- /dev/null +++ b/memcheck/tests/freebsd/filter_heap_usage @@ -0,0 +1,9 @@ +#! /bin/sh + +../filter_stderr "$@" | +grep "total heap usage:" | +gsed 's/ [^ ]* bytes allocated/ XXX bytes allocated/' + + + + diff --git a/memcheck/tests/freebsd/leak-autofreepool-7.stderr.exp b/memcheck/tests/freebsd/leak-autofreepool-7.stderr.exp new file mode 100644 index 000000000..7c0815330 --- /dev/null +++ b/memcheck/tests/freebsd/leak-autofreepool-7.stderr.exp @@ -0,0 +1 @@ + total heap usage: 31 allocs, 31 frees, XXX bytes allocated diff --git a/memcheck/tests/freebsd/leak-autofreepool-7.vgtest b/memcheck/tests/freebsd/leak-autofreepool-7.vgtest new file mode 100644 index 000000000..be624dccd --- /dev/null +++ b/memcheck/tests/freebsd/leak-autofreepool-7.vgtest @@ -0,0 +1,4 @@ +prog: ../leak-autofreepool +vgopts: --leak-check=full +args: 7 +stderr_filter: filter_heap_usage diff --git a/memcheck/tests/leak-autofreepool.c b/memcheck/tests/leak-autofreepool.c index 3bd6e50dc..057a6573b 100644 --- a/memcheck/tests/leak-autofreepool.c +++ b/memcheck/tests/leak-autofreepool.c @@ -53,6 +53,7 @@ static int MetaPoolFlags = 0; static int CleanupBeforeExit = 0; static int GenerateNoise = 0; static int NoiseCounter = 0; +static int CleanupMoreBeforeExit = 0; static struct cell *cells_plain[2 * N]; static struct cell *cells_meta[2 * N]; @@ -192,6 +193,14 @@ static void set_flags ( int n ) GenerateNoise = 1; break; + // Same as case 2, but enable freeing blocks from PlainPool so that + // we can check that malloc count == free count + case 7: + MetaPoolFlags = VALGRIND_MEMPOOL_METAPOOL | VALGRIND_MEMPOOL_AUTO_FREE; + CleanupBeforeExit = 1; + CleanupMoreBeforeExit = 1; + break; + default: assert(0); } @@ -255,8 +264,10 @@ int main( int argc, char** argv ) } // Leak the memory from the pools by losing the pointers. - for (i = 0; i < N; ++i) { - cells_plain[i] = NULL; + if (!CleanupMoreBeforeExit) { + for (i = 0; i < N; ++i) { + cells_plain[i] = NULL; + } } for (i = 0; i < 2 * N; ++i) { @@ -284,6 +295,11 @@ int main( int argc, char** argv ) } // Cleanup. + if (CleanupMoreBeforeExit) { + for (i = 0; i < N; ++i) { + VALGRIND_MEMPOOL_FREE(PlainPool, cells_plain[i]); + } + } VALGRIND_DESTROY_MEMPOOL(PlainPool); if (GenerateNoise) diff --git a/memcheck/tests/mempool2.c b/memcheck/tests/mempool2.c index 4c8683c22..7408d122a 100644 --- a/memcheck/tests/mempool2.c +++ b/memcheck/tests/mempool2.c @@ -182,6 +182,8 @@ void test(void) res += superblock[29]; // invalid res += superblock[40]; // invalid + VALGRIND_MEMPOOL_FREE(superblock, superblock+30); + VALGRIND_DESTROY_MEMPOOL(superblock); } // claim res is used, so gcc can't nuke this all diff --git a/memcheck/tests/mempool2.stderr.exp b/memcheck/tests/mempool2.stderr.exp index 8dda2cecb..6c6cc7233 100644 --- a/memcheck/tests/mempool2.stderr.exp +++ b/memcheck/tests/mempool2.stderr.exp @@ -3,119 +3,119 @@ Invalid read of size 1 at 0x........: test (mempool2.c:135) - by 0x........: main (mempool2.c:200) + by 0x........: main (mempool2.c:202) Address 0x........ is 1 bytes before a block of size 10 client-defined at 0x........: allocate (mempool2.c:108) by 0x........: test (mempool2.c:130) - by 0x........: main (mempool2.c:200) + by 0x........: main (mempool2.c:202) Invalid read of size 1 at 0x........: test (mempool2.c:136) - by 0x........: main (mempool2.c:200) + by 0x........: main (mempool2.c:202) Address 0x........ is 0 bytes after a block of size 10 client-defined at 0x........: allocate (mempool2.c:108) by 0x........: test (mempool2.c:130) - by 0x........: main (mempool2.c:200) + by 0x........: main (mempool2.c:202) ------ out of range reads in mmap-backed pool ------ Invalid read of size 1 at 0x........: test (mempool2.c:140) - by 0x........: main (mempool2.c:200) + by 0x........: main (mempool2.c:202) Address 0x........ is 1 bytes before a block of size 20 client-defined at 0x........: allocate (mempool2.c:108) by 0x........: test (mempool2.c:131) - by 0x........: main (mempool2.c:200) + by 0x........: main (mempool2.c:202) Invalid read of size 1 at 0x........: test (mempool2.c:141) - by 0x........: main (mempool2.c:200) + by 0x........: main (mempool2.c:202) Address 0x........ is 0 bytes after a block of size 20 client-defined at 0x........: allocate (mempool2.c:108) by 0x........: test (mempool2.c:131) - by 0x........: main (mempool2.c:200) + by 0x........: main (mempool2.c:202) ------ Illegal memory pool address ------ Illegal memory pool address at 0x........: test (mempool2.c:145) - by 0x........: main (mempool2.c:200) + by 0x........: main (mempool2.c:202) Address 0x........ is 0 bytes inside a block of size 32 alloc'd at 0x........: malloc (vg_replace_malloc.c:...) by 0x........: make_pool (mempool2.c:46) by 0x........: test (mempool2.c:122) - by 0x........: main (mempool2.c:200) + by 0x........: main (mempool2.c:202) ------ read free in malloc-backed pool ------ Invalid read of size 1 at 0x........: test (mempool2.c:150) - by 0x........: main (mempool2.c:200) + by 0x........: main (mempool2.c:202) Address 0x........ is 13 bytes inside a recently re-allocated block of size 100,000 alloc'd at 0x........: malloc (vg_replace_malloc.c:...) by 0x........: make_pool (mempool2.c:47) by 0x........: test (mempool2.c:122) - by 0x........: main (mempool2.c:200) + by 0x........: main (mempool2.c:202) ------ read free in mmap-backed pool ------ Invalid read of size 1 at 0x........: test (mempool2.c:155) - by 0x........: main (mempool2.c:200) + by 0x........: main (mempool2.c:202) Address 0x........ is 11 bytes inside a block of size 20 free'd at 0x........: test (mempool2.c:154) - by 0x........: main (mempool2.c:200) + by 0x........: main (mempool2.c:202) Block was alloc'd at at 0x........: allocate (mempool2.c:108) by 0x........: test (mempool2.c:131) - by 0x........: main (mempool2.c:200) + by 0x........: main (mempool2.c:202) ------ double free in malloc-backed pool ------ Invalid free() / delete / delete[] / realloc() at 0x........: test (mempool2.c:159) - by 0x........: main (mempool2.c:200) + by 0x........: main (mempool2.c:202) Address 0x........ is 8 bytes inside a recently re-allocated block of size 100,000 alloc'd at 0x........: malloc (vg_replace_malloc.c:...) by 0x........: make_pool (mempool2.c:47) by 0x........: test (mempool2.c:122) - by 0x........: main (mempool2.c:200) + by 0x........: main (mempool2.c:202) ------ double free in mmap-backed pool ------ Invalid free() / delete / delete[] / realloc() at 0x........: test (mempool2.c:163) - by 0x........: main (mempool2.c:200) + by 0x........: main (mempool2.c:202) Address 0x........ is 0 bytes inside a block of size 20 free'd at 0x........: test (mempool2.c:154) - by 0x........: main (mempool2.c:200) + by 0x........: main (mempool2.c:202) Block was alloc'd at at 0x........: allocate (mempool2.c:108) by 0x........: test (mempool2.c:131) - by 0x........: main (mempool2.c:200) + by 0x........: main (mempool2.c:202) ------ 2 invalid access in 'no no-access superblock' --- Invalid read of size 1 at 0x........: test (mempool2.c:182) - by 0x........: main (mempool2.c:200) + by 0x........: main (mempool2.c:202) Address 0x........ is 1 bytes before a block of size 10 client-defined at 0x........: test (mempool2.c:175) - by 0x........: main (mempool2.c:200) + by 0x........: main (mempool2.c:202) Invalid read of size 1 at 0x........: test (mempool2.c:183) - by 0x........: main (mempool2.c:200) + by 0x........: main (mempool2.c:202) Address 0x........ is 0 bytes after a block of size 10 client-defined at 0x........: test (mempool2.c:175) - by 0x........: main (mempool2.c:200) + by 0x........: main (mempool2.c:202) ------ done ------