]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Change memcheck's (client) realloc implementation so that it copies
authorJulian Seward <jseward@acm.org>
Tue, 22 Jul 2008 18:23:16 +0000 (18:23 +0000)
committerJulian Seward <jseward@acm.org>
Tue, 22 Jul 2008 18:23:16 +0000 (18:23 +0000)
and moves the block even when the new size is smaller or the same.
This increases the chance that it can detect buggy code which assumes
that realloc-smaller doesn't cause the block to move.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@8454

memcheck/mc_malloc_wrappers.c

index 8ccbbc3bfe25a49655ae828e426a0499ca32dd53..cfc1e57ac57fabd79d08cf05b4c5f6a9d7c1869e 100644 (file)
@@ -372,24 +372,45 @@ void* MC_(realloc) ( ThreadId tid, void* p_old, SizeT new_szB )
 
    old_szB = mc->szB;
 
-   if (old_szB == new_szB) {
-      /* size unchanged */
-      mc->where = VG_(record_ExeContext)(tid, 0/*first_ip_delta*/);
-      p_new = p_old;
-      
-   } else if (old_szB > new_szB) {
-      /* new size is smaller */
-      MC_(make_mem_noaccess)( mc->data+new_szB, mc->szB-new_szB );
-      mc->szB = new_szB;
-      mc->where = VG_(record_ExeContext)(tid, 0/*first_ip_delta*/);
-      p_new = p_old;
-      /* Possibly fill freed area with specified junk. */
-      if (MC_(clo_free_fill) != -1) {
-         tl_assert(MC_(clo_free_fill) >= 0x00 && MC_(clo_free_fill) <= 0xFF);
-         VG_(memset)((void*)(mc->data+new_szB), MC_(clo_free_fill), 
-                                                old_szB-new_szB);
+   if (new_szB <= old_szB) {
+      /* new size is smaller or the same */
+      Addr a_new; 
+      /* Get new memory */
+      a_new = (Addr)VG_(cli_malloc)(VG_(clo_alignment), new_szB);
+
+      if (a_new) {
+         ExeContext* ec;
+
+         ec = VG_(record_ExeContext)(tid, 0/*first_ip_delta*/);
+         tl_assert(ec);
+
+         /* Retained part is copied, red zones set as normal */
+         MC_(make_mem_noaccess)( a_new-MC_MALLOC_REDZONE_SZB, 
+                                 MC_MALLOC_REDZONE_SZB );
+         MC_(copy_address_range_state) ( (Addr)p_old, a_new, new_szB );
+         MC_(make_mem_noaccess)        ( a_new+new_szB, MC_MALLOC_REDZONE_SZB );
+
+         /* Copy from old to new */
+         VG_(memcpy)((void*)a_new, p_old, new_szB);
+
+         /* Possibly fill freed area with specified junk. */
+         if (MC_(clo_free_fill) != -1) {
+            tl_assert(MC_(clo_free_fill) >= 0x00 && MC_(clo_free_fill) <= 0xFF);
+            VG_(memset)((void*)p_old, MC_(clo_free_fill), old_szB);
+         }
+
+         /* Free old memory */
+         /* Nb: we have to allocate a new MC_Chunk for the new memory rather
+            than recycling the old one, so that any erroneous accesses to the
+            old memory are reported. */
+         die_and_free_mem ( tid, mc, MC_MALLOC_REDZONE_SZB );
+
+         // Allocate a new chunk.
+         mc = create_MC_Chunk( ec, a_new, new_szB, MC_AllocMalloc );
       }
 
+      p_new = (void*)a_new;
+
    } else {
       /* new size is bigger */
       Addr a_new;