]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Add VALGRIND_RESIZEINPLACE_BLOCK() and hence close #267819.
authorBart Van Assche <bvanassche@acm.org>
Fri, 25 Mar 2011 20:07:25 +0000 (20:07 +0000)
committerBart Van Assche <bvanassche@acm.org>
Fri, 25 Mar 2011 20:07:25 +0000 (20:07 +0000)
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@11666

20 files changed:
coregrind/m_scheduler/scheduler.c
docs/xml/manual-core-adv.xml
drd/drd_clientreq.c
include/valgrind.h
massif/ms_main.c
memcheck/mc_errors.c
memcheck/mc_include.h
memcheck/mc_main.c
memcheck/mc_malloc_wrappers.c
memcheck/tests/badfree-2trace.stderr.exp
memcheck/tests/badfree.stderr.exp
memcheck/tests/badfree3.stderr.exp
memcheck/tests/custom_alloc.c
memcheck/tests/custom_alloc.stderr.exp
memcheck/tests/doublefree.stderr.exp
memcheck/tests/fprw.stderr.exp
memcheck/tests/malloc2.stderr.exp
memcheck/tests/memalign_test.stderr.exp
memcheck/tests/suppfree.stderr.exp
memcheck/tests/xml1.stderr.exp

index fb25c9be8622d9bf7b78ffbd51effa3663095ef9..200adaef1b45f6a1b7beed9a63e97dcd720ef0e3 100644 (file)
@@ -1584,6 +1584,7 @@ void do_client_request ( ThreadId tid )
       }
 
       case VG_USERREQ__MALLOCLIKE_BLOCK:
+      case VG_USERREQ__RESIZEINPLACE_BLOCK:
       case VG_USERREQ__FREELIKE_BLOCK:
          // Ignore them if the addr is NULL;  otherwise pass onto the tool.
          if (!arg[1]) {
index 9eea68c3db3f5e39b6ba591e1db6f214add2bfae..4d00ebfcdaeec6756ddf3902329345fa8b462aaa 100644 (file)
@@ -151,6 +151,15 @@ tool-specific macros).</para>
    </listitem>
   </varlistentry>
 
+  <varlistentry>
+   <term><command><computeroutput>VALGRIND_RESIZEINPLACE_BLOCK</computeroutput>:</command></term>
+   <listitem>
+    <para>Informs a Valgrind tool that the size of an allocated block has been
+    modified but not its address. See <filename>valgrind.h</filename> for
+    more information on how to use it.</para>
+   </listitem>
+  </varlistentry>
+
   <varlistentry>
    <term>
    <command><computeroutput>VALGRIND_CREATE_MEMPOOL</computeroutput></command>,
index 6b63dd904da18c216797c33e1790f8dbb28795b4..ba0a5a4495efdc1a5ddbff46230a38f8d9afc78b 100644 (file)
@@ -97,6 +97,22 @@ static Bool handle_client_request(ThreadId vg_tid, UWord* arg, UWord* ret)
          DRD_(malloclike_block)(vg_tid, arg[1]/*addr*/, arg[2]/*size*/);
       break;
 
+   case VG_USERREQ__RESIZEINPLACE_BLOCK:
+      if (!DRD_(freelike_block)(vg_tid, arg[1]/*addr*/, False))
+      {
+         GenericErrInfo GEI = {
+            .tid = DRD_(thread_get_running_tid)(),
+            .addr = 0,
+         };
+         VG_(maybe_record_error)(vg_tid,
+                                 GenericErr,
+                                 VG_(get_IP)(vg_tid),
+                                 "Invalid VG_USERREQ__RESIZEINPLACE_BLOCK request",
+                                 &GEI);
+      }
+      DRD_(malloclike_block)(vg_tid, arg[1]/*addr*/, arg[3]/*newSize*/);
+      break;
+
    case VG_USERREQ__FREELIKE_BLOCK:
       if (arg[1] && ! DRD_(freelike_block)(vg_tid, arg[1]/*addr*/, False))
       {
index 4843a753ed76dd41924361ed4a6a1591c33c1ffa..75441bcac12d09f3575e71acc586421abf51b116 100644 (file)
@@ -4846,6 +4846,7 @@ typedef
           /* These are useful and can be interpreted by any tool that
              tracks malloc() et al, by using vg_replace_malloc.c. */
           VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
+          VG_USERREQ__RESIZEINPLACE_BLOCK = 0x130b,
           VG_USERREQ__FREELIKE_BLOCK   = 0x1302,
           /* Memory pool support. */
           VG_USERREQ__CREATE_MEMPOOL   = 0x1303,
@@ -5178,7 +5179,24 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
    VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a
    heap block is deallocated.
 
-   In many cases, these two client requests will not be enough to get your
+   VALGRIND_RESIZEINPLACE_BLOCK informs a tool about reallocation. For
+   Memcheck, it does four things:
+
+   - It records that the size of a block has been changed.  This assumes that
+     the block was annotated as having been allocated via
+     VALGRIND_MALLOCLIKE_BLOCK.  Otherwise, an error will be issued.
+
+   - If the block shrunk, it marks the freed memory as being unaddressable.
+
+   - If the block grew, it marks the new area as undefined and defines a red
+     zone past the end of the new block.
+
+   - The V-bits of the overlap between the old and the new block are preserved.
+
+   VALGRIND_RESIZEINPLACE_BLOCK should be put after allocation of the new block
+   and before deallocation of the old block.
+
+   In many cases, these three client requests will not be enough to get your
    allocator working well with Memcheck.  More specifically, if your allocator
    writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call
    will be necessary to mark the memory as addressable just before the zeroing
@@ -5196,9 +5214,6 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
    understand the distinction between the allocator and the rest of the
    program.
 
-   Note: there is currently no VALGRIND_REALLOCLIKE_BLOCK client request;  it
-   has to be emulated with MALLOCLIKE/FREELIKE and memory copying.
-   
    Ignored if addr == 0.
 */
 #define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed)    \
@@ -5208,6 +5223,16 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
                                addr, sizeB, rzB, is_zeroed, 0);   \
    }
 
+/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
+   Ignored if addr == 0.
+*/
+#define VALGRIND_RESIZEINPLACE_BLOCK(addr, oldSizeB, newSizeB, rzB)\
+   {unsigned int _qzz_res;                                        \
+    VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
+                               VG_USERREQ__RESIZEINPLACE_BLOCK,     \
+                               addr, oldSizeB, newSizeB, rzB, 0); \
+   }
+
 /* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
    Ignored if addr == 0.
 */
index ae39b7a5273180b1241011d858f93e03b67dc2ed..67702cda8f728f7d2d51b4be5b5256760d6b7d3f 100644 (file)
@@ -1988,6 +1988,15 @@ static Bool ms_handle_client_request ( ThreadId tid, UWord* argv, UWord* ret )
       *ret = 0;
       return True;
    }
+   case VG_USERREQ__RESIZEINPLACE_BLOCK: {
+      void* p        = (void*)argv[1];
+      SizeT newSizeB =       argv[3];
+
+      unrecord_block(p, /*maybe_snapshot*/True);
+      record_block(tid, p, newSizeB, /*slop_szB*/0,
+                   /*exclude_first_entry*/False, /*maybe_snapshot*/True);
+      return True;
+   }
    case VG_USERREQ__FREELIKE_BLOCK: {
       void* p = (void*)argv[1];
       unrecord_block(p, /*maybe_snapshot*/True);
index 43da9880b418853e2e2cff0c0284ae763ac73607..e09d5147e5af39a867b6e00c449b9428a30ac0ee 100644 (file)
@@ -582,12 +582,13 @@ void MC_(pp_Error) ( Error* err )
       case Err_Free:
          if (xml) {
             emit( "  <kind>InvalidFree</kind>\n" );
-            emit( "  <what>Invalid free() / delete / delete[]</what>\n" );
+            emit( "  <what>Invalid free() / delete / delete[]"
+                  " / realloc()</what>\n" );
             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
             mc_pp_AddrInfo( VG_(get_error_address)(err),
                             &extra->Err.Free.ai, False );
          } else {
-            emit( "Invalid free() / delete / delete[]\n" );
+            emit( "Invalid free() / delete / delete[] / realloc()\n" );
             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
             mc_pp_AddrInfo( VG_(get_error_address)(err),
                             &extra->Err.Free.ai, False );
index c2ef03eb65fa0f5a9658f1ed00118bec2780900a..ece6eac3144c81554877d8a595dd5d6af0697500 100644 (file)
@@ -127,6 +127,9 @@ void  MC_(__builtin_vec_delete) ( ThreadId tid, void* p );
 void* MC_(realloc)              ( ThreadId tid, void* p, SizeT new_size );
 SizeT MC_(malloc_usable_size)   ( ThreadId tid, void* p );
 
+void MC_(handle_resizeInPlace)(ThreadId tid, Addr p,
+                               SizeT oldSizeB, SizeT newSizeB, SizeT rzB);
+
 
 /*------------------------------------------------------------*/
 /*--- Origin tracking translate-time support               ---*/
index f62ad47d1c59c3a30f15799dfd2af50cdd920c32..37735cfe0a48ff3d38ec4f64eca2cfcc97ccb821 100644 (file)
@@ -4987,6 +4987,7 @@ static Bool mc_handle_client_request ( ThreadId tid, UWord* arg, UWord* ret )
 
    if (!VG_IS_TOOL_USERREQ('M','C',arg[0])
        && VG_USERREQ__MALLOCLIKE_BLOCK != arg[0]
+       && VG_USERREQ__RESIZEINPLACE_BLOCK != arg[0]
        && VG_USERREQ__FREELIKE_BLOCK   != arg[0]
        && VG_USERREQ__CREATE_MEMPOOL   != arg[0]
        && VG_USERREQ__DESTROY_MEMPOOL  != arg[0]
@@ -5121,6 +5122,15 @@ static Bool mc_handle_client_request ( ThreadId tid, UWord* arg, UWord* ret )
                           MC_AllocCustom, MC_(malloc_list) );
          return True;
       }
+      case VG_USERREQ__RESIZEINPLACE_BLOCK: {
+         Addr p         = (Addr)arg[1];
+         SizeT oldSizeB =       arg[2];
+         SizeT newSizeB =       arg[3];
+         UInt rzB       =       arg[4];
+
+         MC_(handle_resizeInPlace) ( tid, p, oldSizeB, newSizeB, rzB );
+         return True;
+      }
       case VG_USERREQ__FREELIKE_BLOCK: {
          Addr p         = (Addr)arg[1];
          UInt rzB       =       arg[2];
index 2e8b78103c6d9a73a3b4d1f6e95ab732a4e61ef3..d8f40a869b16329cc6cb2bda3099a8f7a5751890 100644 (file)
@@ -486,6 +486,37 @@ SizeT MC_(malloc_usable_size) ( ThreadId tid, void* p )
    return ( mc ? mc->szB : 0 );
 }
 
+/* This handles the in place resize of a block, as performed by the
+   VALGRIND_RESIZEINPLACE_BLOCK client request.  It is unrelated to,
+   and not used for, handling of the normal libc realloc()
+   function. */
+void MC_(handle_resizeInPlace)(ThreadId tid, Addr p,
+                               SizeT oldSizeB, SizeT newSizeB, SizeT rzB)
+{
+   MC_Chunk* mc = VG_(HT_lookup) ( MC_(malloc_list), (UWord)p );
+   if (!mc || mc->szB != oldSizeB || newSizeB == 0) {
+      /* Reject if: p is not found, or oldSizeB is wrong,
+         or new block would be empty. */
+      MC_(record_free_error) ( tid, p );
+      return;
+   }
+
+   if (oldSizeB == newSizeB)
+      return;
+
+   mc->szB = newSizeB;
+   if (newSizeB < oldSizeB) {
+      MC_(make_mem_noaccess)( p + newSizeB, oldSizeB - newSizeB + rzB );
+   } else {
+      ExeContext* ec  = VG_(record_ExeContext)(tid, 0/*first_ip_delta*/);
+      UInt        ecu = VG_(get_ECU_from_ExeContext)(ec);
+      MC_(make_mem_undefined_w_otag)( p + oldSizeB, newSizeB - oldSizeB,
+                                      ecu | MC_OKIND_HEAP );
+      if (rzB > 0)
+         MC_(make_mem_noaccess)( p + newSizeB, rzB );
+   }
+}
+
 
 /*------------------------------------------------------------*/
 /*--- Memory pool stuff.                                   ---*/
index 5b937c19e9350911d493132f49b4c7e802a41515..a3ea7a413eaaff9c8faa3e1695cfef85f486b270 100644 (file)
@@ -1,9 +1,9 @@
-Invalid free() / delete / delete[]
+Invalid free() / delete / delete[] / realloc()
    at 0x........: free (vg_replace_malloc.c:...)
    by 0x........: main (badfree.c:12)
  Address 0x........ is not stack'd, malloc'd or (recently) free'd
 
-Invalid free() / delete / delete[]
+Invalid free() / delete / delete[] / realloc()
    at 0x........: free (vg_replace_malloc.c:...)
    by 0x........: main (badfree.c:15)
  Address 0x........ is on thread 1's stack
index 5b937c19e9350911d493132f49b4c7e802a41515..a3ea7a413eaaff9c8faa3e1695cfef85f486b270 100644 (file)
@@ -1,9 +1,9 @@
-Invalid free() / delete / delete[]
+Invalid free() / delete / delete[] / realloc()
    at 0x........: free (vg_replace_malloc.c:...)
    by 0x........: main (badfree.c:12)
  Address 0x........ is not stack'd, malloc'd or (recently) free'd
 
-Invalid free() / delete / delete[]
+Invalid free() / delete / delete[] / realloc()
    at 0x........: free (vg_replace_malloc.c:...)
    by 0x........: main (badfree.c:15)
  Address 0x........ is on thread 1's stack
index ca3ecf55e3435d53ee37e44263f743263ac66021..f276c3578a0dff05ed4d56cb489f42e7d4c800d2 100644 (file)
@@ -1,9 +1,9 @@
-Invalid free() / delete / delete[]
+Invalid free() / delete / delete[] / realloc()
    at 0x........: free (coregrind/vg_replace_malloc.c:...)
    by 0x........: main (memcheck/tests/badfree.c:12)
  Address 0x........ is not stack'd, malloc'd or (recently) free'd
 
-Invalid free() / delete / delete[]
+Invalid free() / delete / delete[] / realloc()
    at 0x........: free (coregrind/vg_replace_malloc.c:...)
    by 0x........: main (memcheck/tests/badfree.c:15)
  Address 0x........ is on thread 1's stack
index 9f22851b011bd0a834a32ebafa9e34a3015b0b32..13bf12a2aaa3af5a3b5d5c57dd2d289688f940d4 100644 (file)
@@ -53,7 +53,7 @@ static void custom_free(void* p)
    // don't actually free any memory... but mark it as freed
    VALGRIND_FREELIKE_BLOCK( p, RZ );
 }
-#undef RZ
+
 
 
 
@@ -78,6 +78,23 @@ int main(void)
    array[9]  = 8;
    array[10] = 10;      // invalid write (ok w/o MALLOCLIKE -- in superblock)
 
+   VALGRIND_RESIZEINPLACE_BLOCK(array, sizeof(int) * 10, sizeof(int) * 5, RZ);
+   array[4] = 7;
+   array[5] = 9; // invalid write
+
+   // Make the entire array defined again such that it can be verified whether
+   // the red zone is marked properly when resizing in place.
+   VALGRIND_MAKE_MEM_DEFINED(array, sizeof(int) * 10);
+
+   VALGRIND_RESIZEINPLACE_BLOCK(array, sizeof(int) * 5, sizeof(int) * 7, RZ);
+   if (array[5]) array[4]++; // uninitialized read of array[5]
+   array[5]  = 11;
+   array[6]  = 7;
+   array[7] = 8; // invalid write
+
+   // invalid realloc
+   VALGRIND_RESIZEINPLACE_BLOCK(array+1, sizeof(int) * 7, sizeof(int) * 8, RZ);
+
    custom_free(array);  // ok
 
    custom_free((void*)0x1);  // invalid free
@@ -101,3 +118,5 @@ int main(void)
 
    // leak from make_leak()
 }
+
+#undef RZ
index b3c2b09a326062668fcdeb7579d8495016fb160a..bb55f8c0cfbbdaed3fc50c5d00355fb6f57783df 100644 (file)
@@ -4,21 +4,42 @@ Invalid write of size 4
    at 0x........: custom_alloc (custom_alloc.c:47)
    by 0x........: main (custom_alloc.c:76)
 
-Invalid free() / delete / delete[]
+Invalid write of size 4
+   at 0x........: main (custom_alloc.c:83)
+ Address 0x........ is 0 bytes after a block of size 20 alloc'd
+   at 0x........: custom_alloc (custom_alloc.c:47)
+   by 0x........: main (custom_alloc.c:76)
+
+Conditional jump or move depends on uninitialised value(s)
+   at 0x........: main (custom_alloc.c:90)
+
+Invalid write of size 4
+   at 0x........: main (custom_alloc.c:93)
+ Address 0x........ is 0 bytes after a block of size 28 alloc'd
+   at 0x........: custom_alloc (custom_alloc.c:47)
+   by 0x........: main (custom_alloc.c:76)
+
+Invalid free() / delete / delete[] / realloc()
+   at 0x........: main (custom_alloc.c:96)
+ Address 0x........ is 4 bytes inside a block of size 28 alloc'd
+   at 0x........: custom_alloc (custom_alloc.c:47)
+   by 0x........: main (custom_alloc.c:76)
+
+Invalid free() / delete / delete[] / realloc()
    at 0x........: custom_free (custom_alloc.c:54)
-   by 0x........: main (custom_alloc.c:83)
+   by 0x........: main (custom_alloc.c:100)
  Address 0x........ is not stack'd, malloc'd or (recently) free'd
 
 Mismatched free() / delete / delete []
    at 0x........: custom_free (custom_alloc.c:54)
-   by 0x........: main (custom_alloc.c:86)
+   by 0x........: main (custom_alloc.c:103)
  Address 0x........ is 0 bytes inside a block of size 40 alloc'd
    at 0x........: malloc (vg_replace_malloc.c:...)
-   by 0x........: main (custom_alloc.c:85)
+   by 0x........: main (custom_alloc.c:102)
 
 Invalid read of size 4
-   at 0x........: main (custom_alloc.c:89)
- Address 0x........ is 0 bytes inside a block of size 40 free'd
+   at 0x........: main (custom_alloc.c:106)
+ Address 0x........ is 0 bytes inside a block of size 28 free'd
    at 0x........: custom_free (custom_alloc.c:54)
-   by 0x........: main (custom_alloc.c:81)
+   by 0x........: main (custom_alloc.c:98)
 
index 672eda01bdc86f7f3d7f6fd014da4daebd7c8ca0..9ed5375c72623819106b5d2a3b7abe5903efc1ed 100644 (file)
@@ -1,4 +1,4 @@
-Invalid free() / delete / delete[]
+Invalid free() / delete / delete[] / realloc()
    at 0x........: free (vg_replace_malloc.c:...)
    by 0x........: main (doublefree.c:10)
  Address 0x........ is 0 bytes inside a block of size 177 free'd
index d083387ce63343ba8b9ea673e8e5fa237db1cee7..4719f80b413ab6ede51386e6927f98cb4ea53681 100644 (file)
@@ -28,7 +28,7 @@ Invalid write of size 4
    at 0x........: free (vg_replace_malloc.c:...)
    by 0x........: main (fprw.c:19)
 
-Invalid free() / delete / delete[]
+Invalid free() / delete / delete[] / realloc()
    at 0x........: free (vg_replace_malloc.c:...)
    by 0x........: main (fprw.c:22)
  Address 0x........ is not stack'd, malloc'd or (recently) free'd
index 0c29fa4db268e9317c18aa5992616d446b63288d..7ba0426992b67eea8901d849ecc1031add5e5c09 100644 (file)
@@ -4,7 +4,7 @@ Invalid write of size 1
    at 0x........: free (vg_replace_malloc.c:...)
    by 0x........: main (malloc2.c:38)
 
-Invalid free() / delete / delete[]
+Invalid free() / delete / delete[] / realloc()
    at 0x........: free (vg_replace_malloc.c:...)
    by 0x........: main (malloc2.c:43)
  Address 0x........ is 0 bytes inside a block of size 429 free'd
index 5a01c4ad7f5ca7c4a034d4329581484349b9b518..aa8d5883365bb4c6bedc79a34f0e5221cab980b4 100644 (file)
@@ -1,4 +1,4 @@
-Invalid free() / delete / delete[]
+Invalid free() / delete / delete[] / realloc()
    at 0x........: free (vg_replace_malloc.c:...)
    by 0x........: main (memalign_test.c:25)
  Address 0x........ is 0 bytes inside a block of size 111,110 free'd
index a75d3560423ba11188ce757599f87dc9a995b513..e29d17bfdee9a215d49d51e0b57b96a986789da1 100644 (file)
@@ -1,4 +1,4 @@
-Invalid free() / delete / delete[]
+Invalid free() / delete / delete[] / realloc()
    at 0x........: free (vg_replace_malloc.c:...)
    by 0x........: ddd (suppfree.c:7)
    by 0x........: ccc (suppfree.c:12)
index 8471e5fa918ced5c0bac3aa80ef85f19da15e4e2..b6cb890b26ad0b33fbd06fab4c5c21e317c87c16 100644 (file)
   <unique>0x........</unique>
   <tid>...</tid>
   <kind>InvalidFree</kind>
-  <what>Invalid free() / delete / delete[]</what>
+  <what>Invalid free() / delete / delete[] / realloc()</what>
   <stack>
     <frame>
       <ip>0x........</ip>
   <unique>0x........</unique>
   <tid>...</tid>
   <kind>InvalidFree</kind>
-  <what>Invalid free() / delete / delete[]</what>
+  <what>Invalid free() / delete / delete[] / realloc()</what>
   <stack>
     <frame>
       <ip>0x........</ip>