diff options
author | Andrea Fioraldi <andreafioraldi@gmail.com> | 2020-02-18 10:42:19 +0100 |
---|---|---|
committer | Andrea Fioraldi <andreafioraldi@gmail.com> | 2020-02-18 10:42:19 +0100 |
commit | 528193e925595f4c12b946561bde26bd0f3b942d (patch) | |
tree | a3b033ff590759339b66b4448b5e77f6a9e7d91f | |
parent | 3e20edf10e5129e990c295b86e14d896c4a3ca48 (diff) | |
download | afl++-528193e925595f4c12b946561bde26bd0f3b942d.tar.gz |
remove heap checks in alloc-inl.h
-rw-r--r-- | include/alloc-inl.h | 431 | ||||
-rw-r--r-- | include/config.h | 6 |
2 files changed, 8 insertions, 429 deletions
diff --git a/include/alloc-inl.h b/include/alloc-inl.h index 26ce7d22..ada08b69 100644 --- a/include/alloc-inl.h +++ b/include/alloc-inl.h @@ -34,14 +34,6 @@ #include "types.h" #include "debug.h" -/* Disable speed hack in debug mode */ - -#ifdef UNSAFE_MEMORY -#ifdef DEBUG_BUILD -#undef UNSAFE_MEMORY -#endif -#endif - /* User-facing macro to sprintf() to a dynamically allocated buffer. */ #define alloc_printf(_str...) \ @@ -75,91 +67,10 @@ \ } while (0) -/* Magic tokens used to mark used / freed chunks. */ - -#define ALLOC_MAGIC_C1 0xFF00FF00 /* Used head (dword) */ -#define ALLOC_MAGIC_F 0xFE00FE00 /* Freed head (dword) */ -#define ALLOC_MAGIC_C2 0xF0 /* Used tail (byte) */ - -/* Positions of guard tokens in relation to the user-visible pointer. */ - -#ifndef UNSAFE_MEMORY -#define ALLOC_C1(_ptr) (((u32*)(_ptr))[-2]) -#define ALLOC_S(_ptr) (((u32*)(_ptr))[-1]) -#define ALLOC_C2(_ptr) (((u8*)(_ptr))[ALLOC_S(_ptr)]) -#else -#define ALLOC_C1(_ptr) (((u32*)(_ptr))[0]) -#define ALLOC_S(_ptr) (((u32*)(_ptr))[0]) -#define ALLOC_C2(_ptr) (((u8*)(_ptr))[ALLOC_S(_ptr)]) -#endif - -#ifndef UNSAFE_MEMORY -#define ALLOC_OFF_HEAD 8 -#define ALLOC_OFF_TOTAL (ALLOC_OFF_HEAD + 1) -#else -#define ALLOC_OFF_HEAD 0 -#define ALLOC_OFF_TOTAL 0 -#endif - /* Allocator increments for ck_realloc_block(). */ #define ALLOC_BLK_INC 256 -/* Sanity-checking macros for pointers. */ - -#ifndef UNSAFE_MEMORY -#define CHECK_PTR(_p) \ - do { \ - \ - if (_p) { \ - \ - if (ALLOC_C1(_p) ^ ALLOC_MAGIC_C1) { \ - \ - if (ALLOC_C1(_p) == ALLOC_MAGIC_F) \ - ABORT("Use after free."); \ - else \ - ABORT("Corrupted head alloc canary."); \ - \ - } \ - \ - } \ - \ - } while (0) - -#else -#define CHECK_PTR(_p) \ - do { \ - \ - } while (0) -#endif - -/* #define CHECK_PTR(_p) do { \ - if (_p) { \ - if (ALLOC_C1(_p) ^ ALLOC_MAGIC_C1) {\ - if (ALLOC_C1(_p) == ALLOC_MAGIC_F) \ - ABORT("Use after free."); \ - else ABORT("Corrupted head alloc canary."); \ - - } \ - - if (ALLOC_C2(_p) ^ ALLOC_MAGIC_C2) \ - ABORT("Corrupted tail alloc canary."); \ - - } \ - - } while (0) - -*/ - -#define CHECK_PTR_EXPR(_p) \ - ({ \ - \ - typeof(_p) _tmp = (_p); \ - CHECK_PTR(_tmp); \ - _tmp; \ - \ - }) - /* Allocate a buffer, explicitly not zeroing it. Returns NULL for zero-sized requests. */ @@ -170,17 +81,9 @@ static inline void* DFL_ck_alloc_nozero(u32 size) { if (!size) return NULL; ALLOC_CHECK_SIZE(size); - ret = malloc(size + ALLOC_OFF_TOTAL); + ret = malloc(size); ALLOC_CHECK_RESULT(ret, size); -#ifndef UNSAFE_MEMORY - ret += ALLOC_OFF_HEAD; - - ALLOC_C1(ret) = ALLOC_MAGIC_C1; - ALLOC_S(ret) = size; - ALLOC_C2(ret) = ALLOC_MAGIC_C2; -#endif - return (void*)ret; } @@ -198,28 +101,11 @@ static inline void* DFL_ck_alloc(u32 size) { } -/* Free memory, checking for double free and corrupted heap. When DEBUG_BUILD - is set, the old memory will be also clobbered with 0xFF. */ +/* Free memory */ static inline void DFL_ck_free(void* mem) { - if (!mem) return; - - CHECK_PTR(mem); - -#ifdef DEBUG_BUILD - - /* Catch pointer issues sooner. */ - memset(mem, 0xFF, ALLOC_S(mem)); - -#endif /* DEBUG_BUILD */ - -#ifndef UNSAFE_MEMORY - ALLOC_C1(mem) = ALLOC_MAGIC_F; -#endif - - u8* realStart = mem; - free(realStart - ALLOC_OFF_HEAD); + free(mem); } @@ -239,64 +125,11 @@ static inline void* DFL_ck_realloc(void* orig, u32 size) { } - if (orig) { - - CHECK_PTR(orig); - -#ifndef UNSAFE_MEMORY -#ifndef DEBUG_BUILD - ALLOC_C1(orig) = ALLOC_MAGIC_F; -#endif /* !DEBUG_BUILD */ -#endif - -#ifndef UNSAFE_MEMORY - old_size = ALLOC_S(orig); - u8* origu8 = orig; - origu8 -= ALLOC_OFF_HEAD; - orig = origu8; - - ALLOC_CHECK_SIZE(old_size); -#endif - - } - ALLOC_CHECK_SIZE(size); -#ifndef DEBUG_BUILD - - ret = realloc(orig, size + ALLOC_OFF_TOTAL); + ret = realloc(orig, size); ALLOC_CHECK_RESULT(ret, size); -#else - - /* Catch pointer issues sooner: force relocation and make sure that the - original buffer is wiped. */ - - ret = malloc(size + ALLOC_OFF_TOTAL); - ALLOC_CHECK_RESULT(ret, size); - - if (orig) { - - u8* origu8 = orig; - memcpy(ret + ALLOC_OFF_HEAD, origu8 + ALLOC_OFF_HEAD, MIN(size, old_size)); - memset(origu8 + ALLOC_OFF_HEAD, 0xFF, old_size); - - ALLOC_C1(origu8 + ALLOC_OFF_HEAD) = ALLOC_MAGIC_F; - - free(orig); - - } - -#endif /* ^!DEBUG_BUILD */ - -#ifdef UNSAFE_MEMORY - ret += ALLOC_OFF_HEAD; - - ALLOC_C1(ret) = ALLOC_MAGIC_C1; - ALLOC_S(ret) = size; - ALLOC_C2(ret) = ALLOC_MAGIC_C2; -#endif - if (size > old_size) memset(ret + old_size, 0, size - old_size); return (void*)ret; @@ -308,22 +141,9 @@ static inline void* DFL_ck_realloc(void* orig, u32 size) { static inline void* DFL_ck_realloc_block(void* orig, u32 size) { -#ifndef DEBUG_BUILD - - if (orig) { - - CHECK_PTR(orig); - -#ifndef UNSAFE_MEMORY - if (ALLOC_S(orig) >= size) return orig; -#endif - + if (orig) size += ALLOC_BLK_INC; - } - -#endif /* !DEBUG_BUILD */ - return DFL_ck_realloc(orig, size); } @@ -340,17 +160,9 @@ static inline u8* DFL_ck_strdup(u8* str) { size = strlen((char*)str) + 1; ALLOC_CHECK_SIZE(size); - ret = malloc(size + ALLOC_OFF_TOTAL); + ret = malloc(size); ALLOC_CHECK_RESULT(ret, size); -#ifdef UNSAFE_MEMORY - ret += ALLOC_OFF_HEAD; - - ALLOC_C1(ret) = ALLOC_MAGIC_C1; - ALLOC_S(ret) = size; - ALLOC_C2(ret) = ALLOC_MAGIC_C2; -#endif - return memcpy(ret, str, size); } @@ -365,17 +177,9 @@ static inline void* DFL_ck_memdup(void* mem, u32 size) { if (!mem || !size) return NULL; ALLOC_CHECK_SIZE(size); - ret = malloc(size + ALLOC_OFF_TOTAL); + ret = malloc(size); ALLOC_CHECK_RESULT(ret, size); -#ifdef UNSAFE_MEMORY - ret += ALLOC_OFF_HEAD; - - ALLOC_C1(ret) = ALLOC_MAGIC_C1; - ALLOC_S(ret) = size; - ALLOC_C2(ret) = ALLOC_MAGIC_C2; -#endif - return memcpy(ret, mem, size); } @@ -390,17 +194,9 @@ static inline u8* DFL_ck_memdup_str(u8* mem, u32 size) { if (!mem || !size) return NULL; ALLOC_CHECK_SIZE(size); - ret = malloc(size + ALLOC_OFF_TOTAL + 1); + ret = malloc(size + 1); ALLOC_CHECK_RESULT(ret, size); -#ifdef UNSAFE_MEMORY - ret += ALLOC_OFF_HEAD; - - ALLOC_C1(ret) = ALLOC_MAGIC_C1; - ALLOC_S(ret) = size; - ALLOC_C2(ret) = ALLOC_MAGIC_C2; -#endif - memcpy(ret, mem, size); ret[size] = 0; @@ -408,8 +204,6 @@ static inline u8* DFL_ck_memdup_str(u8* mem, u32 size) { } -#ifndef DEBUG_BUILD - /* In non-debug mode, we just do straightforward aliasing of the above functions to user-visible names such as ck_alloc(). */ @@ -424,214 +218,5 @@ static inline u8* DFL_ck_memdup_str(u8* mem, u32 size) { #define alloc_report() -#else - -/* In debugging mode, we also track allocations to detect memory leaks, and the - flow goes through one more layer of indirection. */ - -/* Alloc tracking data structures: */ - -#define ALLOC_BUCKETS 4096 - -struct TRK_obj { - - void* ptr; - char *file, *func; - u32 line; - -}; - -#ifdef AFL_MAIN - -struct TRK_obj* TRK[ALLOC_BUCKETS]; -u32 TRK_cnt[ALLOC_BUCKETS]; - -#define alloc_report() TRK_report() - -#else - -extern struct TRK_obj* TRK[ALLOC_BUCKETS]; -extern u32 TRK_cnt[ALLOC_BUCKETS]; - -#define alloc_report() - -#endif /* ^AFL_MAIN */ - -/* Bucket-assigning function for a given pointer: */ - -#define TRKH(_ptr) (((((u32)(_ptr)) >> 16) ^ ((u32)(_ptr))) % ALLOC_BUCKETS) - -/* Add a new entry to the list of allocated objects. */ - -static inline void TRK_alloc_buf(void* ptr, const char* file, const char* func, - u32 line) { - - u32 i, bucket; - - if (!ptr) return; - - bucket = TRKH(ptr); - - /* Find a free slot in the list of entries for that bucket. */ - - for (i = 0; i < TRK_cnt[bucket]; i++) - - if (!TRK[bucket][i].ptr) { - - TRK[bucket][i].ptr = ptr; - TRK[bucket][i].file = (char*)file; - TRK[bucket][i].func = (char*)func; - TRK[bucket][i].line = line; - return; - - } - - /* No space available - allocate more. */ - - TRK[bucket] = DFL_ck_realloc_block( - TRK[bucket], (TRK_cnt[bucket] + 1) * sizeof(struct TRK_obj)); - - TRK[bucket][i].ptr = ptr; - TRK[bucket][i].file = (char*)file; - TRK[bucket][i].func = (char*)func; - TRK[bucket][i].line = line; - - TRK_cnt[bucket]++; - -} - -/* Remove entry from the list of allocated objects. */ - -static inline void TRK_free_buf(void* ptr, const char* file, const char* func, - u32 line) { - - u32 i, bucket; - - if (!ptr) return; - - bucket = TRKH(ptr); - - /* Find the element on the list... */ - - for (i = 0; i < TRK_cnt[bucket]; i++) - - if (TRK[bucket][i].ptr == ptr) { - - TRK[bucket][i].ptr = 0; - return; - - } - - WARNF("ALLOC: Attempt to free non-allocated memory in %s (%s:%u)", func, file, - line); - -} - -/* Do a final report on all non-deallocated objects. */ - -static inline void TRK_report(void) { - - u32 i, bucket; - - fflush(0); - - for (bucket = 0; bucket < ALLOC_BUCKETS; bucket++) - for (i = 0; i < TRK_cnt[bucket]; i++) - if (TRK[bucket][i].ptr) - WARNF("ALLOC: Memory never freed, created in %s (%s:%u)", - TRK[bucket][i].func, TRK[bucket][i].file, TRK[bucket][i].line); - -} - -/* Simple wrappers for non-debugging functions: */ - -static inline void* TRK_ck_alloc(u32 size, const char* file, const char* func, - u32 line) { - - void* ret = DFL_ck_alloc(size); - TRK_alloc_buf(ret, file, func, line); - return ret; - -} - -static inline void* TRK_ck_realloc(void* orig, u32 size, const char* file, - const char* func, u32 line) { - - void* ret = DFL_ck_realloc(orig, size); - TRK_free_buf(orig, file, func, line); - TRK_alloc_buf(ret, file, func, line); - return ret; - -} - -static inline void* TRK_ck_realloc_block(void* orig, u32 size, const char* file, - const char* func, u32 line) { - - void* ret = DFL_ck_realloc_block(orig, size); - TRK_free_buf(orig, file, func, line); - TRK_alloc_buf(ret, file, func, line); - return ret; - -} - -static inline void* TRK_ck_strdup(u8* str, const char* file, const char* func, - u32 line) { - - void* ret = DFL_ck_strdup(str); - TRK_alloc_buf(ret, file, func, line); - return ret; - -} - -static inline void* TRK_ck_memdup(void* mem, u32 size, const char* file, - const char* func, u32 line) { - - void* ret = DFL_ck_memdup(mem, size); - TRK_alloc_buf(ret, file, func, line); - return ret; - -} - -static inline void* TRK_ck_memdup_str(void* mem, u32 size, const char* file, - const char* func, u32 line) { - - void* ret = DFL_ck_memdup_str(mem, size); - TRK_alloc_buf(ret, file, func, line); - return ret; - -} - -static inline void TRK_ck_free(void* ptr, const char* file, const char* func, - u32 line) { - - TRK_free_buf(ptr, file, func, line); - DFL_ck_free(ptr); - -} - -/* Aliasing user-facing names to tracking functions: */ - -#define ck_alloc(_p1) TRK_ck_alloc(_p1, __FILE__, __FUNCTION__, __LINE__) - -#define ck_alloc_nozero(_p1) TRK_ck_alloc(_p1, __FILE__, __FUNCTION__, __LINE__) - -#define ck_realloc(_p1, _p2) \ - TRK_ck_realloc(_p1, _p2, __FILE__, __FUNCTION__, __LINE__) - -#define ck_realloc_block(_p1, _p2) \ - TRK_ck_realloc_block(_p1, _p2, __FILE__, __FUNCTION__, __LINE__) - -#define ck_strdup(_p1) TRK_ck_strdup(_p1, __FILE__, __FUNCTION__, __LINE__) - -#define ck_memdup(_p1, _p2) \ - TRK_ck_memdup(_p1, _p2, __FILE__, __FUNCTION__, __LINE__) - -#define ck_memdup_str(_p1, _p2) \ - TRK_ck_memdup_str(_p1, _p2, __FILE__, __FUNCTION__, __LINE__) - -#define ck_free(_p1) TRK_ck_free(_p1, __FILE__, __FUNCTION__, __LINE__) - -#endif /* ^!DEBUG_BUILD */ - #endif /* ! _HAVE_ALLOC_INL_H */ diff --git a/include/config.h b/include/config.h index c55c46c9..12e2d092 100644 --- a/include/config.h +++ b/include/config.h @@ -46,12 +46,6 @@ #define FANCY_BOXES #endif -/* Comment out to have safe memory checks (security in ck_ functions). - This will cost a little speed, so disable when developing on how - the queue works */ - -#define UNSAFE_MEMORY - /* Default timeout for fuzzed code (milliseconds). This is the upper bound, also used for detecting hangs; the actual value is auto-scaled: */ |