From c2bfdc506c3aeec52e4495d3985d48c76a1d4ec8 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 24 Jul 2003 17:39:59 +0000 Subject: [PATCH] Changed the behaviour of realloc() in Memcheck, Addrcheck and Helgrind. Previously, when realloc() was asked to make a block bigger, the ExeContext describing where that block was allocated was increased; however, if the block became smaller or stayed the same size, the original ExeContext remained. This is correct in one way (that's where the memory manager actually parcelled out the block) but it's not very intuitive. This commit changes things so the ExeContext of a block is always changed upon realloc(). I added a regression test for it too. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1783 --- helgrind/hg_main.c | 2 ++ memcheck/mac_malloc_wrappers.c | 2 ++ memcheck/tests/Makefile.am | 4 +++- memcheck/tests/realloc3.c | 28 ++++++++++++++++++++++++++++ memcheck/tests/realloc3.stderr.exp | 29 +++++++++++++++++++++++++++++ memcheck/tests/realloc3.vgtest | 2 ++ 6 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 memcheck/tests/realloc3.c create mode 100644 memcheck/tests/realloc3.stderr.exp create mode 100644 memcheck/tests/realloc3.vgtest diff --git a/helgrind/hg_main.c b/helgrind/hg_main.c index d95173e41..9a03ca402 100644 --- a/helgrind/hg_main.c +++ b/helgrind/hg_main.c @@ -1965,11 +1965,13 @@ void* SK_(realloc) ( void* p, Int new_size ) if (hc->size == new_size) { /* size unchanged */ + hc->where = VG_(get_ExeContext)(tid); return p; } else if (hc->size > new_size) { /* new size is smaller */ hc->size = new_size; + hc->where = VG_(get_ExeContext)(tid); return p; } else { diff --git a/memcheck/mac_malloc_wrappers.c b/memcheck/mac_malloc_wrappers.c index 879bffd3b..536cc2e12 100644 --- a/memcheck/mac_malloc_wrappers.c +++ b/memcheck/mac_malloc_wrappers.c @@ -354,6 +354,7 @@ void* SK_(realloc) ( void* p, Int new_size ) if (mc->size == new_size) { /* size unchanged */ + mc->where = VG_(get_ExeContext)(tid); VGP_POPCC(VgpCliMalloc); return p; @@ -361,6 +362,7 @@ void* SK_(realloc) ( void* p, Int new_size ) /* new size is smaller */ MAC_(die_mem_heap)( mc->data+new_size, mc->size-new_size ); mc->size = new_size; + mc->where = VG_(get_ExeContext)(tid); VGP_POPCC(VgpCliMalloc); return p; diff --git a/memcheck/tests/Makefile.am b/memcheck/tests/Makefile.am index 86b20a398..4f9dc16aa 100644 --- a/memcheck/tests/Makefile.am +++ b/memcheck/tests/Makefile.am @@ -44,6 +44,7 @@ EXTRA_DIST = $(noinst_SCRIPTS) \ pushfpopf.stderr.exp pushfpopf.stdout.exp pushfpopf.vgtest \ realloc1.stderr.exp realloc1.vgtest \ realloc2.stderr.exp realloc2.vgtest \ + realloc3.stderr.exp realloc3.vgtest \ sigaltstack.stderr.exp sigaltstack.vgtest \ signal2.stderr.exp \ signal2.stdout.exp signal2.vgtest \ @@ -64,7 +65,7 @@ check_PROGRAMS = \ malloc1 malloc2 malloc3 manuel1 manuel2 manuel3 \ memalign_test memcmptest mmaptest nanoleak null_socket \ overlap pushfpopf \ - realloc1 realloc2 sigaltstack signal2 supp1 supp2 suppfree \ + realloc1 realloc2 realloc3 sigaltstack signal2 supp1 supp2 suppfree \ trivialleak tronical weirdioctl \ mismatches new_override metadata threadederrno @@ -103,6 +104,7 @@ overlap_SOURCES = overlap.c pushfpopf_SOURCES = pushfpopf_c.c pushfpopf_s.s realloc1_SOURCES = realloc1.c realloc2_SOURCES = realloc2.c +realloc3_SOURCES = realloc3.c signal2_SOURCES = signal2.c supp1_SOURCES = supp.c supp2_SOURCES = supp.c diff --git a/memcheck/tests/realloc3.c b/memcheck/tests/realloc3.c new file mode 100644 index 000000000..0c6a5f8a0 --- /dev/null +++ b/memcheck/tests/realloc3.c @@ -0,0 +1,28 @@ +/* For a long time (from Valgrind 1.0 to 1.9.6, AFAICT) when realloc() was + called and made a block smaller, or didn't change its size, the + ExeContext of the block was not updated; therefore any errors that + referred to it would state that it was allocated not by the realloc(), + but by the previous malloc() or whatever. While this is true in one + sense, it is misleading and not what you'd expect. This test + demonstrates this -- 'x' and 'y' are unchanged and shrunk, and their + ExeContexts should be updated upon their realloc(). I hope that's clear. +*/ +#include + +int main(void) +{ + int* x = malloc(5); + int* y = malloc(10); + int* z = malloc(2); + int a, b, c; + + x = realloc(x, 5); // same size + y = realloc(y, 5); // make smaller + z = realloc(z, 5); // make bigger + + a = (x[5] == 0xdeadbeef ? 1 : 0); + b = (y[5] == 0xdeadbeef ? 1 : 0); + c = (z[5] == 0xdeadbeef ? 1 : 0); + + return a + b + c; +} diff --git a/memcheck/tests/realloc3.stderr.exp b/memcheck/tests/realloc3.stderr.exp new file mode 100644 index 000000000..67041889c --- /dev/null +++ b/memcheck/tests/realloc3.stderr.exp @@ -0,0 +1,29 @@ +Invalid read of size 4 + at 0x........: main (realloc3.c:23) + by 0x........: __libc_start_main (...libc...) + by 0x........: ... + Address 0x........ is 15 bytes after a block of size 5 alloc'd + at 0x........: realloc (vg_replace_malloc.c:...) + by 0x........: main (realloc3.c:19) + by 0x........: __libc_start_main (...libc...) + by 0x........: ... + +Invalid read of size 4 + at 0x........: main (realloc3.c:24) + by 0x........: __libc_start_main (...libc...) + by 0x........: ... + Address 0x........ is 15 bytes after a block of size 5 alloc'd + at 0x........: realloc (vg_replace_malloc.c:...) + by 0x........: main (realloc3.c:20) + by 0x........: __libc_start_main (...libc...) + by 0x........: ... + +Invalid read of size 4 + at 0x........: main (realloc3.c:25) + by 0x........: __libc_start_main (...libc...) + by 0x........: ... + Address 0x........ is 15 bytes after a block of size 5 alloc'd + at 0x........: realloc (vg_replace_malloc.c:...) + by 0x........: main (realloc3.c:21) + by 0x........: __libc_start_main (...libc...) + by 0x........: ... diff --git a/memcheck/tests/realloc3.vgtest b/memcheck/tests/realloc3.vgtest new file mode 100644 index 000000000..ff295abac --- /dev/null +++ b/memcheck/tests/realloc3.vgtest @@ -0,0 +1,2 @@ +prog: realloc3 +vgopts: -q