Add a new heuristic 'length64' to detect interior pointers
pointing at offset 64bit of a block, when the first 8 bytes contains
the block size - 8. This is e.g. used by sqlite3MemMalloc.

Patch by Matthias Schwarzott (with small modif)



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@14179 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/memcheck/mc_leakcheck.c b/memcheck/mc_leakcheck.c
index 670d89f..cb8abd1 100644
--- a/memcheck/mc_leakcheck.c
+++ b/memcheck/mc_leakcheck.c
@@ -594,6 +594,7 @@
    switch(h) {
    case LchNone:                return "none";
    case LchStdString:           return "stdstring";
+   case LchLength64:            return "length64";
    case LchNewArray:            return "newarray";
    case LchMultipleInheritance: return "multipleinheritance";
    default:                     return "???invalid heuristic???";
@@ -672,6 +673,16 @@
    return False;
 }
 
+// true if a is properly aligned and points to 64bits of valid memory
+static Bool is_valid_aligned_ULong ( Addr a )
+{
+   if (sizeof(Word) == 8)
+      return MC_(is_valid_aligned_word)(a);
+
+   return MC_(is_valid_aligned_word)(a)
+      && MC_(is_valid_aligned_word)(a + 4);
+}
+
 // If ch is heuristically reachable via an heuristic member of heur_set,
 // returns this heuristic.
 // If ch cannot be considered reachable using one of these heuristics,
@@ -712,6 +723,23 @@
       }
    }
 
+   if (HiS(LchLength64, heur_set)) {
+      // Detects inner pointers that point at 64bit offset (8 bytes) into a
+      // block following the length of the remaining as 64bit number 
+      // (=total block size - 8).
+      // This is used e.g. by sqlite for tracking the total size of allocated
+      // memory.
+      // Note that on 64bit platforms, a block matching LchLength64 will
+      // also be matched by LchNewArray.
+      if ( ptr == ch->data + sizeof(ULong)
+          && is_valid_aligned_ULong(ch->data)) {
+         const ULong size = *((ULong*)ch->data);
+         if (size > 0 && (ch->szB - sizeof(ULong)) == size) {
+            return LchLength64;
+         }
+      }
+   }
+
    if (HiS(LchNewArray, heur_set)) {
       // Detects inner pointers at second word of new[] array, following
       // a plausible nr of elements.
@@ -1058,7 +1086,7 @@
                   MC_(pp_describe_addr) (ptr);
                   if (lc_is_a_chunk_ptr(addr, &ch_no, &ch, &ex) ) {
                      Int h;
-                     for (h = LchStdString; h <= LchMultipleInheritance; h++) {
+                     for (h = LchStdString; h < N_LEAK_CHECK_HEURISTICS; h++) {
                         if (heuristic_reachedness(addr, ch, ex, H2S(h)) == h) {
                            VG_(umsg)("block at %#lx considered reachable "
                                      "by ptr %#lx using %s heuristic\n",