about summary refs log tree commit diff
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