* tmalloc: fixed and improved realloc() logic; added wipe_on_free setting.
authorUrban Wallasch <urban.wallasch@freenet.de>
Sun, 10 Nov 2019 11:33:08 +0000 (12:33 +0100)
committerUrban Wallasch <urban.wallasch@freenet.de>
Sun, 10 Nov 2019 11:33:08 +0000 (12:33 +0100)
tmalloc/tmalloc.c
tmalloc/tmalloc.h
tmalloc/tmalloc_test.c

index d09e4e4259a07158d344ecdfae9f4243ec03ecae..8d4bdd9062da490db6968337f9a8db43a69b8b76 100644 (file)
@@ -50,6 +50,7 @@ extern void *__libc_free(void *ptr);
 static int tmalloc_log_fd = STDERR_FILENO;
 static int tmalloc_log_level = TM_LOG_TRACE;
 static int tmalloc_abort_on_error = 0;
+static int tmalloc_wipe_on_free = 0;
 
 static uint64_t tm_sentinel = 0x5a5a5a5a5a5a5a5aULL;
 #define TM_SENTSZ  (sizeof tm_sentinel)
@@ -130,8 +131,12 @@ static inline void log_xdump(const void *s, size_t n) {
  * Called when a serious error is encountered:
  */
 
+static inline void tm_ht_dump(void);
+
 static inline void tm_panic(void) {
     if (tmalloc_abort_on_error) {
+        if (tmalloc_log_level >= TM_LOG_INFO)
+            tm_ht_dump();
         log_str("Aborting.\n");
         abort();
     }
@@ -235,6 +240,28 @@ static inline int tm_ht_check_entry(struct tm_info_struct *p) {
     return res;
 }
 
+static inline int tm_ht_update(void *addr, size_t size,
+                               void *raddr, size_t rsize, void *caller) {
+    struct tm_info_struct *p;
+    uint32_t h;
+
+    h = tm_hash((uint64_t)addr);
+    for (p = tm_htab[h]; p; p = p->next) {
+        if (p->addr == addr) {
+            p->size = size;
+            p->raddr = raddr;
+            p->rsize = rsize;
+            p->caller = caller;
+            return 0;
+        }
+    }
+    log_str(TM_LOG_PFX"ERROR: attempt to update block at ");
+    log_hex((uint64_t)addr);
+    log_str(", not listed as allocated!\n");
+    tm_panic();
+    return -1;
+}
+
 static inline int tm_ht_remove(void *addr, int wipe) {
     struct tm_info_struct *p, *prev = NULL;
     uint32_t h;
@@ -389,16 +416,22 @@ void *calloc(size_t nmemb, size_t size) {
 void *realloc(void *ptr, size_t size) {
     void *caller = ret_address(0);
     void *addr;
+    void *oaddr = ptr ? ptr - TM_SENTSZ : NULL;
     size_t xsize = size + (TM_SENTSZ * 2);
 
     TM_HT_LOCK();
-    tm_ht_check(ptr);
-    addr = __libc_realloc(ptr - TM_SENTSZ, xsize);
+    addr = __libc_realloc(oaddr, xsize);
     if (addr) {
-        tm_ht_remove(ptr, 0);
-        memcpy(addr, &tm_sentinel, TM_SENTSZ);
+        if (addr == oaddr) {
+            tm_ht_update(ptr, size, addr, xsize, caller);
+        }
+        else {
+            if (ptr)
+                tm_ht_remove(ptr, 0);
+            tm_ht_insert(addr + TM_SENTSZ, size, addr, xsize, caller);
+            memcpy(addr, &tm_sentinel, TM_SENTSZ);
+        }
         memcpy(addr + xsize - TM_SENTSZ, &tm_sentinel, sizeof tm_sentinel);
-        tm_ht_insert(addr + TM_SENTSZ, size, addr, xsize, caller);
         addr += TM_SENTSZ;
     }
     else if (tmalloc_log_level >= TM_LOG_WARNING) {
@@ -428,7 +461,7 @@ void free(void *ptr) {
     if (ptr) {
         TM_HT_LOCK();
         tm_ht_check(ptr);
-        if (tm_ht_remove(ptr, 1) != 0) {
+        if (tm_ht_remove(ptr, tmalloc_wipe_on_free) != 0) {
             log_str(TM_LOG_PFX"ERROR: possible double free(");
             log_hex((uint64_t)ptr);
             log_str("): *** HEAP IS VERY LIKELY CORRUPT! ***\n");
@@ -460,6 +493,10 @@ void tmalloc_set_abort_on_error(int a) {
     tmalloc_abort_on_error = a;
 }
 
+void tmalloc_set_wipe_on_free(int w) {
+    tmalloc_wipe_on_free = w;
+}
+
 void tmalloc_check(void) {
     TM_HT_LOCK();
     tm_ht_checkall();
index 72fa2f0cc8e6d6e66d988a02e96789c96454837f..2c404c4d10d152b9c1775202d71b0161851191cf 100644 (file)
@@ -45,6 +45,12 @@ extern void tmalloc_set_log_level(int v);
  */
 extern void tmalloc_set_abort_on_error(int a);
 
+/*
+ * Enable or disable wiping of freed blocks.
+ * Default: 0 (do not wipe)
+ */
+void tmalloc_set_wipe_on_free(int w);
+
 /*
  * Check all known allocated blocks for intact sentinel values
  * and report any problems detected.
index 06da94b5272ea773e68056d1799f70076c52db75..56ffe954245856b9968cd8f160485899831ccdbc 100644 (file)
@@ -20,8 +20,9 @@
 #include "tmalloc.h"
 
 int main(void) {
+    tmalloc_set_wipe_on_free(1);
 
-    void *p = malloc(1337);
+    void *p = realloc(NULL, 1337);
     //tmalloc_stat();
     p = realloc(p, 2000);
     //tmalloc_stat();
@@ -54,7 +55,7 @@ int main(void) {
     free(q);
     //tmalloc_stat();
     fputs( "-----\n", stderr );
-    fputs( "Deliberate out of bounds access:\n", stderr );
+    fputs( "Deliberate out of bounds write:\n", stderr );
     *(s-1) = '#';
     *(s+44) = '+';
     tmalloc_check();