aboutsummaryrefslogtreecommitdiff
path: root/include/afl-prealloc.h
diff options
context:
space:
mode:
authorDominik Maier <domenukk@gmail.com>2020-03-09 11:24:10 +0100
committerGitHub <noreply@github.com>2020-03-09 11:24:10 +0100
commitdba3595c0ae26795a78753ea33ff0c3edf9d6328 (patch)
tree03bcaf132705d6de222ef8d6eff9b5bc2f03ce54 /include/afl-prealloc.h
parentc159b872ef17d4c09238f99ac11021e12975cb3a (diff)
downloadafl++-dba3595c0ae26795a78753ea33ff0c3edf9d6328.tar.gz
AFL without globals (#220)
* moved globals to afl, shm and fsrv * moved argv to afl state, less bugs * fixed unicorn docu * lists everywhere * merged custom mutators * fixed leaks in afl-fuzz
Diffstat (limited to 'include/afl-prealloc.h')
-rw-r--r--include/afl-prealloc.h101
1 files changed, 101 insertions, 0 deletions
diff --git a/include/afl-prealloc.h b/include/afl-prealloc.h
new file mode 100644
index 00000000..712cdec6
--- /dev/null
+++ b/include/afl-prealloc.h
@@ -0,0 +1,101 @@
+/* If we know we'll reuse small elements often, we'll just preallocate a buffer, then fall back to malloc */
+// TODO: Replace free status check with bitmask+CLZ
+
+#ifndef AFL_PREALLOC_H
+#define AFL_PREALLOC_H
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include "debug.h"
+
+typedef enum prealloc_status {
+ PRE_STATUS_UNUSED = 0,/* free in buf */
+ PRE_STATUS_USED, /* used in buf */
+ PRE_STATUS_MALLOC /* system malloc */
+} pre_status_t;
+
+
+/* Adds the entry used for prealloc bookkeeping to this struct */
+
+#define PREALLOCABLE ;pre_status_t pre_status; /* prealloc status of this instance */
+
+
+/* allocate an element of type *el_ptr, to this variable.
+ Uses (and reuses) the given prealloc_buf before hitting libc's malloc.
+ prealloc_buf must be the pointer to an array with type `type`.
+ `type` must be a struct with uses PREALLOCABLE (a pre_status_t pre_status member).
+ prealloc_size must be the array size.
+ prealloc_counter must be a variable initialized with 0 (of any name).
+ */
+
+#define PRE_ALLOC(el_ptr, prealloc_buf, prealloc_size, prealloc_counter) do { \
+ \
+ if ((prealloc_counter) >= (prealloc_size)) { \
+ \
+ el_ptr = malloc(sizeof(*el_ptr)); \
+ el_ptr->pre_status = PRE_STATUS_MALLOC; \
+ \
+ } else { \
+ \
+ /* Find one of our preallocated elements */ \
+ u32 i; \
+ for (i = 0; i < (prealloc_size); i++) { \
+ \
+ el_ptr = &((prealloc_buf)[i]); \
+ if (el_ptr->pre_status == PRE_STATUS_UNUSED) { \
+ \
+ (prealloc_counter)++; \
+ el_ptr->pre_status = PRE_STATUS_USED; \
+ break; \
+ \
+ } \
+ } \
+ } \
+ \
+ if(!el_ptr) { \
+ FATAL("BUG in list.h -> no element found or allocated!"); \
+ } \
+} while(0);
+
+
+/* Take a chosen (free) element from the prealloc_buf directly */
+
+#define PRE_ALLOC_FORCE(el_ptr, prealloc_counter) do { \
+ if ((el_ptr)->pre_status != PRE_STATUS_UNUSED) { \
+ FATAL("PRE_ALLOC_FORCE element already allocated"); \
+ } \
+ (el_ptr)->pre_status = PRE_STATUS_USED; \
+ (prealloc_counter)++; \
+} while(0);
+
+
+/* free an preallocated element */
+
+#define PRE_FREE(el_ptr, prealloc_counter) do { \
+ \
+ switch ((el_ptr)->pre_status) { \
+ \
+ case PRE_STATUS_USED: { \
+ (el_ptr)->pre_status = PRE_STATUS_UNUSED; \
+ (prealloc_counter)--; \
+ if ((prealloc_counter) < 0) { \
+ FATAL("Inconsistent data in PRE_FREE"); \
+ } \
+ break; \
+ } \
+ case PRE_STATUS_MALLOC: { \
+ (el_ptr)->pre_status = PRE_STATUS_UNUSED; \
+ free((el_ptr)); \
+ break; \
+ } \
+ default: { \
+ FATAL("Double Free Detected"); \
+ break; \
+ } \
+ \
+ } \
+} while(0);
+
+#endif