From: Urban Wallasch Date: Sun, 10 Nov 2019 11:33:08 +0000 (+0100) Subject: * tmalloc: fixed and improved realloc() logic; added wipe_on_free setting. X-Git-Url: https://git.packet-gain.de/?a=commitdiff_plain;h=2a949695cfacbdf885415a489c23e74442fac7ad;p=oddbits.git * tmalloc: fixed and improved realloc() logic; added wipe_on_free setting. --- diff --git a/tmalloc/tmalloc.c b/tmalloc/tmalloc.c index d09e4e4..8d4bdd9 100644 --- a/tmalloc/tmalloc.c +++ b/tmalloc/tmalloc.c @@ -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(); diff --git a/tmalloc/tmalloc.h b/tmalloc/tmalloc.h index 72fa2f0..2c404c4 100644 --- a/tmalloc/tmalloc.h +++ b/tmalloc/tmalloc.h @@ -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. diff --git a/tmalloc/tmalloc_test.c b/tmalloc/tmalloc_test.c index 06da94b..56ffe95 100644 --- a/tmalloc/tmalloc_test.c +++ b/tmalloc/tmalloc_test.c @@ -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();