about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/README.md24
-rw-r--r--src/README.src22
-rw-r--r--src/afl-analyze.c5
-rw-r--r--src/afl-common.c399
-rw-r--r--src/afl-forkserver.c30
-rw-r--r--src/afl-fuzz-bitmap.c47
-rw-r--r--src/afl-fuzz-cmplog.c76
-rw-r--r--src/afl-fuzz-init.c33
-rw-r--r--src/afl-fuzz-mutators.c61
-rw-r--r--src/afl-fuzz-one.c150
-rw-r--r--src/afl-fuzz-python.c130
-rw-r--r--src/afl-fuzz-queue.c57
-rw-r--r--src/afl-fuzz-redqueen.c5
-rw-r--r--src/afl-fuzz-run.c83
-rw-r--r--src/afl-fuzz-state.c (renamed from src/afl-fuzz-globals.c)13
-rw-r--r--src/afl-fuzz-stats.c125
-rw-r--r--src/afl-fuzz.c13
-rw-r--r--src/afl-showmap.c25
-rw-r--r--src/afl-tmin.c21
-rw-r--r--src/third_party/libradamsa/libradamsa.c2
20 files changed, 872 insertions, 449 deletions
diff --git a/src/README.md b/src/README.md
new file mode 100644
index 00000000..6da534c3
--- /dev/null
+++ b/src/README.md
@@ -0,0 +1,24 @@
+# Source Folder
+
+Quick explanation about the files here:
+
+- `afl-analyze.c`		- afl-analyze binary tool
+- `afl-as.c`		- afl-as binary tool
+- `afl-gotcpu.c`		- afl-gotcpu binary tool
+- `afl-showmap.c`		- afl-showmap binary tool
+- `afl-tmin.c`		- afl-tmin binary tool
+- `afl-fuzz.c`		- afl-fuzz binary tool (just main() and usage())
+- `afl-fuzz-bitmap.c`	- afl-fuzz bitmap handling
+- `afl-fuzz-extras.c`	- afl-fuzz the *extra* function calls
+- `afl-fuzz-state.c`	- afl-fuzz state and globals
+- `afl-fuzz-init.c`		- afl-fuzz initialization
+- `afl-fuzz-misc.c`		- afl-fuzz misc functions
+- `afl-fuzz-one.c`          - afl-fuzz fuzzer_one big loop, this is where the mutation is happening
+- `afl-fuzz-python.c`	- afl-fuzz the python mutator extension
+- `afl-fuzz-queue.c`	- afl-fuzz handling the queue
+- `afl-fuzz-run.c`		- afl-fuzz running the target
+- `afl-fuzz-stats.c`	- afl-fuzz writing the statistics file
+- `afl-gcc.c`		- afl-gcc binary tool (deprecated)
+- `afl-common.c`		- common functions, used by afl-analyze, afl-fuzz, afl-showmap and afl-tmin
+- `afl-forkserver.c`	- forkserver implementation, used by afl-fuzz and afl-tmin
+afl-sharedmem.c		- sharedmem implementation, used by afl-fuzz and afl-tmin
diff --git a/src/README.src b/src/README.src
deleted file mode 100644
index 244f5ddd..00000000
--- a/src/README.src
+++ /dev/null
@@ -1,22 +0,0 @@
-Quick explanation about the files here:
-
-afl-analyze.c		- afl-analyze binary tool
-afl-as.c		- afl-as binary tool
-afl-gotcpu.c		- afl-gotcpu binary tool
-afl-showmap.c		- afl-showmap binary tool
-afl-tmin.c		- afl-tmin binary tool
-afl-fuzz.c		- afl-fuzz binary tool (just main() and usage())
-afl-fuzz-bitmap.c	- afl-fuzz bitmap handling
-afl-fuzz-extras.c	- afl-fuzz the *extra* function calls
-afl-fuzz-globals.c	- afl-fuzz global variables
-afl-fuzz-init.c		- afl-fuzz initialization
-afl-fuzz-misc.c		- afl-fuzz misc functions
-afl-fuzz-one.c          - afl-fuzz fuzzer_one big loop, this is where the mutation is happening
-afl-fuzz-python.c	- afl-fuzz the python mutator extension
-afl-fuzz-queue.c	- afl-fuzz handling the queue
-afl-fuzz-run.c		- afl-fuzz running the target
-afl-fuzz-stats.c	- afl-fuzz writing the statistics file
-afl-gcc.c		- afl-gcc binary tool (deprecated)
-afl-common.c		- common functions, used by afl-analyze, afl-fuzz, afl-showmap and afl-tmin
-afl-forkserver.c	- forkserver implementation, used by afl-fuzz and afl-tmin
-afl-sharedmem.c		- sharedmem implementation, used by afl-fuzz and afl-tmin
diff --git a/src/afl-analyze.c b/src/afl-analyze.c
index d509c43e..427fbe6d 100644
--- a/src/afl-analyze.c
+++ b/src/afl-analyze.c
@@ -60,8 +60,7 @@ static s32 child_pid;                  /* PID of the tested program         */
 u8 *trace_bits;                        /* SHM with instrumentation bitmap   */
 
 static u8 *in_file,                    /* Analyzer input test case          */
-    *prog_in,                          /* Targeted program input file       */
-    *doc_path;                         /* Path to docs                      */
+    *prog_in;                          /* Targeted program input file       */
 
 static u8 *in_data;                    /* Input data for analysis           */
 
@@ -77,7 +76,7 @@ static s32 dev_null_fd = -1;           /* FD to /dev/null                   */
 
 u8 edges_only,                         /* Ignore hit counts?                */
     use_hex_offsets,                   /* Show hex offsets?                 */
-    be_quiet, use_stdin = 1;           /* Use stdin for program input?      */
+    use_stdin = 1;                     /* Use stdin for program input?      */
 
 static volatile u8 stop_soon,          /* Ctrl-C pressed?                   */
     child_timed_out;                   /* Child timed out?                  */
diff --git a/src/afl-common.c b/src/afl-common.c
index 8c4d53e8..920c7dfd 100644
--- a/src/afl-common.c
+++ b/src/afl-common.c
@@ -30,6 +30,7 @@
 #include "debug.h"
 #include "alloc-inl.h"
 #include "envs.h"
+#include "common.h"
 
 /* Detect @@ in args. */
 #ifndef __glibc__
@@ -37,8 +38,10 @@
 #endif
 #include <limits.h>
 
-extern u8 be_quiet;
-char *    afl_environment_variables[] = {
+u8  be_quiet = 0;
+u8 *doc_path = "";
+
+char *afl_environment_variables[] = {
 
     "AFL_ALIGNED_ALLOC", "AFL_ALLOW_TMP", "AFL_ANALYZE_HEX", "AFL_AS",
     "AFL_AUTORESUME", "AFL_AS_FORCE_INSTRUMENT", "AFL_BENCH_JUST_ONE",
@@ -73,7 +76,7 @@ char *    afl_environment_variables[] = {
     "AFL_SHUFFLE_QUEUE", "AFL_SKIP_BIN_CHECK", "AFL_SKIP_CPUFREQ",
     "AFL_SKIP_CRASHES", "AFL_TMIN_EXACT", "AFL_TMPDIR", "AFL_TOKEN_FILE",
     "AFL_TRACE_PC", "AFL_USE_ASAN", "AFL_USE_MSAN", "AFL_USE_TRACE_PC",
-    "AFL_USE_UBSAN", "AFL_WINE_PATH", NULL};
+    "AFL_USE_UBSAN", "AFL_USE_CFISAN", "AFL_WINE_PATH", NULL};
 
 void detect_file_args(char **argv, u8 *prog_in, u8 *use_stdin) {
 
@@ -393,3 +396,393 @@ char *get_afl_env(char *env) {
 
 }
 
+u64 get_cur_time(void) {
+
+  struct timeval  tv;
+  struct timezone tz;
+
+  gettimeofday(&tv, &tz);
+
+  return (tv.tv_sec * 1000ULL) + (tv.tv_usec / 1000);
+
+}
+
+/* Get unix time in microseconds */
+
+u64 get_cur_time_us(void) {
+
+  struct timeval  tv;
+  struct timezone tz;
+
+  gettimeofday(&tv, &tz);
+
+  return (tv.tv_sec * 1000000ULL) + tv.tv_usec;
+
+}
+
+/* Describe integer. The buf should be
+   at least 6 bytes to fit all ints we randomly see.
+   Will return buf for convenience. */
+
+u8 *stringify_int(u8 *buf, size_t len, u64 val) {
+\
+#define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast)     \
+  do {                                                     \
+                                                           \
+    if (val < (_divisor) * (_limit_mult)) {                \
+                                                           \
+      snprintf(buf, len, _fmt, ((_cast)val) / (_divisor)); \
+      return buf;                                          \
+                                                           \
+    }                                                      \
+                                                           \
+  } while (0)
+
+  /* 0-9999 */
+  CHK_FORMAT(1, 10000, "%llu", u64);
+
+  /* 10.0k - 99.9k */
+  CHK_FORMAT(1000, 99.95, "%0.01fk", double);
+
+  /* 100k - 999k */
+  CHK_FORMAT(1000, 1000, "%lluk", u64);
+
+  /* 1.00M - 9.99M */
+  CHK_FORMAT(1000 * 1000, 9.995, "%0.02fM", double);
+
+  /* 10.0M - 99.9M */
+  CHK_FORMAT(1000 * 1000, 99.95, "%0.01fM", double);
+
+  /* 100M - 999M */
+  CHK_FORMAT(1000 * 1000, 1000, "%lluM", u64);
+
+  /* 1.00G - 9.99G */
+  CHK_FORMAT(1000LL * 1000 * 1000, 9.995, "%0.02fG", double);
+
+  /* 10.0G - 99.9G */
+  CHK_FORMAT(1000LL * 1000 * 1000, 99.95, "%0.01fG", double);
+
+  /* 100G - 999G */
+  CHK_FORMAT(1000LL * 1000 * 1000, 1000, "%lluG", u64);
+
+  /* 1.00T - 9.99G */
+  CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 9.995, "%0.02fT", double);
+
+  /* 10.0T - 99.9T */
+  CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 99.95, "%0.01fT", double);
+
+  /* 100T+ */
+  strncpy(buf, "infty", len);
+  buf[len - 1] = '\0';
+
+  return buf;
+
+}
+
+/* Describe float. Similar as int. */
+
+u8 *stringify_float(u8 *buf, size_t len, double val) {
+
+  if (val < 99.995) {
+
+    snprintf(buf, len, "%0.02f", val);
+
+  } else if (val < 999.95) {
+
+    snprintf(buf, len, "%0.01f", val);
+
+  } else {
+
+    stringify_int(buf, len, (u64)val);
+
+  }
+
+  return buf;
+
+}
+
+/* Describe integer as memory size. */
+
+u8 *stringify_mem_size(u8 *buf, size_t len, u64 val) {
+
+  /* 0-9999 */
+  CHK_FORMAT(1, 10000, "%llu B", u64);
+
+  /* 10.0k - 99.9k */
+  CHK_FORMAT(1024, 99.95, "%0.01f kB", double);
+
+  /* 100k - 999k */
+  CHK_FORMAT(1024, 1000, "%llu kB", u64);
+
+  /* 1.00M - 9.99M */
+  CHK_FORMAT(1024 * 1024, 9.995, "%0.02f MB", double);
+
+  /* 10.0M - 99.9M */
+  CHK_FORMAT(1024 * 1024, 99.95, "%0.01f MB", double);
+
+  /* 100M - 999M */
+  CHK_FORMAT(1024 * 1024, 1000, "%llu MB", u64);
+
+  /* 1.00G - 9.99G */
+  CHK_FORMAT(1024LL * 1024 * 1024, 9.995, "%0.02f GB", double);
+
+  /* 10.0G - 99.9G */
+  CHK_FORMAT(1024LL * 1024 * 1024, 99.95, "%0.01f GB", double);
+
+  /* 100G - 999G */
+  CHK_FORMAT(1024LL * 1024 * 1024, 1000, "%llu GB", u64);
+
+  /* 1.00T - 9.99G */
+  CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 9.995, "%0.02f TB", double);
+
+  /* 10.0T - 99.9T */
+  CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 99.95, "%0.01f TB", double);
+
+#undef CHK_FORMAT
+
+  /* 100T+ */
+  strncpy(buf, "infty", len - 1);
+  buf[len - 1] = '\0';
+
+  return buf;
+
+}
+
+/* Describe time delta as string.
+   Returns a pointer to buf for convenience. */
+
+u8 *stringify_time_diff(u8 *buf, size_t len, u64 cur_ms, u64 event_ms) {
+
+  u64 delta;
+  s32 t_d, t_h, t_m, t_s;
+  u8  val_buf[STRINGIFY_VAL_SIZE_MAX];
+
+  if (!event_ms) {
+
+    snprintf(buf, len, "none seen yet");
+
+  } else {
+
+    delta = cur_ms - event_ms;
+
+    t_d = delta / 1000 / 60 / 60 / 24;
+    t_h = (delta / 1000 / 60 / 60) % 24;
+    t_m = (delta / 1000 / 60) % 60;
+    t_s = (delta / 1000) % 60;
+
+    stringify_int(val_buf, sizeof(val_buf), t_d);
+    snprintf(buf, len, "%s days, %d hrs, %d min, %d sec", val_buf, t_h, t_m,
+             t_s);
+
+  }
+
+  return buf;
+
+}
+
+/* Unsafe Describe integer. The buf sizes are not checked.
+   This is unsafe but fast.
+   Will return buf for convenience. */
+
+u8 *u_stringify_int(u8 *buf, u64 val) {
+\
+#define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast) \
+  do {                                                 \
+                                                       \
+    if (val < (_divisor) * (_limit_mult)) {            \
+                                                       \
+      sprintf(buf, _fmt, ((_cast)val) / (_divisor));   \
+      return buf;                                      \
+                                                       \
+    }                                                  \
+                                                       \
+  } while (0)
+
+  /* 0-9999 */
+  CHK_FORMAT(1, 10000, "%llu", u64);
+
+  /* 10.0k - 99.9k */
+  CHK_FORMAT(1000, 99.95, "%0.01fk", double);
+
+  /* 100k - 999k */
+  CHK_FORMAT(1000, 1000, "%lluk", u64);
+
+  /* 1.00M - 9.99M */
+  CHK_FORMAT(1000 * 1000, 9.995, "%0.02fM", double);
+
+  /* 10.0M - 99.9M */
+  CHK_FORMAT(1000 * 1000, 99.95, "%0.01fM", double);
+
+  /* 100M - 999M */
+  CHK_FORMAT(1000 * 1000, 1000, "%lluM", u64);
+
+  /* 1.00G - 9.99G */
+  CHK_FORMAT(1000LL * 1000 * 1000, 9.995, "%0.02fG", double);
+
+  /* 10.0G - 99.9G */
+  CHK_FORMAT(1000LL * 1000 * 1000, 99.95, "%0.01fG", double);
+
+  /* 100G - 999G */
+  CHK_FORMAT(1000LL * 1000 * 1000, 1000, "%lluG", u64);
+
+  /* 1.00T - 9.99G */
+  CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 9.995, "%0.02fT", double);
+
+  /* 10.0T - 99.9T */
+  CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 99.95, "%0.01fT", double);
+
+  /* 100T+ */
+  strcpy(buf, "infty");
+
+  return buf;
+
+}
+
+/* Unsafe describe float. Similar as unsafe int. */
+
+u8 *u_stringify_float(u8 *buf, double val) {
+
+  if (val < 99.995) {
+
+    sprintf(buf, "%0.02f", val);
+
+  } else if (val < 999.95) {
+
+    sprintf(buf, "%0.01f", val);
+
+  } else {
+
+    return u_stringify_int(buf, (u64)val);
+
+  }
+
+  return buf;
+
+}
+
+/* Unsafe describe integer as memory size. */
+
+u8 *u_stringify_mem_size(u8 *buf, u64 val) {
+
+  /* 0-9999 */
+  CHK_FORMAT(1, 10000, "%llu B", u64);
+
+  /* 10.0k - 99.9k */
+  CHK_FORMAT(1024, 99.95, "%0.01f kB", double);
+
+  /* 100k - 999k */
+  CHK_FORMAT(1024, 1000, "%llu kB", u64);
+
+  /* 1.00M - 9.99M */
+  CHK_FORMAT(1024 * 1024, 9.995, "%0.02f MB", double);
+
+  /* 10.0M - 99.9M */
+  CHK_FORMAT(1024 * 1024, 99.95, "%0.01f MB", double);
+
+  /* 100M - 999M */
+  CHK_FORMAT(1024 * 1024, 1000, "%llu MB", u64);
+
+  /* 1.00G - 9.99G */
+  CHK_FORMAT(1024LL * 1024 * 1024, 9.995, "%0.02f GB", double);
+
+  /* 10.0G - 99.9G */
+  CHK_FORMAT(1024LL * 1024 * 1024, 99.95, "%0.01f GB", double);
+
+  /* 100G - 999G */
+  CHK_FORMAT(1024LL * 1024 * 1024, 1000, "%llu GB", u64);
+
+  /* 1.00T - 9.99G */
+  CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 9.995, "%0.02f TB", double);
+
+  /* 10.0T - 99.9T */
+  CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 99.95, "%0.01f TB", double);
+
+#undef CHK_FORMAT
+
+  /* 100T+ */
+  strcpy(buf, "infty");
+
+  return buf;
+
+}
+
+/* Unsafe describe time delta as string.
+   Returns a pointer to buf for convenience. */
+
+u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms) {
+
+  u64 delta;
+  s32 t_d, t_h, t_m, t_s;
+  u8  val_buf[STRINGIFY_VAL_SIZE_MAX];
+
+  if (!event_ms) {
+
+    sprintf(buf, "none seen yet");
+
+  } else {
+
+    delta = cur_ms - event_ms;
+
+    t_d = delta / 1000 / 60 / 60 / 24;
+    t_h = (delta / 1000 / 60 / 60) % 24;
+    t_m = (delta / 1000 / 60) % 60;
+    t_s = (delta / 1000) % 60;
+
+    u_stringify_int(val_buf, t_d);
+    sprintf(buf, "%s days, %d hrs, %d min, %d sec", val_buf, t_h, t_m, t_s);
+
+  }
+
+  return buf;
+
+}
+
+/* Wrapper for select() and read(), reading exactly len bytes.
+  Returns the time passed to read.
+  If the wait times out, returns timeout_ms + 1;
+  Returns 0 if an error occurred (fd closed, signal, ...); */
+u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms) {
+
+  struct timeval timeout;
+  fd_set         readfds;
+  FD_ZERO(&readfds);
+  FD_SET(fd, &readfds);
+
+  timeout.tv_sec = (timeout_ms / 1000);
+  timeout.tv_usec = (timeout_ms % 1000) * 1000;
+
+  size_t read_total = 0;
+  size_t len_read = 0;
+
+  while (len_read < len) {
+
+    /* set exceptfds as well to return when a child exited/closed the pipe. */
+    int sret = select(fd + 1, &readfds, NULL, NULL, &timeout);
+
+    if (!sret) {
+
+      // printf("Timeout in sret.");
+      return timeout_ms + 1;
+
+    } else if (sret < 0) {
+
+      // perror("sret malloc");
+      // TODO: catch other (errno == EINTR) than ctrl+c?
+      return 0;
+
+    }
+
+    len_read = read(fd, ((u8 *)buf) + len_read, len - len_read);
+    if (!len_read) { return 0; }
+    read_total += len_read;
+
+  }
+
+  s32 exec_ms =
+      MIN(timeout_ms,
+          ((u64)timeout_ms - (timeout.tv_sec * 1000 + timeout.tv_usec / 1000)));
+  return exec_ms > 0 ? exec_ms
+                     : 1;  // at least 1 milli must have passed (0 is an error)
+
+}
+
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index 2dd7a9f0..11b359da 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -49,8 +49,6 @@
 
 /* Describe integer as memory size. */
 
-extern u8 *doc_path;
-
 list_t fsrv_list = {.element_prealloc_count = 0};
 
 /* Initializes the struct */
@@ -164,10 +162,9 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) {
 
 void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv) {
 
-  struct timeval timeout;
-  int            st_pipe[2], ctl_pipe[2];
-  int            status;
-  s32            rlen;
+  int st_pipe[2], ctl_pipe[2];
+  int status;
+  s32 rlen;
 
   if (fsrv->use_fauxsrv) ACTF("Using Fauxserver:");
 
@@ -318,26 +315,19 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv) {
   rlen = 0;
   if (fsrv->exec_tmout) {
 
-    fd_set readfds;
-
-    FD_ZERO(&readfds);
-    FD_SET(fsrv->fsrv_st_fd, &readfds);
-    timeout.tv_sec = ((fsrv->exec_tmout * FORK_WAIT_MULT) / 1000);
-    timeout.tv_usec = ((fsrv->exec_tmout * FORK_WAIT_MULT) % 1000) * 1000;
+    rlen = 4;
+    u32 time = read_timed(fsrv->fsrv_st_fd, &status, rlen,
+                          fsrv->exec_tmout * FORK_WAIT_MULT);
 
-    int sret = select(fsrv->fsrv_st_fd + 1, &readfds, NULL, NULL, &timeout);
-
-    if (sret == 0) {
+    if (time > fsrv->exec_tmout * FORK_WAIT_MULT) {
 
       fsrv->child_timed_out = 1;
-      kill(fsrv->child_pid, SIGKILL);
-
-    } else {
-
-      rlen = read(fsrv->fsrv_st_fd, &status, 4);
+      kill(fsrv->fsrv_pid, SIGKILL);
 
     }
 
+    if (!time) { kill(fsrv->fsrv_pid, SIGKILL); }
+
   } else {
 
     rlen = read(fsrv->fsrv_st_fd, &status, 4);
diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c
index 0d5b542d..8ca286b2 100644
--- a/src/afl-fuzz-bitmap.c
+++ b/src/afl-fuzz-bitmap.c
@@ -31,13 +31,13 @@
 
 void write_bitmap(afl_state_t *afl) {
 
-  u8 *fname;
+  u8  fname[PATH_MAX];
   s32 fd;
 
   if (!afl->bitmap_changed) return;
   afl->bitmap_changed = 0;
 
-  fname = alloc_printf("%s/fuzz_bitmap", afl->out_dir);
+  snprintf(fname, PATH_MAX, "%s/fuzz_bitmap", afl->out_dir);
   fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC, 0600);
 
   if (fd < 0) PFATAL("Unable to open '%s'", fname);
@@ -45,7 +45,6 @@ void write_bitmap(afl_state_t *afl) {
   ck_write(fd, afl->virgin_bits, MAP_SIZE, fname);
 
   close(fd);
-  ck_free(fname);
 
 }
 
@@ -462,14 +461,15 @@ u8 *describe_op(afl_state_t *afl, u8 hnb) {
 
 static void write_crash_readme(afl_state_t *afl) {
 
-  u8 *  fn = alloc_printf("%s/crashes/README.txt", afl->out_dir);
+  u8    fn[PATH_MAX];
   s32   fd;
   FILE *f;
 
   u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
 
+  sprintf(fn, "%s/crashes/README.txt", afl->out_dir);
+
   fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
-  ck_free(fn);
 
   /* Do not die on errors here - that would be impolite. */
 
@@ -520,11 +520,13 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
 
   if (unlikely(len == 0)) return 0;
 
-  u8 *fn = "";
+  u8 *queue_fn = "";
   u8  hnb;
   s32 fd;
   u8  keeping = 0, res;
 
+  u8 fn[PATH_MAX];
+
   /* Update path frequency. */
   u32 cksum = hash32(afl->fsrv.trace_bits, MAP_SIZE, HASH_CONST);
 
@@ -556,16 +558,17 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
 
 #ifndef SIMPLE_FILES
 
-    fn = alloc_printf("%s/queue/id:%06u,%s", afl->out_dir, afl->queued_paths,
-                      describe_op(afl, hnb));
+    queue_fn = alloc_printf("%s/queue/id:%06u,%s", afl->out_dir,
+                            afl->queued_paths, describe_op(afl, hnb));
 
 #else
 
-    fn = alloc_printf("%s/queue/id_%06u", afl->out_dir, afl->queued_paths);
+    queue_fn =
+        alloc_printf("%s/queue/id_%06u", afl->out_dir, afl->queued_paths);
 
 #endif                                                    /* ^!SIMPLE_FILES */
 
-    add_to_queue(afl, fn, len, 0);
+    add_to_queue(afl, queue_fn, len, 0);
 
     if (hnb == 2) {
 
@@ -584,9 +587,9 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
     if (unlikely(res == FAULT_ERROR))
       FATAL("Unable to execute target application");
 
-    fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
-    if (unlikely(fd < 0)) PFATAL("Unable to create '%s'", fn);
-    ck_write(fd, mem, len, fn);
+    fd = open(queue_fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
+    if (unlikely(fd < 0)) PFATAL("Unable to create '%s'", queue_fn);
+    ck_write(fd, mem, len, queue_fn);
     close(fd);
 
     keeping = 1;
@@ -642,12 +645,13 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
 
 #ifndef SIMPLE_FILES
 
-      fn = alloc_printf("%s/hangs/id:%06llu,%s", afl->out_dir,
-                        afl->unique_hangs, describe_op(afl, 0));
+      snprintf(fn, PATH_MAX, "%s/hangs/id:%06llu,%s", afl->out_dir,
+               afl->unique_hangs, describe_op(afl, 0));
 
 #else
 
-      fn = alloc_printf("%s/hangs/id_%06llu", afl->out_dir, afl->unique_hangs);
+      snprintf(fn, PATH_MAX, "%s/hangs/id_%06llu", afl->out_dir,
+               afl->unique_hangs);
 
 #endif                                                    /* ^!SIMPLE_FILES */
 
@@ -685,14 +689,13 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
 
 #ifndef SIMPLE_FILES
 
-      fn = alloc_printf("%s/crashes/id:%06llu,sig:%02u,%s", afl->out_dir,
-                        afl->unique_crashes, afl->kill_signal,
-                        describe_op(afl, 0));
+      snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s", afl->out_dir,
+               afl->unique_crashes, afl->kill_signal, describe_op(afl, 0));
 
 #else
 
-      fn = alloc_printf("%s/crashes/id_%06llu_%02u", afl->out_dir,
-                        afl->unique_crashes, afl->kill_signal);
+      snprintf(fn, PATH_MAX, "%s/crashes/id_%06llu_%02u", afl->out_dir,
+               afl->unique_crashes, afl->kill_signal);
 
 #endif                                                    /* ^!SIMPLE_FILES */
 
@@ -729,8 +732,6 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
   ck_write(fd, mem, len, fn);
   close(fd);
 
-  ck_free(fn);
-
   return keeping;
 
 }
diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c
index 6c6f05ac..f932f33b 100644
--- a/src/afl-fuzz-cmplog.c
+++ b/src/afl-fuzz-cmplog.c
@@ -31,10 +31,9 @@
 
 void init_cmplog_forkserver(afl_state_t *afl) {
 
-  struct timeval timeout;
-  int            st_pipe[2], ctl_pipe[2];
-  int            status;
-  s32            rlen;
+  int st_pipe[2], ctl_pipe[2];
+  int status;
+  s32 rlen;
 
   ACTF("Spinning up the cmplog fork server...");
 
@@ -185,21 +184,19 @@ void init_cmplog_forkserver(afl_state_t *afl) {
   rlen = 0;
   if (afl->fsrv.exec_tmout) {
 
-    fd_set readfds;
-    FD_ZERO(&readfds);
-    FD_SET(afl->cmplog_fsrv_st_fd, &readfds);
-    timeout.tv_sec = ((afl->fsrv.exec_tmout * FORK_WAIT_MULT) / 1000);
-    timeout.tv_usec = ((afl->fsrv.exec_tmout * FORK_WAIT_MULT) % 1000) * 1000;
+    rlen = 4;
+    u32 timeout_ms = afl->fsrv.exec_tmout * FORK_WAIT_MULT;
+    /* Reuse readfds as exceptfds to see when the child closed the pipe */
+    u32 exec_ms = read_timed(afl->cmplog_fsrv_st_fd, &status, rlen, timeout_ms);
 
-    int sret =
-        select(afl->cmplog_fsrv_st_fd + 1, &readfds, NULL, NULL, &timeout);
+    if (!exec_ms) {
 
-    if (sret == 0) {
+      PFATAL("Error in timed read");
 
-      kill(afl->cmplog_fsrv_pid, SIGKILL);
-
-    } else {
+    } else if (exec_ms > timeout_ms) {
 
+      afl->fsrv.child_timed_out = 1;
+      kill(afl->cmplog_fsrv_pid, SIGKILL);
       rlen = read(afl->cmplog_fsrv_st_fd, &status, 4);
 
     }
@@ -213,6 +210,11 @@ void init_cmplog_forkserver(afl_state_t *afl) {
   /* If we have a four-byte "hello" message from the server, we're all set.
      Otherwise, try to figure out what went wrong. */
 
+  if (afl->fsrv.child_timed_out)
+    FATAL(
+        "Timeout while initializing cmplog fork server (adjusting -t may "
+        "help)");
+
   if (rlen == 4) {
 
     OKF("All right - fork server is up.");
@@ -220,11 +222,6 @@ void init_cmplog_forkserver(afl_state_t *afl) {
 
   }
 
-  if (afl->fsrv.child_timed_out)
-    FATAL(
-        "Timeout while initializing cmplog fork server (adjusting -t may "
-        "help)");
-
   if (waitpid(afl->cmplog_fsrv_pid, &status, 0) <= 0)
     PFATAL("waitpid() failed");
 
@@ -379,16 +376,12 @@ void init_cmplog_forkserver(afl_state_t *afl) {
 
 u8 run_cmplog_target(afl_state_t *afl, u32 timeout) {
 
-  struct timeval it;
-  int            status = 0;
-  int            sret;
-  u64            exec_ms;
+  int status = 0;
+  u32 exec_ms;
 
   u32 tb4;
   s32 res;
 
-  fd_set readfds;
-
   afl->fsrv.child_timed_out = 0;
 
   /* After this memset, afl->fsrv.trace_bits[] are effectively volatile, so we
@@ -423,18 +416,9 @@ u8 run_cmplog_target(afl_state_t *afl, u32 timeout) {
 
   /* Configure timeout, as requested by user, then wait for child to terminate.
    */
+  exec_ms = read_timed(afl->cmplog_fsrv_st_fd, &status, 4, timeout);
 
-  it.tv_sec = (timeout / 1000);
-  it.tv_usec = (timeout % 1000) * 1000;
-
-  FD_ZERO(&readfds);
-  FD_SET(afl->cmplog_fsrv_st_fd, &readfds);
-  it.tv_sec = ((timeout) / 1000);
-  it.tv_usec = ((timeout) % 1000) * 1000;
-
-  sret = select(afl->cmplog_fsrv_st_fd + 1, &readfds, NULL, NULL, &it);
-
-  if (sret == 0) {
+  if (exec_ms > timeout) {
 
     /* If there was no response from forkserver after timeout seconds,
     we kill the child. The forkserver should inform us afterwards */
@@ -442,9 +426,12 @@ u8 run_cmplog_target(afl_state_t *afl, u32 timeout) {
     kill(afl->cmplog_child_pid, SIGKILL);
     afl->fsrv.child_timed_out = 1;
 
+    /* After killing the child, the forkserver should tell us */
+    if (!read(afl->cmplog_fsrv_st_fd, &status, 4)) exec_ms = 0;
+
   }
 
-  if ((res = read(afl->cmplog_fsrv_st_fd, &status, 4)) != 4) {
+  if (!exec_ms) {  // Something went wrong.
 
     if (afl->stop_soon) return 0;
     SAYF("\n" cLRD "[-] " cRST
@@ -467,12 +454,8 @@ u8 run_cmplog_target(afl_state_t *afl, u32 timeout) {
 
   if (!WIFSTOPPED(status)) afl->cmplog_child_pid = 0;
 
-  exec_ms = (u64)timeout - (it.tv_sec * 1000 + it.tv_usec / 1000);
   if (afl->slowest_exec_ms < exec_ms) afl->slowest_exec_ms = exec_ms;
 
-  it.tv_sec = 0;
-  it.tv_usec = 0;
-
   ++afl->total_execs;
 
   /* Any subsequent operations on afl->fsrv.trace_bits must not be moved by the
@@ -527,8 +510,13 @@ u8 common_fuzz_cmplog_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
 
   if (afl->post_handler) {
 
-    out_buf = afl->post_handler(out_buf, &len);
-    if (!out_buf || !len) return 0;
+    u8 *post_buf = NULL;
+
+    size_t post_len =
+        afl->post_handler(afl->post_data, out_buf, len, &post_buf);
+    if (!post_buf || !post_len) return 0;
+    out_buf = post_buf;
+    len = post_len;
 
   }
 
diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c
index 038c4393..e2495524 100644
--- a/src/afl-fuzz-init.c
+++ b/src/afl-fuzz-init.c
@@ -76,21 +76,16 @@ void bind_to_free_cpu(afl_state_t *afl) {
 
   while ((de = readdir(d))) {
 
-    u8 *  fn;
+    u8    fn[PATH_MAX];
     FILE *f;
     u8    tmp[MAX_LINE];
     u8    has_vmsize = 0;
 
     if (!isdigit(de->d_name[0])) continue;
 
-    fn = alloc_printf("/proc/%s/status", de->d_name);
+    snprintf(fn, PATH_MAX, "/proc/%s/status", de->d_name);
 
-    if (!(f = fopen(fn, "r"))) {
-
-      ck_free(fn);
-      continue;
-
-    }
+    if (!(f = fopen(fn, "r"))) { continue; }
 
     while (fgets(tmp, MAX_LINE, f)) {
 
@@ -111,7 +106,6 @@ void bind_to_free_cpu(afl_state_t *afl) {
 
     }
 
-    ck_free(fn);
     fclose(f);
 
   }
@@ -276,7 +270,9 @@ void setup_post(afl_state_t *afl) {
 
   void *dh;
   u8 *  fn = afl->afl_env.afl_post_library;
+  u8    tbuf[6];
   u32   tlen = 6;
+  strncpy(tbuf, "hello", tlen);
 
   if (!fn) return;
 
@@ -287,10 +283,20 @@ void setup_post(afl_state_t *afl) {
 
   afl->post_handler = dlsym(dh, "afl_postprocess");
   if (!afl->post_handler) FATAL("Symbol 'afl_postprocess' not found.");
+  afl->post_init = dlsym(dh, "afl_postprocess_init");
+  if (!afl->post_init) FATAL("Symbol 'afl_postprocess_init' not found.");
+  afl->post_deinit = dlsym(dh, "afl_postprocess_deinit");
+  if (!afl->post_deinit) FATAL("Symbol 'afl_postprocess_deinit' not found.");
 
   /* Do a quick test. It's better to segfault now than later =) */
 
-  afl->post_handler("hello", &tlen);
+  u8 *post_buf = NULL;
+  afl->post_data = afl->post_init(afl);
+  if (!afl->post_data) FATAL("Could not initialize post handler.");
+
+  size_t post_len = afl->post_handler(afl->post_data, tbuf, tlen, &post_buf);
+  if (!post_len || !post_buf)
+    SAYF("Empty return in test post handler for buf=\"hello\\0\".");
 
   OKF("Postprocessor installed successfully.");
 
@@ -369,9 +375,10 @@ void read_testcases(afl_state_t *afl) {
 
     struct stat st;
 
+    u8 dfn[PATH_MAX];
+    snprintf(dfn, PATH_MAX, "%s/.state/deterministic_done/%s", afl->in_dir,
+             nl[i]->d_name);
     u8 *fn2 = alloc_printf("%s/%s", afl->in_dir, nl[i]->d_name);
-    u8 *dfn = alloc_printf("%s/.state/deterministic_done/%s", afl->in_dir,
-                           nl[i]->d_name);
 
     u8 passed_det = 0;
 
@@ -385,7 +392,6 @@ void read_testcases(afl_state_t *afl) {
     if (!S_ISREG(st.st_mode) || !st.st_size || strstr(fn2, "/README.txt")) {
 
       ck_free(fn2);
-      ck_free(dfn);
       continue;
 
     }
@@ -401,7 +407,6 @@ void read_testcases(afl_state_t *afl) {
        and probably very time-consuming. */
 
     if (!access(dfn, F_OK)) passed_det = 1;
-    ck_free(dfn);
 
     add_to_queue(afl, fn2, st.st_size, passed_det);
 
diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c
index 0ded4ba1..754b2190 100644
--- a/src/afl-fuzz-mutators.c
+++ b/src/afl-fuzz-mutators.c
@@ -7,6 +7,7 @@
    Now maintained by  Marc Heuse <mh@mh-sec.de>,
                         Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
                         Andrea Fioraldi <andreafioraldi@gmail.com>
+                        Dominik Maier <mail@dmnk.co>
 
    Copyright 2016, 2017 Google Inc. All rights reserved.
    Copyright 2019-2020 AFLplusplus Project. All rights reserved.
@@ -78,8 +79,15 @@ void destroy_custom_mutator(afl_state_t *afl) {
 
     afl->mutator->afl_custom_deinit(afl->mutator->data);
 
-    if (afl->mutator->dh)
-      dlclose(afl->mutator->dh);
+    if (afl->mutator->dh) dlclose(afl->mutator->dh);
+
+    if (afl->mutator->pre_save_buf) {
+
+      ck_free(afl->mutator->pre_save_buf);
+      afl->mutator->pre_save_buf = NULL;
+      afl->mutator->pre_save_size = 0;
+
+    }
 
     ck_free(afl->mutator);
     afl->mutator = NULL;
@@ -92,6 +100,8 @@ void load_custom_mutator(afl_state_t *afl, const char *fn) {
 
   void *dh;
   afl->mutator = ck_alloc(sizeof(struct custom_mutator));
+  afl->mutator->pre_save_buf = NULL;
+  afl->mutator->pre_save_size = 0;
 
   afl->mutator->name = fn;
   ACTF("Loading custom mutator library from '%s'...", fn);
@@ -103,11 +113,13 @@ void load_custom_mutator(afl_state_t *afl, const char *fn) {
   /* Mutator */
   /* "afl_custom_init", required */
   afl->mutator->afl_custom_init = dlsym(dh, "afl_custom_init");
-  if (!afl->mutator->afl_custom_init) FATAL("Symbol 'afl_custom_init' not found.");
+  if (!afl->mutator->afl_custom_init)
+    FATAL("Symbol 'afl_custom_init' not found.");
 
   /* "afl_custom_deinit", required */
   afl->mutator->afl_custom_deinit = dlsym(dh, "afl_custom_deinit");
-  if (!afl->mutator->afl_custom_deinit) FATAL("Symbol 'afl_custom_deinit' not found.");
+  if (!afl->mutator->afl_custom_deinit)
+    FATAL("Symbol 'afl_custom_deinit' not found.");
 
   /* "afl_custom_fuzz" or "afl_custom_mutator", required */
   afl->mutator->afl_custom_fuzz = dlsym(dh, "afl_custom_fuzz");
@@ -181,7 +193,8 @@ void load_custom_mutator(afl_state_t *afl, const char *fn) {
 
   /* Initialize the custom mutator */
   if (afl->mutator->afl_custom_init)
-    afl->mutator->afl_custom_init(afl, rand_below(afl, 0xFFFFFFFF));
+    afl->mutator->data =
+        afl->mutator->afl_custom_init(afl, rand_below(afl, 0xFFFFFFFF));
 
 }
 
@@ -198,24 +211,28 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
 
   /* Initialize trimming in the custom mutator */
   afl->stage_cur = 0;
-  afl->stage_max = afl->mutator->afl_custom_init_trim(afl->mutator->data, in_buf, q->len);
-
+  afl->stage_max =
+      afl->mutator->afl_custom_init_trim(afl->mutator->data, in_buf, q->len);
+  if (unlikely(afl->stage_max) < 0)
+    FATAL("custom_init_trim error ret: %d", afl->stage_max);
   if (afl->not_on_tty && afl->debug)
     SAYF("[Custom Trimming] START: Max %d iterations, %u bytes", afl->stage_max,
          q->len);
 
   while (afl->stage_cur < afl->stage_max) {
 
-    sprintf(afl->stage_name_buf, "ptrim %s", u_stringify_int(val_buf, trim_exec));
+    u8 *retbuf = NULL;
 
-    u32 cksum;
+    sprintf(afl->stage_name_buf, "ptrim %s",
+            u_stringify_int(val_buf, trim_exec));
 
-    u8 *   retbuf = NULL;
-    size_t retlen = 0;
+    u32 cksum;
 
-    afl->mutator->afl_custom_trim(afl, &retbuf, &retlen);
+    size_t retlen = afl->mutator->afl_custom_trim(afl->mutator->data, &retbuf);
 
-    if (retlen > orig_len)
+    if (unlikely(!retbuf))
+      FATAL("custom_trim failed (ret %zd)", retlen);
+    else if (unlikely(retlen > orig_len))
       FATAL(
           "Trimmed data returned by custom mutator is larger than original "
           "data");
@@ -225,12 +242,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
     fault = run_target(afl, afl->fsrv.exec_tmout);
     ++afl->trim_execs;
 
-    if (afl->stop_soon || fault == FAULT_ERROR) {
-
-      ck_free(retbuf);
-      goto abort_trimming;
-
-    }
+    if (afl->stop_soon || fault == FAULT_ERROR) { goto abort_trimming; }
 
     cksum = hash32(afl->fsrv.trace_bits, MAP_SIZE, HASH_CONST);
 
@@ -250,7 +262,8 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
       }
 
       /* Tell the custom mutator that the trimming was successful */
-      afl->stage_cur = afl->mutator->afl_custom_post_trim(afl, 1);
+      afl->stage_cur =
+          afl->mutator->afl_custom_post_trim(afl->mutator->data, 1);
 
       if (afl->not_on_tty && afl->debug)
         SAYF("[Custom Trimming] SUCCESS: %d/%d iterations (now at %u bytes)",
@@ -259,15 +272,16 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
     } else {
 
       /* Tell the custom mutator that the trimming was unsuccessful */
-      afl->stage_cur = afl->mutator->afl_custom_post_trim(afl, 0);
+      afl->stage_cur =
+          afl->mutator->afl_custom_post_trim(afl->mutator->data, 0);
+      if (unlikely(afl->stage_cur < 0))
+        FATAL("Error ret in custom_post_trim: %d", afl->stage_cur);
       if (afl->not_on_tty && afl->debug)
         SAYF("[Custom Trimming] FAILURE: %d/%d iterations", afl->stage_cur,
              afl->stage_max);
 
     }
 
-    ck_free(retbuf);
-
     /* Since this can be slow, update the screen every now and then. */
 
     if (!(trim_exec++ % afl->stats_update_freq)) show_stats(afl);
@@ -304,3 +318,4 @@ abort_trimming:
   return fault;
 
 }
+
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index cc150cfe..b20bde90 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -347,6 +347,9 @@ u8 fuzz_one_original(afl_state_t *afl) {
   u8  a_collect[MAX_AUTO_EXTRA];
   u32 a_len = 0;
 
+/* Not pretty, but saves a lot of writing */
+#define BUF_PARAMS(name) (void **)&afl->name##_buf, &afl->name##_size
+
 #ifdef IGNORE_FINDS
 
   /* In IGNORE_FINDS mode, skip any entries that weren't in the
@@ -360,7 +363,8 @@ u8 fuzz_one_original(afl_state_t *afl) {
 
     /* The custom mutator will decide to skip this test case or not. */
 
-    if (!afl->mutator->afl_custom_queue_get(afl, afl->queue_cur->fname))
+    if (!afl->mutator->afl_custom_queue_get(afl->mutator->data,
+                                            afl->queue_cur->fname))
       return 1;
 
   }
@@ -426,7 +430,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
      single byte anyway, so it wouldn't give us any performance or memory usage
      benefits. */
 
-  out_buf = ck_alloc_nozero(len);
+  out_buf = ck_maybe_grow(BUF_PARAMS(out), len);
 
   afl->subseq_tmouts = 0;
 
@@ -718,7 +722,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
   /* Initialize effector map for the next step (see comments below). Always
      flag first and last byte as doing something. */
 
-  eff_map = ck_alloc(EFF_ALEN(len));
+  eff_map = ck_maybe_grow(BUF_PARAMS(eff), EFF_ALEN(len));
   eff_map[0] = 1;
 
   if (EFF_APOS(len - 1) != 0) {
@@ -1442,7 +1446,7 @@ skip_interest:
 
   orig_hit_cnt = new_hit_cnt;
 
-  ex_tmp = ck_alloc(len + MAX_DICT_FILE);
+  ex_tmp = ck_maybe_grow(BUF_PARAMS(ex), len + MAX_DICT_FILE);
 
   for (i = 0; i <= len; ++i) {
 
@@ -1465,7 +1469,6 @@ skip_interest:
 
       if (common_fuzz_stuff(afl, ex_tmp, len + afl->extras[j].len)) {
 
-        ck_free(ex_tmp);
         goto abandon_entry;
 
       }
@@ -1479,8 +1482,6 @@ skip_interest:
 
   }
 
-  ck_free(ex_tmp);
-
   new_hit_cnt = afl->queued_paths + afl->unique_crashes;
 
   afl->stage_finds[STAGE_EXTRAS_UI] += new_hit_cnt - orig_hit_cnt;
@@ -1606,18 +1607,23 @@ custom_mutator_stage:
     /* Read the additional testcase into a new buffer. */
     fd = open(target->fname, O_RDONLY);
     if (unlikely(fd < 0)) PFATAL("Unable to open '%s'", target->fname);
-    new_buf = ck_alloc_nozero(target->len);
+
+    new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), target->len);
     ck_read(fd, new_buf, target->len, target->fname);
     close(fd);
 
+    u8 *mutated_buf = NULL;
+
     size_t mutated_size = afl->mutator->afl_custom_fuzz(
-        afl, &out_buf, len, new_buf, target->len, max_seed_size);
+        afl->mutator->data, out_buf, len, &mutated_buf, new_buf, target->len,
+        max_seed_size);
 
-    ck_free(new_buf);
+    if (unlikely(!mutated_buf))
+      FATAL("Error in custom_fuzz. Size returned: %zd", mutated_size);
 
     if (mutated_size > 0) {
 
-      if (common_fuzz_stuff(afl, out_buf, (u32)mutated_size)) {
+      if (common_fuzz_stuff(afl, mutated_buf, (u32)mutated_size)) {
 
         goto abandon_entry;
 
@@ -1641,7 +1647,8 @@ custom_mutator_stage:
 
     }
 
-    if (mutated_size < len) out_buf = ck_realloc(out_buf, len);
+    /* `(afl->)out_buf` may have been changed by the call to custom_fuzz */
+    /* TODO: Only do this when `mutated_buf` == `out_buf`? Branch vs Memcpy. */
     memcpy(out_buf, in_buf, len);
 
   }
@@ -1702,7 +1709,7 @@ havoc_stage:
   if (stacked_custom && afl->mutator->afl_custom_havoc_mutation_probability) {
 
     stacked_custom_prob =
-        afl->mutator->afl_custom_havoc_mutation_probability(afl);
+        afl->mutator->afl_custom_havoc_mutation_probability(afl->mutator->data);
     if (stacked_custom_prob > 100)
       FATAL(
           "The probability returned by afl_custom_havoc_mutation_propability "
@@ -1723,8 +1730,22 @@ havoc_stage:
 
       if (stacked_custom && rand_below(afl, 100) < stacked_custom_prob) {
 
-        temp_len = afl->mutator->afl_custom_havoc_mutation(afl, &out_buf,
-                                                           temp_len, MAX_FILE);
+        u8 *   custom_havoc_buf = NULL;
+        size_t new_len = afl->mutator->afl_custom_havoc_mutation(
+            afl->mutator->data, out_buf, temp_len, &custom_havoc_buf, MAX_FILE);
+        if (unlikely(!custom_havoc_buf))
+          FATAL("Error in custom_havoc (return %zd)", new_len);
+        if (likely(new_len > 0 && custom_havoc_buf)) {
+
+          temp_len = new_len;
+          if (out_buf != custom_havoc_buf) {
+
+            ck_maybe_grow(BUF_PARAMS(out), temp_len);
+            memcpy(out_buf, custom_havoc_buf, temp_len);
+
+          }
+
+        }
 
       }
 
@@ -1954,7 +1975,8 @@ havoc_stage:
 
             clone_to = rand_below(afl, temp_len);
 
-            new_buf = ck_alloc_nozero(temp_len + clone_len);
+            new_buf =
+                ck_maybe_grow(BUF_PARAMS(out_scratch), temp_len + clone_len);
 
             /* Head */
 
@@ -1974,8 +1996,9 @@ havoc_stage:
             memcpy(new_buf + clone_to + clone_len, out_buf + clone_to,
                    temp_len - clone_to);
 
-            ck_free(out_buf);
+            swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch));
             out_buf = new_buf;
+            new_buf = NULL;
             temp_len += clone_len;
 
           }
@@ -2068,7 +2091,8 @@ havoc_stage:
 
             if (temp_len + extra_len >= MAX_FILE) break;
 
-            new_buf = ck_alloc_nozero(temp_len + extra_len);
+            new_buf =
+                ck_maybe_grow(BUF_PARAMS(out_scratch), temp_len + extra_len);
 
             /* Head */
             memcpy(new_buf, out_buf, insert_at);
@@ -2084,7 +2108,8 @@ havoc_stage:
 
             if (temp_len + extra_len >= MAX_FILE) break;
 
-            new_buf = ck_alloc_nozero(temp_len + extra_len);
+            new_buf =
+                ck_maybe_grow(BUF_PARAMS(out_scratch), temp_len + extra_len);
 
             /* Head */
             memcpy(new_buf, out_buf, insert_at);
@@ -2098,8 +2123,9 @@ havoc_stage:
           memcpy(new_buf + insert_at + extra_len, out_buf + insert_at,
                  temp_len - insert_at);
 
-          ck_free(out_buf);
+          swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch));
           out_buf = new_buf;
+          new_buf = NULL;
           temp_len += extra_len;
 
           break;
@@ -2115,7 +2141,7 @@ havoc_stage:
     /* out_buf might have been mangled a bit, so let's restore it to its
        original size and shape. */
 
-    if (temp_len < len) out_buf = ck_realloc(out_buf, len);
+    out_buf = ck_maybe_grow(BUF_PARAMS(out), len);
     temp_len = len;
     memcpy(out_buf, in_buf, len);
 
@@ -2177,7 +2203,6 @@ retry_splicing:
 
     if (in_buf != orig_in) {
 
-      ck_free(in_buf);
       in_buf = orig_in;
       len = afl->queue_cur->len;
 
@@ -2221,7 +2246,7 @@ retry_splicing:
 
     if (unlikely(fd < 0)) PFATAL("Unable to open '%s'", target->fname);
 
-    new_buf = ck_alloc_nozero(target->len);
+    new_buf = ck_maybe_grow(BUF_PARAMS(in_scratch), target->len);
 
     ck_read(fd, new_buf, target->len, target->fname);
 
@@ -2233,12 +2258,7 @@ retry_splicing:
 
     locate_diffs(in_buf, new_buf, MIN(len, target->len), &f_diff, &l_diff);
 
-    if (f_diff < 0 || l_diff < 2 || f_diff == l_diff) {
-
-      ck_free(new_buf);
-      goto retry_splicing;
-
-    }
+    if (f_diff < 0 || l_diff < 2 || f_diff == l_diff) { goto retry_splicing; }
 
     /* Split somewhere between the first and last differing byte. */
 
@@ -2248,10 +2268,10 @@ retry_splicing:
 
     len = target->len;
     memcpy(new_buf, in_buf, split_at);
+    swap_bufs(BUF_PARAMS(in), BUF_PARAMS(in_scratch));
     in_buf = new_buf;
 
-    ck_free(out_buf);
-    out_buf = ck_alloc_nozero(len);
+    out_buf = ck_maybe_grow(BUF_PARAMS(out), len);
     memcpy(out_buf, in_buf, len);
 
     goto custom_mutator_stage;
@@ -2279,12 +2299,14 @@ radamsa_stage:
 
   orig_hit_cnt = afl->queued_paths + afl->unique_crashes;
 
-  /* Read the additional testcase into a new buffer. */
-  u8 *save_buf = ck_alloc_nozero(len);
+  /* Read the additional testcase.
+  We'll reuse in_scratch, as it is free at this point.
+  */
+  u8 *save_buf = ck_maybe_grow(BUF_PARAMS(in_scratch), len);
   memcpy(save_buf, out_buf, len);
 
   u32 max_len = len + choose_block_len(afl, HAVOC_BLK_XL);
-  u8 *new_buf = ck_alloc_nozero(max_len);
+  u8 *new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), max_len);
   u8 *tmp_buf;
 
   for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) {
@@ -2304,19 +2326,10 @@ radamsa_stage:
 
     }
 
-    if (common_fuzz_stuff(afl, tmp_buf, temp_len)) {
-
-      ck_free(save_buf);
-      ck_free(new_buf);
-      goto abandon_entry;
-
-    }
+    if (common_fuzz_stuff(afl, tmp_buf, temp_len)) { goto abandon_entry; }
 
   }
 
-  ck_free(save_buf);
-  ck_free(new_buf);
-
   new_hit_cnt = afl->queued_paths + afl->unique_crashes;
 
   afl->stage_finds[STAGE_RADAMSA] += new_hit_cnt - orig_hit_cnt;
@@ -2346,10 +2359,6 @@ abandon_entry:
 
   munmap(orig_in, afl->queue_cur->len);
 
-  if (in_buf != orig_in) ck_free(in_buf);
-  ck_free(out_buf);
-  ck_free(eff_map);
-
   return ret_val;
 
 #undef FLIP_BIT
@@ -2448,7 +2457,7 @@ u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
      single byte anyway, so it wouldn't give us any performance or memory usage
      benefits. */
 
-  out_buf = ck_alloc_nozero(len);
+  out_buf = ck_maybe_grow(BUF_PARAMS(out), len);
 
   afl->subseq_tmouts = 0;
 
@@ -2727,7 +2736,7 @@ u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
   /* Initialize effector map for the next step (see comments below). Always
          flag first and last byte as doing something. */
 
-  eff_map = ck_alloc(EFF_ALEN(len));
+  eff_map = ck_maybe_grow(BUF_PARAMS(eff), EFF_ALEN(len));
   eff_map[0] = 1;
 
   if (EFF_APOS(len - 1) != 0) {
@@ -3451,7 +3460,7 @@ skip_interest:
 
   orig_hit_cnt = new_hit_cnt;
 
-  ex_tmp = ck_alloc(len + MAX_DICT_FILE);
+  ex_tmp = ck_maybe_grow(BUF_PARAMS(ex), len + MAX_DICT_FILE);
 
   for (i = 0; i <= len; ++i) {
 
@@ -3474,7 +3483,6 @@ skip_interest:
 
       if (common_fuzz_stuff(afl, ex_tmp, len + afl->extras[j].len)) {
 
-        ck_free(ex_tmp);
         goto abandon_entry;
 
       }
@@ -3488,8 +3496,6 @@ skip_interest:
 
   }                                                  /* for i = 0; i <= len */
 
-  ck_free(ex_tmp);
-
   new_hit_cnt = afl->queued_paths + afl->unique_crashes;
 
   afl->stage_finds[STAGE_EXTRAS_UI] += new_hit_cnt - orig_hit_cnt;
@@ -3893,7 +3899,8 @@ pacemaker_fuzzing:
 
                 clone_to = rand_below(afl, temp_len);
 
-                new_buf = ck_alloc_nozero(temp_len + clone_len);
+                new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch),
+                                        temp_len + clone_len);
 
                 /* Head */
 
@@ -3914,7 +3921,7 @@ pacemaker_fuzzing:
                 memcpy(new_buf + clone_to + clone_len, out_buf + clone_to,
                        temp_len - clone_to);
 
-                ck_free(out_buf);
+                swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch));
                 out_buf = new_buf;
                 temp_len += clone_len;
                 MOpt_globals.cycles_v2[STAGE_Clone75] += 1;
@@ -3967,7 +3974,7 @@ pacemaker_fuzzing:
         /* out_buf might have been mangled a bit, so let's restore it to its
            original size and shape. */
 
-        if (temp_len < len) out_buf = ck_realloc(out_buf, len);
+        out_buf = ck_maybe_grow(BUF_PARAMS(out), len);
         temp_len = len;
         memcpy(out_buf, in_buf, len);
 
@@ -4045,7 +4052,6 @@ pacemaker_fuzzing:
 
         if (in_buf != orig_in) {
 
-          ck_free(in_buf);
           in_buf = orig_in;
           len = afl->queue_cur->len;
 
@@ -4090,7 +4096,7 @@ pacemaker_fuzzing:
 
         if (fd < 0) PFATAL("Unable to open '%s'", target->fname);
 
-        new_buf = ck_alloc_nozero(target->len);
+        new_buf = ck_maybe_grow(BUF_PARAMS(in_scratch), target->len);
 
         ck_read(fd, new_buf, target->len, target->fname);
 
@@ -4104,7 +4110,6 @@ pacemaker_fuzzing:
 
         if (f_diff < 0 || l_diff < 2 || f_diff == l_diff) {
 
-          ck_free(new_buf);
           goto retry_splicing_puppet;
 
         }
@@ -4117,9 +4122,9 @@ pacemaker_fuzzing:
 
         len = target->len;
         memcpy(new_buf, in_buf, split_at);
+        swap_bufs(BUF_PARAMS(in), BUF_PARAMS(in_scratch));
         in_buf = new_buf;
-        ck_free(out_buf);
-        out_buf = ck_alloc_nozero(len);
+        out_buf = ck_maybe_grow(BUF_PARAMS(out), len);
         memcpy(out_buf, in_buf, len);
 
         goto havoc_stage_puppet;
@@ -4154,10 +4159,6 @@ pacemaker_fuzzing:
 
       munmap(orig_in, afl->queue_cur->len);
 
-      if (in_buf != orig_in) ck_free(in_buf);
-      ck_free(out_buf);
-      ck_free(eff_map);
-
       if (afl->key_puppet == 1) {
 
         if (unlikely(
@@ -4379,18 +4380,13 @@ u8 fuzz_one(afl_state_t *afl) {
   int key_val_lv = 0;
 
 #ifdef _AFL_DOCUMENT_MUTATIONS
-  if (afl->do_document == 0) {
-
-    char *fn = alloc_printf("%s/mutations", afl->out_dir);
-    if (fn) {
 
-      afl->do_document = mkdir(fn, 0700);  // if it exists we do not care
-      afl->do_document = 1;
-      ck_free(fn);
-
-    } else
+  u8 path_buf[PATH_MAX];
+  if (afl->do_document == 0) {
 
-      PFATAL("malloc()");
+    snprintf(path_buf, PATH_MAX, "%s/mutations", afl->out_dir);
+    afl->do_document = mkdir(path_buf, 0700);  // if it exists we do not care
+    afl->do_document = 1;
 
   } else {
 
@@ -4418,5 +4414,7 @@ u8 fuzz_one(afl_state_t *afl) {
 
   return key_val_lv;
 
+#undef BUF_PARAMS
+
 }
 
diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c
index d3027d2b..12c3a09d 100644
--- a/src/afl-fuzz-python.c
+++ b/src/afl-fuzz-python.c
@@ -29,19 +29,28 @@
 #ifdef USE_PYTHON
 
 static void *unsupported(afl_state_t *afl, unsigned int seed) {
+
   FATAL("Python Mutator cannot be called twice yet");
   return NULL;
+
 }
 
-size_t fuzz_py(void *py_mutator, u8 **buf, size_t buf_size, u8 *add_buf,
-               size_t add_buf_size, size_t max_size) {
+/* sorry for this makro...
+it just fills in `&py_mutator->something_buf, &py_mutator->something_size`. */
+#define BUF_PARAMS(name)                              \
+  (void **)&((py_mutator_t *)py_mutator)->name##_buf, \
+      &((py_mutator_t *)py_mutator)->name##_size
+
+size_t fuzz_py(void *py_mutator, u8 *buf, size_t buf_size, u8 **out_buf,
+               u8 *add_buf, size_t add_buf_size, size_t max_size) {
 
   size_t    mutated_size;
   PyObject *py_args, *py_value;
   py_args = PyTuple_New(3);
+  py_mutator_t *py = (py_mutator_t *)py_mutator;
 
   /* buf */
-  py_value = PyByteArray_FromStringAndSize(*buf, buf_size);
+  py_value = PyByteArray_FromStringAndSize(buf, buf_size);
   if (!py_value) {
 
     Py_DECREF(py_args);
@@ -77,29 +86,29 @@ size_t fuzz_py(void *py_mutator, u8 **buf, size_t buf_size, u8 *add_buf,
 
   PyTuple_SetItem(py_args, 2, py_value);
 
-  py_value = PyObject_CallObject(((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_FUZZ], py_args);
+  py_value = PyObject_CallObject(py->py_functions[PY_FUNC_FUZZ], py_args);
 
   Py_DECREF(py_args);
 
   if (py_value != NULL) {
 
     mutated_size = PyByteArray_Size(py_value);
-    if (buf_size < mutated_size) *buf = ck_realloc(*buf, mutated_size);
 
-    memcpy(*buf, PyByteArray_AsString(py_value), mutated_size);
+    *out_buf = ck_maybe_grow(BUF_PARAMS(fuzz), mutated_size);
+
+    memcpy(*out_buf, PyByteArray_AsString(py_value), mutated_size);
     Py_DECREF(py_value);
     return mutated_size;
 
   } else {
 
     PyErr_Print();
-    FATAL("Call failed");
+    FATAL("python custom fuzz: call failed");
 
   }
 
 }
 
-
 static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
 
   if (!module_name) return NULL;
@@ -124,8 +133,8 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
   if (py_module != NULL) {
 
     u8 py_notrim = 0, py_idx;
+    /* init, required */
     py_functions[PY_FUNC_INIT] = PyObject_GetAttrString(py_module, "init");
-    py_functions[PY_FUNC_DEINIT] = PyObject_GetAttrString(py_module, "deinit");
     py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "fuzz");
     py_functions[PY_FUNC_PRE_SAVE] =
         PyObject_GetAttrString(py_module, "pre_save");
@@ -142,6 +151,7 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
         PyObject_GetAttrString(py_module, "queue_get");
     py_functions[PY_FUNC_QUEUE_NEW_ENTRY] =
         PyObject_GetAttrString(py_module, "queue_new_entry");
+    py_functions[PY_FUNC_DEINIT] = PyObject_GetAttrString(py_module, "deinit");
 
     for (py_idx = 0; py_idx < PY_FUNC_COUNT; ++py_idx) {
 
@@ -223,7 +233,8 @@ void finalize_py_module(void *py_mutator) {
 
 }
 
-static void init_py(afl_state_t *afl, py_mutator_t *py_mutator, unsigned int seed) {
+static void init_py(afl_state_t *afl, py_mutator_t *py_mutator,
+                    unsigned int seed) {
 
   PyObject *py_args, *py_value;
 
@@ -244,7 +255,8 @@ static void init_py(afl_state_t *afl, py_mutator_t *py_mutator, unsigned int see
 
   PyTuple_SetItem(py_args, 0, py_value);
 
-  py_value = PyObject_CallObject(py_mutator->py_functions[PY_FUNC_INIT], py_args);
+  py_value =
+      PyObject_CallObject(py_mutator->py_functions[PY_FUNC_INIT], py_args);
 
   Py_DECREF(py_args);
 
@@ -283,15 +295,16 @@ void deinit_py(void *py_mutator) {
 void load_custom_mutator_py(afl_state_t *afl, char *module_name) {
 
   afl->mutator = ck_alloc(sizeof(struct custom_mutator));
+  afl->mutator->pre_save_buf = NULL;
+  afl->mutator->pre_save_size = 0;
 
   afl->mutator->name = module_name;
   ACTF("Loading Python mutator library from '%s'...", module_name);
 
   py_mutator_t *py_mutator;
   py_mutator = init_py_module(afl, module_name);
-  if (!py_mutator) {
-    FATAL("Failed to load python mutator.");
-  }
+  afl->mutator->data = py_mutator;
+  if (!py_mutator) { FATAL("Failed to load python mutator."); }
 
   PyObject **py_functions = py_mutator->py_functions;
 
@@ -334,44 +347,50 @@ void load_custom_mutator_py(afl_state_t *afl, char *module_name) {
 
 }
 
-
 size_t pre_save_py(void *py_mutator, u8 *buf, size_t buf_size, u8 **out_buf) {
 
-  size_t    out_buf_size;
-  PyObject *py_args, *py_value;
+  size_t        py_out_buf_size;
+  PyObject *    py_args, *py_value;
+  py_mutator_t *py = (py_mutator_t *)py_mutator;
+
   py_args = PyTuple_New(1);
   py_value = PyByteArray_FromStringAndSize(buf, buf_size);
   if (!py_value) {
 
     Py_DECREF(py_args);
-    FATAL("Failed to convert arguments");
+    FATAL("Failed to convert arguments in custom pre_save");
 
   }
 
   PyTuple_SetItem(py_args, 0, py_value);
 
-  py_value = PyObject_CallObject(((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_PRE_SAVE], py_args);
+  py_value = PyObject_CallObject(
+      ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_PRE_SAVE], py_args);
 
   Py_DECREF(py_args);
 
   if (py_value != NULL) {
 
-    out_buf_size = PyByteArray_Size(py_value);
-    *out_buf = malloc(out_buf_size);
-    memcpy(*out_buf, PyByteArray_AsString(py_value), out_buf_size);
+    py_out_buf_size = PyByteArray_Size(py_value);
+
+    ck_maybe_grow(BUF_PARAMS(pre_save), py_out_buf_size);
+
+    memcpy(py->pre_save_buf, PyByteArray_AsString(py_value), py_out_buf_size);
     Py_DECREF(py_value);
-    return out_buf_size;
+
+    *out_buf = py->pre_save_buf;
+    return py_out_buf_size;
 
   } else {
 
     PyErr_Print();
-    FATAL("Call failed");
+    FATAL("Python custom mutator: pre_save call failed.");
 
   }
 
 }
 
-u32 init_trim_py(void *py_mutator, u8 *buf, size_t buf_size) {
+s32 init_trim_py(void *py_mutator, u8 *buf, size_t buf_size) {
 
   PyObject *py_args, *py_value;
 
@@ -386,7 +405,8 @@ u32 init_trim_py(void *py_mutator, u8 *buf, size_t buf_size) {
 
   PyTuple_SetItem(py_args, 0, py_value);
 
-  py_value = PyObject_CallObject(((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_INIT_TRIM], py_args);
+  py_value = PyObject_CallObject(
+      ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_INIT_TRIM], py_args);
   Py_DECREF(py_args);
 
   if (py_value != NULL) {
@@ -408,7 +428,7 @@ u32 init_trim_py(void *py_mutator, u8 *buf, size_t buf_size) {
 
 }
 
-u32 post_trim_py(void *py_mutator, u8 success) {
+s32 post_trim_py(void *py_mutator, u8 success) {
 
   PyObject *py_args, *py_value;
 
@@ -424,7 +444,8 @@ u32 post_trim_py(void *py_mutator, u8 success) {
 
   PyTuple_SetItem(py_args, 0, py_value);
 
-  py_value = PyObject_CallObject(((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_POST_TRIM], py_args);
+  py_value = PyObject_CallObject(
+      ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_POST_TRIM], py_args);
   Py_DECREF(py_args);
 
   if (py_value != NULL) {
@@ -446,19 +467,21 @@ u32 post_trim_py(void *py_mutator, u8 success) {
 
 }
 
-void trim_py(void *py_mutator, u8 **out_buf, size_t *out_buf_size) {
+size_t trim_py(void *py_mutator, u8 **out_buf) {
 
   PyObject *py_args, *py_value;
+  size_t    ret;
 
   py_args = PyTuple_New(0);
-  py_value = PyObject_CallObject(((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_TRIM], py_args);
+  py_value = PyObject_CallObject(
+      ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_TRIM], py_args);
   Py_DECREF(py_args);
 
   if (py_value != NULL) {
 
-    *out_buf_size = PyByteArray_Size(py_value);
-    *out_buf = malloc(*out_buf_size);
-    memcpy(*out_buf, PyByteArray_AsString(py_value), *out_buf_size);
+    ret = PyByteArray_Size(py_value);
+    *out_buf = ck_maybe_grow(BUF_PARAMS(trim), ret);
+    memcpy(*out_buf, PyByteArray_AsString(py_value), ret);
     Py_DECREF(py_value);
 
   } else {
@@ -468,17 +491,19 @@ void trim_py(void *py_mutator, u8 **out_buf, size_t *out_buf_size) {
 
   }
 
+  return ret;
+
 }
 
-size_t havoc_mutation_py(void *py_mutator, u8 **buf, size_t buf_size,
-                         size_t max_size) {
+size_t havoc_mutation_py(void *py_mutator, u8 *buf, size_t buf_size,
+                         u8 **out_buf, size_t max_size) {
 
   size_t    mutated_size;
   PyObject *py_args, *py_value;
   py_args = PyTuple_New(2);
 
   /* buf */
-  py_value = PyByteArray_FromStringAndSize(*buf, buf_size);
+  py_value = PyByteArray_FromStringAndSize(buf, buf_size);
   if (!py_value) {
 
     Py_DECREF(py_args);
@@ -503,17 +528,28 @@ size_t havoc_mutation_py(void *py_mutator, u8 **buf, size_t buf_size,
 
   PyTuple_SetItem(py_args, 1, py_value);
 
-  py_value =
-      PyObject_CallObject(((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_HAVOC_MUTATION], py_args);
+  py_value = PyObject_CallObject(
+      ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_HAVOC_MUTATION],
+      py_args);
 
   Py_DECREF(py_args);
 
   if (py_value != NULL) {
 
     mutated_size = PyByteArray_Size(py_value);
-    if (buf_size < mutated_size) *buf = ck_realloc(*buf, mutated_size);
+    if (mutated_size <= buf_size) {
 
-    memcpy(*buf, PyByteArray_AsString(py_value), mutated_size);
+      /* We reuse the input buf here. */
+      *out_buf = buf;
+
+    } else {
+
+      /* A new buf is needed... */
+      *out_buf = ck_maybe_grow(BUF_PARAMS(havoc), mutated_size);
+
+    }
+
+    memcpy(*out_buf, PyByteArray_AsString(py_value), mutated_size);
 
     Py_DECREF(py_value);
     return mutated_size;
@@ -533,7 +569,9 @@ u8 havoc_mutation_probability_py(void *py_mutator) {
 
   py_args = PyTuple_New(0);
   py_value = PyObject_CallObject(
-      ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_HAVOC_MUTATION_PROBABILITY], py_args);
+      ((py_mutator_t *)py_mutator)
+          ->py_functions[PY_FUNC_HAVOC_MUTATION_PROBABILITY],
+      py_args);
   Py_DECREF(py_args);
 
   if (py_value != NULL) {
@@ -573,7 +611,8 @@ u8 queue_get_py(void *py_mutator, const u8 *filename) {
   PyTuple_SetItem(py_args, 0, py_value);
 
   // Call Python function
-  py_value = PyObject_CallObject(((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_QUEUE_GET], py_args);
+  py_value = PyObject_CallObject(
+      ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_QUEUE_GET], py_args);
   Py_DECREF(py_args);
 
   if (py_value != NULL) {
@@ -642,8 +681,9 @@ void queue_new_entry_py(void *py_mutator, const u8 *filename_new_queue,
   PyTuple_SetItem(py_args, 1, py_value);
 
   // Call
-  py_value =
-      PyObject_CallObject(((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_QUEUE_NEW_ENTRY], py_args);
+  py_value = PyObject_CallObject(
+      ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_QUEUE_NEW_ENTRY],
+      py_args);
   Py_DECREF(py_args);
 
   if (py_value == NULL) {
@@ -655,5 +695,7 @@ void queue_new_entry_py(void *py_mutator, const u8 *filename_new_queue,
 
 }
 
+#undef BUF_PARAMS
+
 #endif                                                        /* USE_PYTHON */
 
diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c
index f49e1f1e..92cbab6f 100644
--- a/src/afl-fuzz-queue.c
+++ b/src/afl-fuzz-queue.c
@@ -30,18 +30,16 @@
 
 void mark_as_det_done(afl_state_t *afl, struct queue_entry *q) {
 
-  u8 *fn = strrchr(q->fname, '/');
+  u8  fn[PATH_MAX];
   s32 fd;
 
-  fn = alloc_printf("%s/queue/.state/deterministic_done/%s", afl->out_dir,
-                    fn + 1);
+  snprintf(fn, PATH_MAX, "%s/queue/.state/deterministic_done/%s", afl->out_dir,
+           strrchr(q->fname, '/') + 1);
 
   fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
   if (fd < 0) PFATAL("Unable to create '%s'", fn);
   close(fd);
 
-  ck_free(fn);
-
   q->passed_det = 1;
 
 }
@@ -51,10 +49,13 @@ void mark_as_det_done(afl_state_t *afl, struct queue_entry *q) {
 
 void mark_as_variable(afl_state_t *afl, struct queue_entry *q) {
 
-  u8 *fn = strrchr(q->fname, '/') + 1, *ldest;
+  u8 fn[PATH_MAX];
+  u8 ldest[PATH_MAX];
+
+  u8 *fn_name = strrchr(q->fname, '/') + 1;
 
-  ldest = alloc_printf("../../%s", fn);
-  fn = alloc_printf("%s/queue/.state/variable_behavior/%s", afl->out_dir, fn);
+  sprintf(ldest, "../../%s", fn_name);
+  sprintf(fn, "%s/queue/.state/variable_behavior/%s", afl->out_dir, fn_name);
 
   if (symlink(ldest, fn)) {
 
@@ -64,9 +65,6 @@ void mark_as_variable(afl_state_t *afl, struct queue_entry *q) {
 
   }
 
-  ck_free(ldest);
-  ck_free(fn);
-
   q->var_behavior = 1;
 
 }
@@ -76,14 +74,14 @@ void mark_as_variable(afl_state_t *afl, struct queue_entry *q) {
 
 void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) {
 
-  u8 *fn;
+  u8 fn[PATH_MAX];
 
   if (state == q->fs_redundant) return;
 
   q->fs_redundant = state;
 
-  fn = strrchr(q->fname, '/');
-  fn = alloc_printf("%s/queue/.state/redundant_edges/%s", afl->out_dir, fn + 1);
+  sprintf(fn, "%s/queue/.state/redundant_edges/%s", afl->out_dir,
+          strrchr(q->fname, '/') + 1);
 
   if (state) {
 
@@ -99,8 +97,6 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) {
 
   }
 
-  ck_free(fn);
-
 }
 
 /* Append new test case to the queue. */
@@ -114,6 +110,7 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
   q->depth = afl->cur_depth + 1;
   q->passed_det = passed_det;
   q->n_fuzz = 1;
+  q->trace_mini = NULL;
 
   if (q->depth > afl->max_depth) afl->max_depth = q->depth;
 
@@ -147,7 +144,8 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
     /* At the initialization stage, queue_cur is NULL */
     if (afl->queue_cur) fname_orig = afl->queue_cur->fname;
 
-    afl->mutator->afl_custom_queue_new_entry(afl, fname, fname_orig);
+    afl->mutator->afl_custom_queue_new_entry(afl->mutator->data, fname,
+                                             fname_orig);
 
   }
 
@@ -186,9 +184,9 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
 
   u32 i;
   u64 fav_factor;
-  u64 fuzz_p2 = next_p2(q->n_fuzz);
+  u64 fuzz_p2 = next_pow2(q->n_fuzz);
 
-  if (afl->schedule == MMOPT || afl->schedule == RARE)
+  if (afl->schedule == MMOPT || afl->schedule == RARE || unlikely(afl->fixed_seed))
     fav_factor = q->len << 2;
   else
     fav_factor = q->exec_us * q->len;
@@ -203,9 +201,9 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
 
         /* Faster-executing or smaller test cases are favored. */
         u64 top_rated_fav_factor;
-        u64 top_rated_fuzz_p2 = next_p2(afl->top_rated[i]->n_fuzz);
+        u64 top_rated_fuzz_p2 = next_pow2(afl->top_rated[i]->n_fuzz);
 
-        if (afl->schedule == MMOPT || afl->schedule == RARE)
+        if (afl->schedule == MMOPT || afl->schedule == RARE || unlikely(afl->fixed_seed))
           top_rated_fav_factor = afl->top_rated[i]->len << 2;
         else
           top_rated_fav_factor =
@@ -216,8 +214,17 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
         else if (fuzz_p2 == top_rated_fuzz_p2)
           if (fav_factor > top_rated_fav_factor) continue;
 
-        if (fav_factor > afl->top_rated[i]->exec_us * afl->top_rated[i]->len)
-          continue;
+        if (afl->schedule == MMOPT || afl->schedule == RARE || unlikely(afl->fixed_seed)) {
+
+          if (fav_factor > afl->top_rated[i]->len << 2)
+            continue;
+
+        } else {        
+
+          if (fav_factor > afl->top_rated[i]->exec_us * afl->top_rated[i]->len)
+            continue;
+        
+        }
 
         /* Looks like we're going to win. Decrease ref count for the
            previous winner, discard its afl->fsrv.trace_bits[] if necessary. */
@@ -332,7 +339,7 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) {
   // Longer execution time means longer work on the input, the deeper in
   // coverage, the better the fuzzing, right? -mh
 
-  if (afl->schedule != MMOPT && afl->schedule != RARE) {
+  if (afl->schedule != MMOPT && afl->schedule != RARE && likely(!afl->fixed_seed)) {
 
     if (q->exec_us * 0.1 > avg_exec_us)
       perf_score = 10;
@@ -442,7 +449,7 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) {
       if (q->fuzz_level < 16)
         factor = ((u32)(1 << q->fuzz_level)) / (fuzz == 0 ? 1 : fuzz);
       else
-        factor = MAX_FACTOR / (fuzz == 0 ? 1 : next_p2(fuzz));
+        factor = MAX_FACTOR / (fuzz == 0 ? 1 : next_pow2(fuzz));
       break;
 
     case LIN: factor = q->fuzz_level / (fuzz == 0 ? 1 : fuzz); break;
diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c
index b069fa77..4acc204b 100644
--- a/src/afl-fuzz-redqueen.c
+++ b/src/afl-fuzz-redqueen.c
@@ -529,9 +529,10 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len,
 
     if (!afl->shm.cmp_map->headers[k].hits) continue;
     if (afl->shm.cmp_map->headers[k].type == CMP_TYPE_INS)
-      afl->stage_max += MIN(afl->shm.cmp_map->headers[k].hits, CMP_MAP_H);
+      afl->stage_max += MIN((u32)afl->shm.cmp_map->headers[k].hits, CMP_MAP_H);
     else
-      afl->stage_max += MIN(afl->shm.cmp_map->headers[k].hits, CMP_MAP_RTN_H);
+      afl->stage_max +=
+          MIN((u32)afl->shm.cmp_map->headers[k].hits, CMP_MAP_RTN_H);
 
   }
 
diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c
index 8c4b5941..5875eb68 100644
--- a/src/afl-fuzz-run.c
+++ b/src/afl-fuzz-run.c
@@ -33,13 +33,10 @@
 u8 run_target(afl_state_t *afl, u32 timeout) {
 
   s32 res;
-  int sret;
+  u32 exec_ms;
 
-  fd_set readfds;
-
-  struct timeval it;
-  int            status = 0;
-  u32            tb4;
+  int status = 0;
+  u32 tb4;
 
   afl->fsrv.child_timed_out = 0;
 
@@ -70,26 +67,20 @@ u8 run_target(afl_state_t *afl, u32 timeout) {
 
   if (afl->fsrv.child_pid <= 0) FATAL("Fork server is misbehaving (OOM?)");
 
-  /* use select to monitor the forkserver for timeouts. */
-
-  FD_ZERO(&readfds);
-  FD_SET(afl->fsrv.fsrv_st_fd, &readfds);
-  it.tv_sec = ((timeout) / 1000);
-  it.tv_usec = ((timeout) % 1000) * 1000;
-
-  sret = select(afl->fsrv.fsrv_st_fd + 1, &readfds, NULL, NULL, &it);
+  exec_ms = read_timed(afl->fsrv.fsrv_st_fd, &status, 4, timeout);
 
-  if (sret == 0) {
+  if (exec_ms > timeout) {
 
     /* If there was no response from forkserver after timeout seconds,
     we kill the child. The forkserver should inform us afterwards */
 
     kill(afl->fsrv.child_pid, SIGKILL);
     afl->fsrv.child_timed_out = 1;
+    if (read(afl->fsrv.fsrv_st_fd, &status, 4) < 4) exec_ms = 0;
 
   }
 
-  if ((res = read(afl->fsrv.fsrv_st_fd, &status, 4)) != 4) {
+  if (!exec_ms) {
 
     if (afl->stop_soon) return 0;
     SAYF("\n" cLRD "[-] " cRST
@@ -176,20 +167,16 @@ void write_to_testcase(afl_state_t *afl, void *mem, u32 len) {
   s32 fd = afl->fsrv.out_fd;
 
 #ifdef _AFL_DOCUMENT_MUTATIONS
-  s32   doc_fd;
-  char *fn = alloc_printf("%s/mutations/%09u:%s", afl->out_dir,
+  s32  doc_fd;
+  char fn[PATH_MAX];
+  snprintf(fn, PATH_MAX, ("%s/mutations/%09u:%s", afl->out_dir,
                           afl->document_counter++, describe_op(afl, 0));
-  if (fn != NULL) {
-
-    if ((doc_fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600)) >= 0) {
-
-      if (write(doc_fd, mem, len) != len)
-        PFATAL("write to mutation file failed: %s", fn);
-      close(doc_fd);
 
-    }
+  if ((doc_fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600)) >= 0) {
 
-    ck_free(fn);
+    if (write(doc_fd, mem, len) != len)
+      PFATAL("write to mutation file failed: %s", fn);
+    close(doc_fd);
 
   }
 
@@ -214,16 +201,22 @@ void write_to_testcase(afl_state_t *afl, void *mem, u32 len) {
 
     lseek(fd, 0, SEEK_SET);
 
-  if (afl->mutator && afl->mutator->afl_custom_pre_save) {
+  if (unlikely(afl->mutator && afl->mutator->afl_custom_pre_save)) {
+
+    u8 *new_buf = NULL;
+
+    size_t new_size = afl->mutator->afl_custom_pre_save(afl->mutator->data, mem,
+                                                        len, &new_buf);
 
-    u8 *   new_data;
-    size_t new_size =
-        afl->mutator->afl_custom_pre_save(afl, mem, len, &new_data);
-    ck_write(fd, new_data, new_size, afl->fsrv.out_file);
-    ck_free(new_data);
+    if (unlikely(!new_buf))
+      FATAL("Custom_pre_save failed (ret: %lu)", (long unsigned)new_size);
+
+    /* everything as planned. use the new data. */
+    ck_write(fd, new_buf, new_size, afl->fsrv.out_file);
 
   } else {
 
+    /* boring uncustom. */
     ck_write(fd, mem, len, afl->fsrv.out_file);
 
   }
@@ -505,8 +498,8 @@ void sync_fuzzers(afl_state_t *afl) {
     afl->stage_cur = 0;
     afl->stage_max = 0;
 
-    /* For every file queued by this fuzzer, parse ID and see if we have looked
-       at it before; exec a test case if not. */
+    /* For every file queued by this fuzzer, parse ID and see if we have
+       looked at it before; exec a test case if not. */
 
     while ((qd_ent = readdir(qd))) {
 
@@ -615,7 +608,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
 
   /* Select initial chunk len, starting with large steps. */
 
-  len_p2 = next_p2(q->len);
+  len_p2 = next_pow2(q->len);
 
   remove_len = MAX(len_p2 / TRIM_START_STEPS, TRIM_MIN_BYTES);
 
@@ -627,8 +620,8 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
     u32 remove_pos = remove_len;
 
     sprintf(afl->stage_name_buf, "trim %s/%s",
-             u_stringify_int(val_bufs[0], remove_len),
-             u_stringify_int(val_bufs[1], remove_len));
+            u_stringify_int(val_bufs[0], remove_len),
+            u_stringify_int(val_bufs[1], remove_len));
 
     afl->stage_cur = 0;
     afl->stage_max = q->len / remove_len;
@@ -645,7 +638,8 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
 
       if (afl->stop_soon || fault == FAULT_ERROR) goto abort_trimming;
 
-      /* Note that we don't keep track of crashes or hangs here; maybe TODO? */
+      /* Note that we don't keep track of crashes or hangs here; maybe TODO?
+       */
 
       cksum = hash32(afl->fsrv.trace_bits, MAP_SIZE, HASH_CONST);
 
@@ -659,7 +653,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
         u32 move_tail = q->len - remove_pos - trim_avail;
 
         q->len -= trim_avail;
-        len_p2 = next_p2(q->len);
+        len_p2 = next_pow2(q->len);
 
         memmove(in_buf + remove_pos, in_buf + remove_pos + trim_avail,
                 move_tail);
@@ -734,8 +728,13 @@ u8 common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
 
   if (afl->post_handler) {
 
-    out_buf = afl->post_handler(out_buf, &len);
-    if (!out_buf || !len) return 0;
+    u8 *post_buf = NULL;
+
+    size_t post_len =
+        afl->post_handler(afl->post_data, out_buf, len, &post_buf);
+    if (!post_buf || !post_len) return 0;
+    out_buf = post_buf;
+    len = post_len;
 
   }
 
diff --git a/src/afl-fuzz-globals.c b/src/afl-fuzz-state.c
index 88633a1b..80176a10 100644
--- a/src/afl-fuzz-globals.c
+++ b/src/afl-fuzz-state.c
@@ -34,8 +34,6 @@ char *power_names[POWER_SCHEDULES_NUM] = {
 
     "explore", "fast", "coe", "lin", "quad", "exploit", "mmopt", "rare"};
 
-u8 *doc_path = NULL;                    /* gath to documentation dir        */
-
 /* Initialize MOpt "globals" for this afl state */
 
 static void init_mopt_globals(afl_state_t *afl) {
@@ -79,6 +77,8 @@ list_t afl_states = {.element_prealloc_count = 0};
 
 void afl_state_init(afl_state_t *afl) {
 
+  /* thanks to this memset, growing vars like out_buf
+  and out_size are NULL/0 by default. */
   memset(afl, 0, sizeof(afl_state_t));
 
   afl->w_init = 0.9;
@@ -347,6 +347,15 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
 
 void afl_state_deinit(afl_state_t *afl) {
 
+  if (afl->post_deinit) afl->post_deinit(afl->post_data);
+
+  free(afl->out_buf);
+  free(afl->out_scratch_buf);
+  free(afl->eff_buf);
+  free(afl->in_buf);
+  free(afl->in_scratch_buf);
+  free(afl->ex_buf);
+
   list_remove(&afl_states, afl);
 
 }
diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c
index dc16df8f..77bbe023 100644
--- a/src/afl-fuzz-stats.c
+++ b/src/afl-fuzz-stats.c
@@ -33,16 +33,17 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
   struct rusage rus;
 
   unsigned long long int cur_time = get_cur_time();
-  u8 *                   fn = alloc_printf("%s/fuzzer_stats", afl->out_dir);
+  u8                     fn[PATH_MAX];
   s32                    fd;
   FILE *                 f;
+  uint32_t               t_bytes = count_non_255_bytes(afl->virgin_bits);
+
+  snprintf(fn, PATH_MAX, "%s/fuzzer_stats", afl->out_dir);
 
   fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600);
 
   if (fd < 0) PFATAL("Unable to create '%s'", fn);
 
-  ck_free(fn);
-
   f = fdopen(fd, "w");
 
   if (!f) PFATAL("fdopen() failed");
@@ -95,8 +96,10 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
       "last_hang         : %llu\n"
       "execs_since_crash : %llu\n"
       "exec_timeout      : %u\n"
-      "slowest_exec_ms   : %llu\n"
+      "slowest_exec_ms   : %u\n"
       "peak_rss_mb       : %lu\n"
+      "var_byte_count    : %u\n"
+      "found_edges       : %u\n"
       "afl_banner        : %s\n"
       "afl_version       : " VERSION
       "\n"
@@ -119,9 +122,10 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
 #else
       (unsigned long int)(rus.ru_maxrss >> 10),
 #endif
-      afl->use_banner, afl->unicorn_mode ? "unicorn" : "",
-      afl->qemu_mode ? "qemu " : "", afl->dumb_mode ? " dumb " : "",
-      afl->no_forkserver ? "no_fsrv " : "", afl->crash_mode ? "crash " : "",
+      afl->var_byte_count, t_bytes, afl->use_banner,
+      afl->unicorn_mode ? "unicorn" : "", afl->qemu_mode ? "qemu " : "",
+      afl->dumb_mode ? " dumb " : "", afl->no_forkserver ? "no_fsrv " : "",
+      afl->crash_mode ? "crash " : "",
       afl->persistent_mode ? "persistent " : "",
       afl->deferred_mode ? "deferred " : "",
       (afl->unicorn_mode || afl->qemu_mode || afl->dumb_mode ||
@@ -257,7 +261,7 @@ void show_stats(afl_state_t *afl) {
   t_byte_ratio = ((double)t_bytes * 100) / MAP_SIZE;
 
   if (t_bytes)
-    stab_ratio = 100 - ((double)afl->var_byte_count) * 100 / t_bytes;
+    stab_ratio = 100 - (((double)afl->var_byte_count) * 100) / t_bytes;
   else
     stab_ratio = 100;
 
@@ -406,8 +410,7 @@ void show_stats(afl_state_t *afl) {
       (afl->last_path_time || afl->resuming_fuzz || afl->queue_cycle == 1 ||
        afl->in_bitmap || afl->crash_mode)) {
 
-    u_stringify_time_diff(time_tmp, cur_ms,
-                        afl->last_path_time);
+    u_stringify_time_diff(time_tmp, cur_ms, afl->last_path_time);
     SAYF(bV bSTOP "   last new path : " cRST "%-33s ", time_tmp);
 
   } else {
@@ -533,24 +536,21 @@ void show_stats(afl_state_t *afl) {
 
   if (afl->stats_avg_exec < 100) {
 
-    sprintf(tmp, "%s/sec (%s)",
-             u_stringify_float(IB(0), afl->stats_avg_exec),
-             afl->stats_avg_exec < 20 ? "zzzz..." : "slow!");
+    sprintf(tmp, "%s/sec (%s)", u_stringify_float(IB(0), afl->stats_avg_exec),
+            afl->stats_avg_exec < 20 ? "zzzz..." : "slow!");
 
     SAYF(bV bSTOP "  exec speed : " cLRD "%-20s ", tmp);
 
   } else {
 
-    sprintf(tmp, "%s/sec",
-             u_stringify_float(IB(0), afl->stats_avg_exec));
+    sprintf(tmp, "%s/sec", u_stringify_float(IB(0), afl->stats_avg_exec));
     SAYF(bV bSTOP "  exec speed : " cRST "%-20s ", tmp);
 
   }
 
-  sprintf(tmp, "%s (%s%s unique)",
-           u_stringify_int(IB(0), afl->total_tmouts),
-           u_stringify_int(IB(1), afl->unique_tmouts),
-           (afl->unique_hangs >= KEEP_UNIQUE_HANG) ? "+" : "");
+  sprintf(tmp, "%s (%s%s unique)", u_stringify_int(IB(0), afl->total_tmouts),
+          u_stringify_int(IB(1), afl->unique_tmouts),
+          (afl->unique_hangs >= KEEP_UNIQUE_HANG) ? "+" : "");
 
   SAYF(bSTG bV bSTOP "  total tmouts : " cRST "%-22s" bSTG bV "\n", tmp);
 
@@ -567,12 +567,12 @@ void show_stats(afl_state_t *afl) {
   } else {
 
     sprintf(tmp, "%s/%s, %s/%s, %s/%s",
-             u_stringify_int(IB(0), afl->stage_finds[STAGE_FLIP1]),
-             u_stringify_int(IB(1), afl->stage_cycles[STAGE_FLIP1]),
-             u_stringify_int(IB(2), afl->stage_finds[STAGE_FLIP2]),
-             u_stringify_int(IB(3), afl->stage_cycles[STAGE_FLIP2]),
-             u_stringify_int(IB(3), afl->stage_finds[STAGE_FLIP4]),
-             u_stringify_int(IB(5), afl->stage_cycles[STAGE_FLIP4]));
+            u_stringify_int(IB(0), afl->stage_finds[STAGE_FLIP1]),
+            u_stringify_int(IB(1), afl->stage_cycles[STAGE_FLIP1]),
+            u_stringify_int(IB(2), afl->stage_finds[STAGE_FLIP2]),
+            u_stringify_int(IB(3), afl->stage_cycles[STAGE_FLIP2]),
+            u_stringify_int(IB(4), afl->stage_finds[STAGE_FLIP4]),
+            u_stringify_int(IB(5), afl->stage_cycles[STAGE_FLIP4]));
 
   }
 
@@ -582,12 +582,12 @@ void show_stats(afl_state_t *afl) {
 
   if (!afl->skip_deterministic)
     sprintf(tmp, "%s/%s, %s/%s, %s/%s",
-             u_stringify_int(IB(0), afl->stage_finds[STAGE_FLIP8]),
-             u_stringify_int(IB(1), afl->stage_cycles[STAGE_FLIP8]),
-             u_stringify_int(IB(2), afl->stage_finds[STAGE_FLIP16]),
-             u_stringify_int(IB(3), afl->stage_cycles[STAGE_FLIP16]),
-             u_stringify_int(IB(4), afl->stage_finds[STAGE_FLIP32]),
-             u_stringify_int(IB(5), afl->stage_cycles[STAGE_FLIP32]));
+            u_stringify_int(IB(0), afl->stage_finds[STAGE_FLIP8]),
+            u_stringify_int(IB(1), afl->stage_cycles[STAGE_FLIP8]),
+            u_stringify_int(IB(2), afl->stage_finds[STAGE_FLIP16]),
+            u_stringify_int(IB(3), afl->stage_cycles[STAGE_FLIP16]),
+            u_stringify_int(IB(4), afl->stage_finds[STAGE_FLIP32]),
+            u_stringify_int(IB(5), afl->stage_cycles[STAGE_FLIP32]));
 
   SAYF(bV bSTOP "  byte flips : " cRST "%-36s " bSTG bV bSTOP
                 "   pending : " cRST "%-10s" bSTG       bV "\n",
@@ -595,12 +595,12 @@ void show_stats(afl_state_t *afl) {
 
   if (!afl->skip_deterministic)
     sprintf(tmp, "%s/%s, %s/%s, %s/%s",
-             u_stringify_int(IB(0), afl->stage_finds[STAGE_ARITH8]),
-             u_stringify_int(IB(1), afl->stage_cycles[STAGE_ARITH8]),
-             u_stringify_int(IB(2), afl->stage_finds[STAGE_ARITH16]),
-             u_stringify_int(IB(3), afl->stage_cycles[STAGE_ARITH16]),
-             u_stringify_int(IB(4), afl->stage_finds[STAGE_ARITH32]),
-             u_stringify_int(IB(5), afl->stage_cycles[STAGE_ARITH32]));
+            u_stringify_int(IB(0), afl->stage_finds[STAGE_ARITH8]),
+            u_stringify_int(IB(1), afl->stage_cycles[STAGE_ARITH8]),
+            u_stringify_int(IB(2), afl->stage_finds[STAGE_ARITH16]),
+            u_stringify_int(IB(3), afl->stage_cycles[STAGE_ARITH16]),
+            u_stringify_int(IB(4), afl->stage_finds[STAGE_ARITH32]),
+            u_stringify_int(IB(5), afl->stage_cycles[STAGE_ARITH32]));
 
   SAYF(bV bSTOP " arithmetics : " cRST "%-36s " bSTG bV bSTOP
                 "  pend fav : " cRST "%-10s" bSTG       bV "\n",
@@ -621,25 +621,26 @@ void show_stats(afl_state_t *afl) {
 
   if (!afl->skip_deterministic)
     sprintf(tmp, "%s/%s, %s/%s, %s/%s",
-             u_stringify_int(IB(0), afl->stage_finds[STAGE_EXTRAS_UO]),
-             u_stringify_int(IB(1), afl->stage_cycles[STAGE_EXTRAS_UO]),
-             u_stringify_int(IB(2), afl->stage_finds[STAGE_EXTRAS_UI]),
-             u_stringify_int(IB(3), afl->stage_cycles[STAGE_EXTRAS_UI]),
-             u_stringify_int(IB(4), afl->stage_finds[STAGE_EXTRAS_AO]),
-             u_stringify_int(IB(5), afl->stage_cycles[STAGE_EXTRAS_AO]));
+            u_stringify_int(IB(0), afl->stage_finds[STAGE_EXTRAS_UO]),
+            u_stringify_int(IB(1), afl->stage_cycles[STAGE_EXTRAS_UO]),
+            u_stringify_int(IB(2), afl->stage_finds[STAGE_EXTRAS_UI]),
+            u_stringify_int(IB(3), afl->stage_cycles[STAGE_EXTRAS_UI]),
+            u_stringify_int(IB(4), afl->stage_finds[STAGE_EXTRAS_AO]),
+            u_stringify_int(IB(5), afl->stage_cycles[STAGE_EXTRAS_AO]));
 
   SAYF(bV bSTOP "  dictionary : " cRST "%-36s " bSTG bV bSTOP
                 "  imported : " cRST "%-10s" bSTG       bV "\n",
        tmp,
-       afl->sync_id ? u_stringify_int(IB(0), afl->queued_imported) : (u8 *)"n/a");
+       afl->sync_id ? u_stringify_int(IB(0), afl->queued_imported)
+                    : (u8 *)"n/a");
 
   sprintf(tmp, "%s/%s, %s/%s, %s/%s",
-           u_stringify_int(IB(0), afl->stage_finds[STAGE_HAVOC]),
-           u_stringify_int(IB(2), afl->stage_cycles[STAGE_HAVOC]),
-           u_stringify_int(IB(3), afl->stage_finds[STAGE_SPLICE]),
-           u_stringify_int(IB(4), afl->stage_cycles[STAGE_SPLICE]),
-           u_stringify_int(IB(5), afl->stage_finds[STAGE_RADAMSA]),
-           u_stringify_int(IB(6), afl->stage_cycles[STAGE_RADAMSA]));
+          u_stringify_int(IB(0), afl->stage_finds[STAGE_HAVOC]),
+          u_stringify_int(IB(2), afl->stage_cycles[STAGE_HAVOC]),
+          u_stringify_int(IB(3), afl->stage_finds[STAGE_SPLICE]),
+          u_stringify_int(IB(4), afl->stage_cycles[STAGE_SPLICE]),
+          u_stringify_int(IB(5), afl->stage_finds[STAGE_RADAMSA]),
+          u_stringify_int(IB(6), afl->stage_cycles[STAGE_RADAMSA]));
 
   SAYF(bV bSTOP "   havoc/rad : " cRST "%-36s " bSTG bV bSTOP, tmp);
 
@@ -660,14 +661,14 @@ void show_stats(afl_state_t *afl) {
   if (afl->shm.cmplog_mode) {
 
     sprintf(tmp, "%s/%s, %s/%s, %s/%s, %s/%s",
-             u_stringify_int(IB(0), afl->stage_finds[STAGE_PYTHON]),
-             u_stringify_int(IB(1), afl->stage_cycles[STAGE_PYTHON]),
-             u_stringify_int(IB(2), afl->stage_finds[STAGE_CUSTOM_MUTATOR]),
-             u_stringify_int(IB(3), afl->stage_cycles[STAGE_CUSTOM_MUTATOR]),
-             u_stringify_int(IB(4), afl->stage_finds[STAGE_COLORIZATION]),
-             u_stringify_int(IB(5), afl->stage_cycles[STAGE_COLORIZATION]),
-             u_stringify_int(IB(6), afl->stage_finds[STAGE_ITS]),
-             u_stringify_int(IB(7), afl->stage_cycles[STAGE_ITS]));
+            u_stringify_int(IB(0), afl->stage_finds[STAGE_PYTHON]),
+            u_stringify_int(IB(1), afl->stage_cycles[STAGE_PYTHON]),
+            u_stringify_int(IB(2), afl->stage_finds[STAGE_CUSTOM_MUTATOR]),
+            u_stringify_int(IB(3), afl->stage_cycles[STAGE_CUSTOM_MUTATOR]),
+            u_stringify_int(IB(4), afl->stage_finds[STAGE_COLORIZATION]),
+            u_stringify_int(IB(5), afl->stage_cycles[STAGE_COLORIZATION]),
+            u_stringify_int(IB(6), afl->stage_finds[STAGE_ITS]),
+            u_stringify_int(IB(7), afl->stage_cycles[STAGE_ITS]));
 
     SAYF(bV bSTOP "   custom/rq : " cRST "%-36s " bSTG bVR bH20 bH2 bH bRB "\n",
          tmp);
@@ -675,10 +676,10 @@ void show_stats(afl_state_t *afl) {
   } else {
 
     sprintf(tmp, "%s/%s, %s/%s",
-             u_stringify_int(IB(0), afl->stage_finds[STAGE_PYTHON]),
-             u_stringify_int(IB(1), afl->stage_cycles[STAGE_PYTHON]),
-             u_stringify_int(IB(2), afl->stage_finds[STAGE_CUSTOM_MUTATOR]),
-             u_stringify_int(IB(3), afl->stage_cycles[STAGE_CUSTOM_MUTATOR]));
+            u_stringify_int(IB(0), afl->stage_finds[STAGE_PYTHON]),
+            u_stringify_int(IB(1), afl->stage_cycles[STAGE_PYTHON]),
+            u_stringify_int(IB(2), afl->stage_finds[STAGE_CUSTOM_MUTATOR]),
+            u_stringify_int(IB(3), afl->stage_cycles[STAGE_CUSTOM_MUTATOR]));
 
     SAYF(bV bSTOP "   py/custom : " cRST "%-36s " bSTG bVR bH20 bH2 bH bRB "\n",
          tmp);
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index ba56ff67..ad4f5b6b 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -25,8 +25,6 @@
 
 #include "afl-fuzz.h"
 
-u8 be_quiet = 0;
-
 static u8 *get_libradamsa_path(u8 *own_loc) {
 
   u8 *tmp, *cp, *rsl, *own_copy;
@@ -693,6 +691,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
   if (afl->fixed_seed) OKF("Running with fixed seed: %u", (u32)afl->init_seed);
   srandom((u32)afl->init_seed);
+  srand((u32)afl->init_seed);  // in case it is a different implementation
 
   if (afl->use_radamsa) {
 
@@ -723,6 +722,16 @@ int main(int argc, char **argv_orig, char **envp) {
 
   }
 
+#if defined(__SANITIZE_ADDRESS__)
+  if (afl->fsrv.mem_limit) {
+
+    WARNF("in the ASAN build we disable all memory limits");
+    afl->fsrv.mem_limit = 0;
+
+  }
+
+#endif
+
   setup_signal_handlers();
   check_asan_opts();
 
diff --git a/src/afl-showmap.c b/src/afl-showmap.c
index caacefe4..f8a38c36 100644
--- a/src/afl-showmap.c
+++ b/src/afl-showmap.c
@@ -59,13 +59,10 @@
 #include <sys/types.h>
 #include <sys/resource.h>
 
-u8 be_quiet;
-
 char *stdin_file;                      /* stdin file                        */
 
 u8 *in_dir,                            /* input folder                      */
-    *doc_path,                         /* Path to docs                      */
-        *at_file = NULL;               /* Substitution string for @@        */
+    *at_file = NULL;              /* Substitution string for @@             */
 
 static u8 *in_data;                    /* Input data                        */
 
@@ -224,26 +221,6 @@ static u32 write_results(afl_forkserver_t *fsrv) {
 
 }
 
-/* Write output file. */
-
-static s32 write_to_file(u8 *path, u8 *mem, u32 len) {
-
-  s32 ret;
-
-  unlink(path);                                            /* Ignore errors */
-
-  ret = open(path, O_RDWR | O_CREAT | O_EXCL, 0600);
-
-  if (ret < 0) PFATAL("Unable to create '%s'", path);
-
-  ck_write(ret, mem, len, path);
-
-  lseek(ret, 0, SEEK_SET);
-
-  return ret;
-
-}
-
 /* Write modified data to file for testing. If use_stdin is clear, the old file
    is unlinked and a new one is created. Otherwise, out_fd is rewound and
    truncated. */
diff --git a/src/afl-tmin.c b/src/afl-tmin.c
index 2275aef5..30e76d42 100644
--- a/src/afl-tmin.c
+++ b/src/afl-tmin.c
@@ -61,8 +61,7 @@
 static u8 *mask_bitmap;                /* Mask for trace bits (-B)          */
 
 u8 *in_file,                           /* Minimizer input test case         */
-    *output_file,                      /* Minimizer output file             */
-    *doc_path;                         /* Path to docs                      */
+    *output_file;                      /* Minimizer output file             */
 
 static u8 *in_data;                    /* Input data for trimming           */
 
@@ -77,8 +76,7 @@ u8 crash_mode,                         /* Crash-centric mode?               */
     hang_mode,                         /* Minimize as long as it hangs      */
     exit_crash,                        /* Treat non-zero exit as crash?     */
     edges_only,                        /* Ignore hit counts?                */
-    exact_mode,                        /* Require path match for crashes?   */
-    be_quiet;
+    exact_mode;                        /* Require path match for crashes?   */
 
 static volatile u8 stop_soon;          /* Ctrl-C pressed?                   */
 
@@ -406,17 +404,6 @@ static u8 run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len,
 
 }
 
-/* Find first power of two greater or equal to val. */
-
-static u32 next_p2(u32 val) {
-
-  u32 ret = 1;
-  while (val > ret)
-    ret <<= 1;
-  return ret;
-
-}
-
 /* Actually minimize! */
 
 static void minimize(afl_forkserver_t *fsrv, char **argv) {
@@ -434,7 +421,7 @@ static void minimize(afl_forkserver_t *fsrv, char **argv) {
    * BLOCK NORMALIZATION *
    ***********************/
 
-  set_len = next_p2(in_len / TMIN_SET_STEPS);
+  set_len = next_pow2(in_len / TMIN_SET_STEPS);
   set_pos = 0;
 
   if (set_len < TMIN_SET_MIN_SIZE) set_len = TMIN_SET_MIN_SIZE;
@@ -484,7 +471,7 @@ next_pass:
    * BLOCK DELETION *
    ******************/
 
-  del_len = next_p2(in_len / TRIM_START_STEPS);
+  del_len = next_pow2(in_len / TRIM_START_STEPS);
   stage_o_len = in_len;
 
   ACTF(cBRI "Stage #1: " cRST "Removing blocks of data...");
diff --git a/src/third_party/libradamsa/libradamsa.c b/src/third_party/libradamsa/libradamsa.c
index f3677fa7..fe91594e 100644
--- a/src/third_party/libradamsa/libradamsa.c
+++ b/src/third_party/libradamsa/libradamsa.c
@@ -30815,7 +30815,7 @@ size_t copy_list(uint8_t *ptr, word lispval, size_t max) {
       lispval = G(lispval, 2);              // list   = cdr(list)
    }
    if (lispval != INULL && max == 0) {
-      printf("ERROR: lisp return value was not a proper list. Trailing %lu\n", lispval);
+      printf("ERROR: lisp return value was not a proper list. Trailing %lu\n", (unsigned long)lispval);
    }
    return n;
 }