Check for double free with HEAP_TAG.
authorAdam Green <adamgr@foo.bar>
Tue, 12 Feb 2013 02:50:44 +0000 (18:50 -0800)
committerAdam Green <adamgr@foo.bar>
Tue, 12 Feb 2013 02:50:44 +0000 (18:50 -0800)
If you enable HEAP_TAG, now wraps free() calls to make sure it isn't
already freed and debugbreak()'s if it is.

gcc4mbed/build/gcc4mbed.mk
gcc4mbed/src/gcc4mbed.cpp

index 814b21f..8681d95 100755 (executable)
@@ -173,7 +173,7 @@ endif
 # Setup wraps to memory allocations routines if we want to tag heap allocations.
 HEAP_WRAPS=
 ifeq "$(HEAP_TAGS)" "1"
-HEAP_WRAPS=,--wrap=malloc,--wrap=realloc
+HEAP_WRAPS=,--wrap=malloc,--wrap=realloc,--wrap=free
 DEFINES += -DHEAP_TAGS
 endif
 
index eafd5e4..2377a47 100644 (file)
@@ -174,17 +174,19 @@ extern "C" caddr_t _sbrk(int incr)
 
 
 /* Optional functionality which will tag each heap allocation with the caller's return address. */
-#if HEAP_TAGS
+#ifdef HEAP_TAGS
 
 const unsigned int* __smoothieHeapBase = &__HeapBase;
 
 extern "C" void* __real_malloc(size_t size);
 extern "C" void* __real_realloc(void* ptr, size_t size);
+extern "C" void  __real_free(void* ptr);
 
 static void setTag(void* pv, unsigned int tag);
 static unsigned int* footerForChunk(void* pv);
 static unsigned int* headerForChunk(void* pv);
 static unsigned int sizeOfChunk(unsigned int* pHeader);
+static int isChunkInUse(void* pv);
 
 extern "C" __attribute__((naked)) void __wrap_malloc(size_t size)
 {
@@ -250,6 +252,19 @@ extern "C" void* reallocWithTag(void* ptr, size_t size, unsigned int tag)
     return p;
 }
 
+extern "C" void __wrap_free(void* ptr)
+{
+    if (!isChunkInUse(ptr))
+        __debugbreak();
+    __real_free(ptr);
+}
+
+static int isChunkInUse(void* pv)
+{
+    unsigned int* pFooter = footerForChunk(pv);
+    return pFooter[1] & 1;
+}
+
 __attribute__((naked)) void* operator new(size_t size)
 {
     __asm (
@@ -263,6 +278,8 @@ __attribute__((naked)) void* operator new(size_t size)
         "1$:\n"
         "pop {r4,pc}\n"
     );
+    // This line never executes but silences no return value warning from compiler.
+    return (void*)1;
 }
 
 #endif // HEAP_TAGS