alloc-inl.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570
  1. /*
  2. american fuzzy lop - error-checking, memory-zeroing alloc routines
  3. ------------------------------------------------------------------
  4. Written and maintained by Michal Zalewski <lcamtuf@google.com>
  5. Copyright 2013, 2014, 2015 Google Inc. All rights reserved.
  6. Licensed under the Apache License, Version 2.0 (the "License");
  7. you may not use this file except in compliance with the License.
  8. You may obtain a copy of the License at:
  9. http://www.apache.org/licenses/LICENSE-2.0
  10. This allocator is not designed to resist malicious attackers (the canaries
  11. are small and predictable), but provides a robust and portable way to detect
  12. use-after-free, off-by-one writes, stale pointers, and so on.
  13. */
  14. #ifndef _HAVE_ALLOC_INL_H
  15. #define _HAVE_ALLOC_INL_H
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include "config.h"
  20. #include "types.h"
  21. #include "debug.h"
  22. /* User-facing macro to sprintf() to a dynamically allocated buffer. */
  23. #define alloc_printf(_str...) ({ \
  24. u8* _tmp; \
  25. s32 _len = snprintf(NULL, 0, _str); \
  26. if (_len < 0) FATAL("Whoa, snprintf() fails?!"); \
  27. _tmp = ck_alloc(_len + 1); \
  28. snprintf((char*)_tmp, _len + 1, _str); \
  29. _tmp; \
  30. })
  31. /* Macro to enforce allocation limits as a last-resort defense against
  32. integer overflows. */
  33. #define ALLOC_CHECK_SIZE(_s) do { \
  34. if ((_s) > MAX_ALLOC) \
  35. ABORT("Bad alloc request: %u bytes", (_s)); \
  36. } while (0)
  37. /* Macro to check malloc() failures and the like. */
  38. #define ALLOC_CHECK_RESULT(_r, _s) do { \
  39. if (!(_r)) \
  40. ABORT("Out of memory: can't allocate %u bytes", (_s)); \
  41. } while (0)
  42. /* Magic tokens used to mark used / freed chunks. */
  43. #define ALLOC_MAGIC_C1 0xFF00FF00 /* Used head (dword) */
  44. #define ALLOC_MAGIC_F 0xFE00FE00 /* Freed head (dword) */
  45. #define ALLOC_MAGIC_C2 0xF0 /* Used tail (byte) */
  46. /* Positions of guard tokens in relation to the user-visible pointer. */
  47. #define ALLOC_C1(_ptr) (((u32*)(_ptr))[-2])
  48. #define ALLOC_S(_ptr) (((u32*)(_ptr))[-1])
  49. #define ALLOC_C2(_ptr) (((u8*)(_ptr))[ALLOC_S(_ptr)])
  50. #define ALLOC_OFF_HEAD 8
  51. #define ALLOC_OFF_TOTAL (ALLOC_OFF_HEAD + 1)
  52. /* Allocator increments for ck_realloc_block(). */
  53. #define ALLOC_BLK_INC 256
  54. /* Sanity-checking macros for pointers. */
  55. #define CHECK_PTR(_p) do { \
  56. if (_p) { \
  57. if (ALLOC_C1(_p) ^ ALLOC_MAGIC_C1) {\
  58. if (ALLOC_C1(_p) == ALLOC_MAGIC_F) \
  59. ABORT("Use after free."); \
  60. else ABORT("Corrupted head alloc canary."); \
  61. } \
  62. if (ALLOC_C2(_p) ^ ALLOC_MAGIC_C2) \
  63. ABORT("Corrupted tail alloc canary."); \
  64. } \
  65. } while (0)
  66. #define CHECK_PTR_EXPR(_p) ({ \
  67. typeof (_p) _tmp = (_p); \
  68. CHECK_PTR(_tmp); \
  69. _tmp; \
  70. })
  71. /* Allocate a buffer, explicitly not zeroing it. Returns NULL for zero-sized
  72. requests. */
  73. static inline void* DFL_ck_alloc_nozero(u32 size) {
  74. void* ret;
  75. if (!size) return NULL;
  76. ALLOC_CHECK_SIZE(size);
  77. ret = malloc(size + ALLOC_OFF_TOTAL);
  78. ALLOC_CHECK_RESULT(ret, size);
  79. ret += ALLOC_OFF_HEAD;
  80. ALLOC_C1(ret) = ALLOC_MAGIC_C1;
  81. ALLOC_S(ret) = size;
  82. ALLOC_C2(ret) = ALLOC_MAGIC_C2;
  83. return ret;
  84. }
  85. /* Allocate a buffer, returning zeroed memory. */
  86. static inline void* DFL_ck_alloc(u32 size) {
  87. void* mem;
  88. if (!size) return NULL;
  89. mem = DFL_ck_alloc_nozero(size);
  90. return memset(mem, 0, size);
  91. }
  92. /* Free memory, checking for double free and corrupted heap. When DEBUG_BUILD
  93. is set, the old memory will be also clobbered with 0xFF. */
  94. static inline void DFL_ck_free(void* mem) {
  95. if (!mem) return;
  96. CHECK_PTR(mem);
  97. #ifdef DEBUG_BUILD
  98. /* Catch pointer issues sooner. */
  99. memset(mem, 0xFF, ALLOC_S(mem));
  100. #endif /* DEBUG_BUILD */
  101. ALLOC_C1(mem) = ALLOC_MAGIC_F;
  102. free(mem - ALLOC_OFF_HEAD);
  103. }
  104. /* Re-allocate a buffer, checking for issues and zeroing any newly-added tail.
  105. With DEBUG_BUILD, the buffer is always reallocated to a new addresses and the
  106. old memory is clobbered with 0xFF. */
  107. static inline void* DFL_ck_realloc(void* orig, u32 size) {
  108. void* ret;
  109. u32 old_size = 0;
  110. if (!size) {
  111. DFL_ck_free(orig);
  112. return NULL;
  113. }
  114. if (orig) {
  115. CHECK_PTR(orig);
  116. #ifndef DEBUG_BUILD
  117. ALLOC_C1(orig) = ALLOC_MAGIC_F;
  118. #endif /* !DEBUG_BUILD */
  119. old_size = ALLOC_S(orig);
  120. orig -= ALLOC_OFF_HEAD;
  121. ALLOC_CHECK_SIZE(old_size);
  122. }
  123. ALLOC_CHECK_SIZE(size);
  124. #ifndef DEBUG_BUILD
  125. ret = realloc(orig, size + ALLOC_OFF_TOTAL);
  126. ALLOC_CHECK_RESULT(ret, size);
  127. #else
  128. /* Catch pointer issues sooner: force relocation and make sure that the
  129. original buffer is wiped. */
  130. ret = malloc(size + ALLOC_OFF_TOTAL);
  131. ALLOC_CHECK_RESULT(ret, size);
  132. if (orig) {
  133. memcpy(ret + ALLOC_OFF_HEAD, orig + ALLOC_OFF_HEAD, MIN(size, old_size));
  134. memset(orig + ALLOC_OFF_HEAD, 0xFF, old_size);
  135. ALLOC_C1(orig + ALLOC_OFF_HEAD) = ALLOC_MAGIC_F;
  136. free(orig);
  137. }
  138. #endif /* ^!DEBUG_BUILD */
  139. ret += ALLOC_OFF_HEAD;
  140. ALLOC_C1(ret) = ALLOC_MAGIC_C1;
  141. ALLOC_S(ret) = size;
  142. ALLOC_C2(ret) = ALLOC_MAGIC_C2;
  143. if (size > old_size)
  144. memset(ret + old_size, 0, size - old_size);
  145. return ret;
  146. }
  147. /* Re-allocate a buffer with ALLOC_BLK_INC increments (used to speed up
  148. repeated small reallocs without complicating the user code). */
  149. static inline void* DFL_ck_realloc_block(void* orig, u32 size) {
  150. #ifndef DEBUG_BUILD
  151. if (orig) {
  152. CHECK_PTR(orig);
  153. if (ALLOC_S(orig) >= size) return orig;
  154. size += ALLOC_BLK_INC;
  155. }
  156. #endif /* !DEBUG_BUILD */
  157. return DFL_ck_realloc(orig, size);
  158. }
  159. /* Create a buffer with a copy of a string. Returns NULL for NULL inputs. */
  160. static inline u8* DFL_ck_strdup(u8* str) {
  161. void* ret;
  162. u32 size;
  163. if (!str) return NULL;
  164. size = strlen((char*)str) + 1;
  165. ALLOC_CHECK_SIZE(size);
  166. ret = malloc(size + ALLOC_OFF_TOTAL);
  167. ALLOC_CHECK_RESULT(ret, size);
  168. ret += ALLOC_OFF_HEAD;
  169. ALLOC_C1(ret) = ALLOC_MAGIC_C1;
  170. ALLOC_S(ret) = size;
  171. ALLOC_C2(ret) = ALLOC_MAGIC_C2;
  172. return memcpy(ret, str, size);
  173. }
  174. /* Create a buffer with a copy of a memory block. Returns NULL for zero-sized
  175. or NULL inputs. */
  176. static inline void* DFL_ck_memdup(void* mem, u32 size) {
  177. void* ret;
  178. if (!mem || !size) return NULL;
  179. ALLOC_CHECK_SIZE(size);
  180. ret = malloc(size + ALLOC_OFF_TOTAL);
  181. ALLOC_CHECK_RESULT(ret, size);
  182. ret += ALLOC_OFF_HEAD;
  183. ALLOC_C1(ret) = ALLOC_MAGIC_C1;
  184. ALLOC_S(ret) = size;
  185. ALLOC_C2(ret) = ALLOC_MAGIC_C2;
  186. return memcpy(ret, mem, size);
  187. }
  188. /* Create a buffer with a block of text, appending a NUL terminator at the end.
  189. Returns NULL for zero-sized or NULL inputs. */
  190. static inline u8* DFL_ck_memdup_str(u8* mem, u32 size) {
  191. u8* ret;
  192. if (!mem || !size) return NULL;
  193. ALLOC_CHECK_SIZE(size);
  194. ret = malloc(size + ALLOC_OFF_TOTAL + 1);
  195. ALLOC_CHECK_RESULT(ret, size);
  196. ret += ALLOC_OFF_HEAD;
  197. ALLOC_C1(ret) = ALLOC_MAGIC_C1;
  198. ALLOC_S(ret) = size;
  199. ALLOC_C2(ret) = ALLOC_MAGIC_C2;
  200. memcpy(ret, mem, size);
  201. ret[size] = 0;
  202. return ret;
  203. }
  204. #ifndef DEBUG_BUILD
  205. /* In non-debug mode, we just do straightforward aliasing of the above functions
  206. to user-visible names such as ck_alloc(). */
  207. #define ck_alloc DFL_ck_alloc
  208. #define ck_alloc_nozero DFL_ck_alloc_nozero
  209. #define ck_realloc DFL_ck_realloc
  210. #define ck_realloc_block DFL_ck_realloc_block
  211. #define ck_strdup DFL_ck_strdup
  212. #define ck_memdup DFL_ck_memdup
  213. #define ck_memdup_str DFL_ck_memdup_str
  214. #define ck_free DFL_ck_free
  215. #define alloc_report()
  216. #else
  217. /* In debugging mode, we also track allocations to detect memory leaks, and the
  218. flow goes through one more layer of indirection. */
  219. /* Alloc tracking data structures: */
  220. #define ALLOC_BUCKETS 4096
  221. struct TRK_obj {
  222. void *ptr;
  223. char *file, *func;
  224. u32 line;
  225. };
  226. #ifdef AFL_MAIN
  227. struct TRK_obj* TRK[ALLOC_BUCKETS];
  228. u32 TRK_cnt[ALLOC_BUCKETS];
  229. # define alloc_report() TRK_report()
  230. #else
  231. extern struct TRK_obj* TRK[ALLOC_BUCKETS];
  232. extern u32 TRK_cnt[ALLOC_BUCKETS];
  233. # define alloc_report()
  234. #endif /* ^AFL_MAIN */
  235. /* Bucket-assigning function for a given pointer: */
  236. #define TRKH(_ptr) (((((u32)(_ptr)) >> 16) ^ ((u32)(_ptr))) % ALLOC_BUCKETS)
  237. /* Add a new entry to the list of allocated objects. */
  238. static inline void TRK_alloc_buf(void* ptr, const char* file, const char* func,
  239. u32 line) {
  240. u32 i, bucket;
  241. if (!ptr) return;
  242. bucket = TRKH(ptr);
  243. /* Find a free slot in the list of entries for that bucket. */
  244. for (i = 0; i < TRK_cnt[bucket]; i++)
  245. if (!TRK[bucket][i].ptr) {
  246. TRK[bucket][i].ptr = ptr;
  247. TRK[bucket][i].file = (char*)file;
  248. TRK[bucket][i].func = (char*)func;
  249. TRK[bucket][i].line = line;
  250. return;
  251. }
  252. /* No space available - allocate more. */
  253. TRK[bucket] = DFL_ck_realloc_block(TRK[bucket],
  254. (TRK_cnt[bucket] + 1) * sizeof(struct TRK_obj));
  255. TRK[bucket][i].ptr = ptr;
  256. TRK[bucket][i].file = (char*)file;
  257. TRK[bucket][i].func = (char*)func;
  258. TRK[bucket][i].line = line;
  259. TRK_cnt[bucket]++;
  260. }
  261. /* Remove entry from the list of allocated objects. */
  262. static inline void TRK_free_buf(void* ptr, const char* file, const char* func,
  263. u32 line) {
  264. u32 i, bucket;
  265. if (!ptr) return;
  266. bucket = TRKH(ptr);
  267. /* Find the element on the list... */
  268. for (i = 0; i < TRK_cnt[bucket]; i++)
  269. if (TRK[bucket][i].ptr == ptr) {
  270. TRK[bucket][i].ptr = 0;
  271. return;
  272. }
  273. WARNF("ALLOC: Attempt to free non-allocated memory in %s (%s:%u)",
  274. func, file, line);
  275. }
  276. /* Do a final report on all non-deallocated objects. */
  277. static inline void TRK_report(void) {
  278. u32 i, bucket;
  279. fflush(0);
  280. for (bucket = 0; bucket < ALLOC_BUCKETS; bucket++)
  281. for (i = 0; i < TRK_cnt[bucket]; i++)
  282. if (TRK[bucket][i].ptr)
  283. WARNF("ALLOC: Memory never freed, created in %s (%s:%u)",
  284. TRK[bucket][i].func, TRK[bucket][i].file, TRK[bucket][i].line);
  285. }
  286. /* Simple wrappers for non-debugging functions: */
  287. static inline void* TRK_ck_alloc(u32 size, const char* file, const char* func,
  288. u32 line) {
  289. void* ret = DFL_ck_alloc(size);
  290. TRK_alloc_buf(ret, file, func, line);
  291. return ret;
  292. }
  293. static inline void* TRK_ck_realloc(void* orig, u32 size, const char* file,
  294. const char* func, u32 line) {
  295. void* ret = DFL_ck_realloc(orig, size);
  296. TRK_free_buf(orig, file, func, line);
  297. TRK_alloc_buf(ret, file, func, line);
  298. return ret;
  299. }
  300. static inline void* TRK_ck_realloc_block(void* orig, u32 size, const char* file,
  301. const char* func, u32 line) {
  302. void* ret = DFL_ck_realloc_block(orig, size);
  303. TRK_free_buf(orig, file, func, line);
  304. TRK_alloc_buf(ret, file, func, line);
  305. return ret;
  306. }
  307. static inline void* TRK_ck_strdup(u8* str, const char* file, const char* func,
  308. u32 line) {
  309. void* ret = DFL_ck_strdup(str);
  310. TRK_alloc_buf(ret, file, func, line);
  311. return ret;
  312. }
  313. static inline void* TRK_ck_memdup(void* mem, u32 size, const char* file,
  314. const char* func, u32 line) {
  315. void* ret = DFL_ck_memdup(mem, size);
  316. TRK_alloc_buf(ret, file, func, line);
  317. return ret;
  318. }
  319. static inline void* TRK_ck_memdup_str(void* mem, u32 size, const char* file,
  320. const char* func, u32 line) {
  321. void* ret = DFL_ck_memdup_str(mem, size);
  322. TRK_alloc_buf(ret, file, func, line);
  323. return ret;
  324. }
  325. static inline void TRK_ck_free(void* ptr, const char* file,
  326. const char* func, u32 line) {
  327. TRK_free_buf(ptr, file, func, line);
  328. DFL_ck_free(ptr);
  329. }
  330. /* Aliasing user-facing names to tracking functions: */
  331. #define ck_alloc(_p1) \
  332. TRK_ck_alloc(_p1, __FILE__, __FUNCTION__, __LINE__)
  333. #define ck_alloc_nozero(_p1) \
  334. TRK_ck_alloc(_p1, __FILE__, __FUNCTION__, __LINE__)
  335. #define ck_realloc(_p1, _p2) \
  336. TRK_ck_realloc(_p1, _p2, __FILE__, __FUNCTION__, __LINE__)
  337. #define ck_realloc_block(_p1, _p2) \
  338. TRK_ck_realloc_block(_p1, _p2, __FILE__, __FUNCTION__, __LINE__)
  339. #define ck_strdup(_p1) \
  340. TRK_ck_strdup(_p1, __FILE__, __FUNCTION__, __LINE__)
  341. #define ck_memdup(_p1, _p2) \
  342. TRK_ck_memdup(_p1, _p2, __FILE__, __FUNCTION__, __LINE__)
  343. #define ck_memdup_str(_p1, _p2) \
  344. TRK_ck_memdup_str(_p1, _p2, __FILE__, __FUNCTION__, __LINE__)
  345. #define ck_free(_p1) \
  346. TRK_ck_free(_p1, __FILE__, __FUNCTION__, __LINE__)
  347. #endif /* ^!DEBUG_BUILD */
  348. #endif /* ! _HAVE_ALLOC_INL_H */