about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/afl-analyze.c14
-rw-r--r--src/afl-common.c8
-rw-r--r--src/afl-forkserver.c98
-rw-r--r--src/afl-fuzz-bitmap.c42
-rw-r--r--src/afl-fuzz-cmplog.c235
-rw-r--r--src/afl-fuzz-extras.c23
-rw-r--r--src/afl-fuzz-globals.c30
-rw-r--r--src/afl-fuzz-init.c33
-rw-r--r--src/afl-fuzz-misc.c186
-rw-r--r--src/afl-fuzz-mutators.c95
-rw-r--r--src/afl-fuzz-one.c324
-rw-r--r--src/afl-fuzz-python.c240
-rw-r--r--src/afl-fuzz-queue.c51
-rw-r--r--src/afl-fuzz-redqueen.c2
-rw-r--r--src/afl-fuzz-run.c52
-rw-r--r--src/afl-fuzz-stats.c303
-rw-r--r--src/afl-fuzz.c25
-rw-r--r--src/afl-gotcpu.c2
-rw-r--r--src/afl-showmap.c12
-rw-r--r--src/afl-tmin.c157
20 files changed, 777 insertions, 1155 deletions
diff --git a/src/afl-analyze.c b/src/afl-analyze.c
index 2148cdf0..d509c43e 100644
--- a/src/afl-analyze.c
+++ b/src/afl-analyze.c
@@ -207,15 +207,6 @@ static s32 write_to_file(u8 *path, u8 *mem, u32 len) {
 
 }
 
-/* Handle timeout signal. */
-
-static void handle_timeout(int sig) {
-
-  child_timed_out = 1;
-  if (child_pid > 0) kill(child_pid, SIGKILL);
-
-}
-
 /* Execute target application. Returns exec checksum, or 0 if program
    times out. */
 
@@ -770,11 +761,6 @@ static void setup_signal_handlers(void) {
   sigaction(SIGINT, &sa, NULL);
   sigaction(SIGTERM, &sa, NULL);
 
-  /* Exec timeout notifications. */
-
-  sa.sa_handler = handle_timeout;
-  sigaction(SIGALRM, &sa, NULL);
-
 }
 
 /* Display usage hints. */
diff --git a/src/afl-common.c b/src/afl-common.c
index 1aa15442..8c4d53e8 100644
--- a/src/afl-common.c
+++ b/src/afl-common.c
@@ -57,10 +57,10 @@ char *    afl_environment_variables[] = {
     "AFL_LLVM_INSTRIM_LOOPHEAD", "AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK",
     "AFL_LLVM_LAF_SPLIT_COMPARES", "AFL_LLVM_LAF_SPLIT_COMPARES_BITW",
     "AFL_LLVM_LAF_SPLIT_FLOATS", "AFL_LLVM_LAF_SPLIT_SWITCHES",
-    "AFL_LLVM_LAF_TRANSFORM_COMPARES", "AFL_LLVM_NOT_ZERO",
-    "AFL_LLVM_WHITELIST", "AFL_NO_AFFINITY", "AFL_LLVM_LTO_STARTID",
-    "AFL_LLVM_LTO_DONTWRITEID", "AFL_NO_ARITH", "AFL_NO_BUILTIN",
-    "AFL_NO_CPU_RED", "AFL_NO_FORKSRV", "AFL_NO_UI",
+    "AFL_LLVM_LAF_TRANSFORM_COMPARES", "AFL_LLVM_NGRAM_SIZE", "AFL_NGRAM_SIZE",
+    "AFL_LLVM_NOT_ZERO", "AFL_LLVM_WHITELIST", "AFL_NO_AFFINITY",
+    "AFL_LLVM_LTO_STARTID", "AFL_LLVM_LTO_DONTWRITEID", "AFL_NO_ARITH",
+    "AFL_NO_BUILTIN", "AFL_NO_CPU_RED", "AFL_NO_FORKSRV", "AFL_NO_UI",
     "AFL_NO_X86",  // not really an env but we dont want to warn on it
     "AFL_PATH", "AFL_PERFORMANCE_FILE",
     //"AFL_PERSISTENT", // not implemented anymore, so warn additionally
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index c7a3475f..2dd7a9f0 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -51,91 +51,8 @@
 
 extern u8 *doc_path;
 
-u8 *forkserver_DMS(u64 val) {
-
-  static u8 tmp[12][16];
-  static u8 cur;
-
-#define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast)    \
-  do {                                                    \
-                                                          \
-    if (val < (_divisor) * (_limit_mult)) {               \
-                                                          \
-      sprintf(tmp[cur], _fmt, ((_cast)val) / (_divisor)); \
-      return tmp[cur];                                    \
-                                                          \
-    }                                                     \
-                                                          \
-  } while (0)
-
-  cur = (cur + 1) % 12;
-
-  /* 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(tmp[cur], "infty");
-  return tmp[cur];
-
-}
-
 list_t fsrv_list = {.element_prealloc_count = 0};
 
-/* the timeout handler */
-
-void handle_timeout(int sig) {
-
-  LIST_FOREACH(&fsrv_list, afl_forkserver_t, {
-
-    // TODO: We need a proper timer to handle multiple timeouts
-    if (el->child_pid > 0) {
-
-      el->child_timed_out = 1;
-      kill(el->child_pid, SIGKILL);
-
-    } else if (el->child_pid == -1 && el->fsrv_pid > 0) {
-
-      el->child_timed_out = 1;
-      kill(el->fsrv_pid, SIGKILL);
-
-    }
-
-  });
-
-}
-
 /* Initializes the struct */
 
 void afl_fsrv_init(afl_forkserver_t *fsrv) {
@@ -156,6 +73,7 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
   fsrv->out_dir_fd = -1;
 
   fsrv->use_fauxsrv = 0;
+  fsrv->prev_timed_out = 0;
 
   list_append(&fsrv_list, fsrv);
 
@@ -166,8 +84,8 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
 
 static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) {
 
-  static unsigned char tmp[4] = {0};
-  pid_t                child_pid = -1;
+  unsigned char tmp[4] = {0};
+  pid_t         child_pid = -1;
 
   /* Phone home and tell the parent that we're OK. If parent isn't there,
      assume we're not running in forkserver mode and just execute program. */
@@ -476,6 +394,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv) {
 
     } else {
 
+      u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
+
       SAYF("\n" cLRD "[-] " cRST
            "Whoops, the target binary crashed suddenly, "
            "before receiving any input\n"
@@ -508,7 +428,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv) {
            "options\n"
            "      fail, poke <afl-users@googlegroups.com> for troubleshooting "
            "tips.\n",
-           forkserver_DMS(fsrv->mem_limit << 20), fsrv->mem_limit - 1);
+           stringify_mem_size(val_buf, sizeof(val_buf), fsrv->mem_limit << 20),
+           fsrv->mem_limit - 1);
 
     }
 
@@ -543,6 +464,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv) {
 
   } else {
 
+    u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
+
     SAYF(
         "\n" cLRD "[-] " cRST
         "Hmm, looks like the target binary terminated "
@@ -574,7 +497,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv) {
               "never\n"
               "      reached before the program terminates.\n\n"
             : "",
-        forkserver_DMS(fsrv->mem_limit << 20), fsrv->mem_limit - 1);
+        stringify_int(val_buf, sizeof(val_buf), fsrv->mem_limit << 20),
+        fsrv->mem_limit - 1);
 
   }
 
diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c
index 7e2d3212..0d5b542d 100644
--- a/src/afl-fuzz-bitmap.c
+++ b/src/afl-fuzz-bitmap.c
@@ -138,7 +138,8 @@ u8 has_new_bits(afl_state_t *afl, u8 *virgin_map) {
 
   }
 
-  if (ret && virgin_map == afl->virgin_bits) afl->bitmap_changed = 1;
+  if (unlikely(ret) && unlikely(virgin_map == afl->virgin_bits))
+    afl->bitmap_changed = 1;
 
   return ret;
 
@@ -413,13 +414,13 @@ void minimize_bits(u8 *dst, u8 *src) {
 #ifndef SIMPLE_FILES
 
 /* Construct a file name for a new test case, capturing the operation
-   that led to its discovery. Uses a static buffer. */
+   that led to its discovery. Returns a ptr to afl->describe_op_buf_256. */
 
 u8 *describe_op(afl_state_t *afl, u8 hnb) {
 
   u8 *ret = afl->describe_op_buf_256;
 
-  if (afl->syncing_party) {
+  if (unlikely(afl->syncing_party)) {
 
     sprintf(ret, "sync:%s,src:%06u", afl->syncing_party, afl->syncing_case);
 
@@ -465,16 +466,18 @@ static void write_crash_readme(afl_state_t *afl) {
   s32   fd;
   FILE *f;
 
+  u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
+
   fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
   ck_free(fn);
 
   /* Do not die on errors here - that would be impolite. */
 
-  if (fd < 0) return;
+  if (unlikely(fd < 0)) return;
 
   f = fdopen(fd, "w");
 
-  if (!f) {
+  if (unlikely(!f)) {
 
     close(fd);
     return;
@@ -501,7 +504,9 @@ static void write_crash_readme(afl_state_t *afl) {
 
       "  https://github.com/AFLplusplus/AFLplusplus\n\n",
 
-      afl->orig_cmdline, DMS(afl->fsrv.mem_limit << 20));  /* ignore errors */
+      afl->orig_cmdline,
+      stringify_mem_size(val_buf, sizeof(val_buf),
+                         afl->fsrv.mem_limit << 20));      /* ignore errors */
 
   fclose(f);
 
@@ -513,7 +518,7 @@ static void write_crash_readme(afl_state_t *afl) {
 
 u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
 
-  if (len == 0) return 0;
+  if (unlikely(len == 0)) return 0;
 
   u8 *fn = "";
   u8  hnb;
@@ -537,14 +542,14 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
 
   }
 
-  if (fault == afl->crash_mode) {
+  if (unlikely(fault == afl->crash_mode)) {
 
     /* Keep only if there are new bits in the map, add to queue for
        future fuzzing, etc. */
 
     if (!(hnb = has_new_bits(afl, afl->virgin_bits))) {
 
-      if (afl->crash_mode) ++afl->total_crashes;
+      if (unlikely(afl->crash_mode)) ++afl->total_crashes;
       return 0;
 
     }
@@ -576,10 +581,11 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
 
     res = calibrate_case(afl, afl->queue_top, mem, afl->queue_cycle - 1, 0);
 
-    if (res == FAULT_ERROR) FATAL("Unable to execute target application");
+    if (unlikely(res == FAULT_ERROR))
+      FATAL("Unable to execute target application");
 
     fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
-    if (fd < 0) PFATAL("Unable to create '%s'", fn);
+    if (unlikely(fd < 0)) PFATAL("Unable to create '%s'", fn);
     ck_write(fd, mem, len, fn);
     close(fd);
 
@@ -600,7 +606,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
 
       if (afl->unique_hangs >= KEEP_UNIQUE_HANG) return keeping;
 
-      if (!afl->dumb_mode) {
+      if (likely(!afl->dumb_mode)) {
 
 #ifdef WORD_SIZE_64
         simplify_trace((u64 *)afl->fsrv.trace_bits);
@@ -663,7 +669,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
 
       if (afl->unique_crashes >= KEEP_UNIQUE_CRASH) return keeping;
 
-      if (!afl->dumb_mode) {
+      if (likely(!afl->dumb_mode)) {
 
 #ifdef WORD_SIZE_64
         simplify_trace((u64 *)afl->fsrv.trace_bits);
@@ -675,7 +681,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
 
       }
 
-      if (!afl->unique_crashes) write_crash_readme(afl);
+      if (unlikely(!afl->unique_crashes)) write_crash_readme(afl);
 
 #ifndef SIMPLE_FILES
 
@@ -691,10 +697,10 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
 #endif                                                    /* ^!SIMPLE_FILES */
 
       ++afl->unique_crashes;
-      if (afl->infoexec) {  // if the user wants to be informed on new crashes -
-                            // do
+      if (unlikely(afl->infoexec)) {
+
+        // if the user wants to be informed on new crashes - do that
 #if !TARGET_OS_IPHONE
-        // that
         if (system(afl->infoexec) == -1)
           hnb += 0;  // we dont care if system errors, but we dont want a
                      // compiler warning either
@@ -719,7 +725,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
      test case, too. */
 
   fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
-  if (fd < 0) PFATAL("Unable to create '%s'", fn);
+  if (unlikely(fd < 0)) PFATAL("Unable to create '%s'", fn);
   ck_write(fd, mem, len, fn);
   close(fd);
 
diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c
index 1600af53..6c6f05ac 100644
--- a/src/afl-fuzz-cmplog.c
+++ b/src/afl-fuzz-cmplog.c
@@ -31,10 +31,10 @@
 
 void init_cmplog_forkserver(afl_state_t *afl) {
 
-  static struct timeval timeout;
-  int                   st_pipe[2], ctl_pipe[2];
-  int                   status;
-  s32                   rlen;
+  struct timeval timeout;
+  int            st_pipe[2], ctl_pipe[2];
+  int            status;
+  s32            rlen;
 
   ACTF("Spinning up the cmplog fork server...");
 
@@ -264,6 +264,8 @@ void init_cmplog_forkserver(afl_state_t *afl) {
 
     } else {
 
+      u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
+
       SAYF("\n" cLRD "[-] " cRST
            "Whoops, the target binary crashed suddenly, "
            "before receiving any input\n"
@@ -296,7 +298,9 @@ void init_cmplog_forkserver(afl_state_t *afl) {
            "options\n"
            "      fail, poke <afl-users@googlegroups.com> for troubleshooting "
            "tips.\n",
-           DMS(afl->fsrv.mem_limit << 20), afl->fsrv.mem_limit - 1);
+           stringify_mem_size(val_buf, sizeof(val_buf),
+                              afl->fsrv.mem_limit << 20),
+           afl->fsrv.mem_limit - 1);
 
     }
 
@@ -331,6 +335,8 @@ void init_cmplog_forkserver(afl_state_t *afl) {
 
   } else {
 
+    u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
+
     SAYF(
         "\n" cLRD "[-] " cRST
         "Hmm, looks like the target binary terminated "
@@ -362,7 +368,8 @@ void init_cmplog_forkserver(afl_state_t *afl) {
               "never\n"
               "      reached before the program terminates.\n\n"
             : "",
-        DMS(afl->fsrv.mem_limit << 20), afl->fsrv.mem_limit - 1);
+        stringify_mem_size(val_buf, sizeof(val_buf), afl->fsrv.mem_limit << 20),
+        afl->fsrv.mem_limit - 1);
 
   }
 
@@ -372,12 +379,15 @@ void init_cmplog_forkserver(afl_state_t *afl) {
 
 u8 run_cmplog_target(afl_state_t *afl, u32 timeout) {
 
-  static struct itimerval it;
-  static u32              prev_timed_out = 0;
-  static u64              exec_ms = 0;
+  struct timeval it;
+  int            status = 0;
+  int            sret;
+  u64            exec_ms;
 
-  int status = 0;
   u32 tb4;
+  s32 res;
+
+  fd_set readfds;
 
   afl->fsrv.child_timed_out = 0;
 
@@ -388,185 +398,80 @@ u8 run_cmplog_target(afl_state_t *afl, u32 timeout) {
   memset(afl->fsrv.trace_bits, 0, MAP_SIZE);
   MEM_BARRIER();
 
-  /* If we're running in "dumb" mode, we can't rely on the fork server
-     logic compiled into the target program, so we will just keep calling
-     execve(). There is a bit of code duplication between here and
-     init_forkserver(), but c'est la vie. */
-
-  if (afl->dumb_mode == 1 || afl->no_forkserver) {
-
-    afl->cmplog_child_pid = fork();
-
-    if (afl->cmplog_child_pid < 0) PFATAL("fork() failed");
-
-    if (!afl->cmplog_child_pid) {
-
-      struct rlimit r;
-
-      if (afl->fsrv.mem_limit) {
-
-        r.rlim_max = r.rlim_cur = ((rlim_t)afl->fsrv.mem_limit) << 20;
-
-#ifdef RLIMIT_AS
-
-        setrlimit(RLIMIT_AS, &r);                          /* Ignore errors */
-
-#else
-
-        setrlimit(RLIMIT_DATA, &r);                        /* Ignore errors */
+  /* Since we always have a forkserver (or a fauxserver) running, we can simply
+  tell them to have at it and read back the pid from it.*/
 
-#endif                                                        /* ^RLIMIT_AS */
-
-      }
-
-      r.rlim_max = r.rlim_cur = 0;
-
-      setrlimit(RLIMIT_CORE, &r);                          /* Ignore errors */
-
-      /* Isolate the process and configure standard descriptors. If
-         afl->fsrv.out_file is specified, stdin is /dev/null; otherwise,
-         afl->fsrv.out_fd is cloned instead. */
-
-      setsid();
-
-      dup2(afl->fsrv.dev_null_fd, 1);
-      dup2(afl->fsrv.dev_null_fd, 2);
-
-      if (afl->fsrv.out_file) {
-
-        dup2(afl->fsrv.dev_null_fd, 0);
-
-      } else {
+  if ((res = write(afl->cmplog_fsrv_ctl_fd, &afl->cmplog_prev_timed_out, 4)) !=
+      4) {
 
-        dup2(afl->fsrv.out_fd, 0);
-        close(afl->fsrv.out_fd);
+    if (afl->stop_soon) return 0;
+    RPFATAL(res,
+            "Unable to request new process from cmplog fork server (OOM?)");
 
-      }
-
-      /* On Linux, would be faster to use O_CLOEXEC. Maybe TODO. */
-
-      close(afl->fsrv.dev_null_fd);
-      close(afl->fsrv.out_dir_fd);
-#ifndef HAVE_ARC4RANDOM
-      close(afl->fsrv.dev_urandom_fd);
-#endif
-      close(fileno(afl->fsrv.plot_file));
-
-      /* Set sane defaults for ASAN if nothing else specified. */
-
-      setenv("ASAN_OPTIONS",
-             "abort_on_error=1:"
-             "detect_leaks=0:"
-             "symbolize=0:"
-             "allocator_may_return_null=1",
-             0);
-
-      setenv("MSAN_OPTIONS", "exit_code=" STRINGIFY(MSAN_ERROR) ":"
-                             "symbolize=0:"
-                             "msan_track_origins=0", 0);
-
-      setenv("___AFL_EINS_ZWEI_POLIZEI___", "1", 1);
-
-      if (!afl->qemu_mode && afl->argv[0] != afl->cmplog_binary) {
-
-        ck_free(afl->argv[0]);
-        afl->argv[0] = afl->cmplog_binary;
-
-      }
-
-      execv(afl->argv[0], afl->argv);
-
-      /* Use a distinctive bitmap value to tell the parent about execv()
-         falling through. */
-
-      *(u32 *)afl->fsrv.trace_bits = EXEC_FAIL_SIG;
-      exit(0);
-
-    }
-
-  } else {
-
-    s32 res;
-
-    /* In non-dumb mode, we have the fork server up and running, so simply
-       tell it to have at it, and then read back PID. */
-
-    if ((res = write(afl->cmplog_fsrv_ctl_fd, &prev_timed_out, 4)) != 4) {
-
-      if (afl->stop_soon) return 0;
-      RPFATAL(res,
-              "Unable to request new process from cmplog fork server (OOM?)");
-
-    }
-
-    if ((res = read(afl->cmplog_fsrv_st_fd, &afl->cmplog_child_pid, 4)) != 4) {
-
-      if (afl->stop_soon) return 0;
-      RPFATAL(res,
-              "Unable to request new process from cmplog fork server (OOM?)");
+  }
 
-    }
+  if ((res = read(afl->cmplog_fsrv_st_fd, &afl->cmplog_child_pid, 4)) != 4) {
 
-    if (afl->cmplog_child_pid <= 0)
-      FATAL("Cmplog fork server is misbehaving (OOM?)");
+    if (afl->stop_soon) return 0;
+    RPFATAL(res,
+            "Unable to request new process from cmplog fork server (OOM?)");
 
   }
 
+  if (afl->cmplog_child_pid <= 0)
+    FATAL("Cmplog fork server is misbehaving (OOM?)");
+
   /* Configure timeout, as requested by user, then wait for child to terminate.
    */
 
-  it.it_value.tv_sec = (timeout / 1000);
-  it.it_value.tv_usec = (timeout % 1000) * 1000;
+  it.tv_sec = (timeout / 1000);
+  it.tv_usec = (timeout % 1000) * 1000;
 
-  setitimer(ITIMER_REAL, &it, NULL);
+  FD_ZERO(&readfds);
+  FD_SET(afl->cmplog_fsrv_st_fd, &readfds);
+  it.tv_sec = ((timeout) / 1000);
+  it.tv_usec = ((timeout) % 1000) * 1000;
 
-  /* The SIGALRM handler simply kills the afl->cmplog_child_pid and sets
-   * afl->fsrv.child_timed_out. */
+  sret = select(afl->cmplog_fsrv_st_fd + 1, &readfds, NULL, NULL, &it);
 
-  if (afl->dumb_mode == 1 || afl->no_forkserver) {
+  if (sret == 0) {
 
-    if (waitpid(afl->cmplog_child_pid, &status, 0) <= 0)
-      PFATAL("waitpid() failed");
+    /* If there was no response from forkserver after timeout seconds,
+    we kill the child. The forkserver should inform us afterwards */
 
-  } else {
+    kill(afl->cmplog_child_pid, SIGKILL);
+    afl->fsrv.child_timed_out = 1;
 
-    s32 res;
-
-    if ((res = read(afl->cmplog_fsrv_st_fd, &status, 4)) != 4) {
-
-      if (afl->stop_soon) return 0;
-      SAYF(
-          "\n" cLRD "[-] " cRST
-          "Unable to communicate with fork server. Some possible reasons:\n\n"
-          "    - You've run out of memory. Use -m to increase the the memory "
-          "limit\n"
-          "      to something higher than %lld.\n"
-          "    - The binary or one of the libraries it uses manages to create\n"
-          "      threads before the forkserver initializes.\n"
-          "    - The binary, at least in some circumstances, exits in a way "
-          "that\n"
-          "      also kills the parent process - raise() could be the "
-          "culprit.\n\n"
-          "If all else fails you can disable the fork server via "
-          "AFL_NO_FORKSRV=1.\n",
-          afl->fsrv.mem_limit);
-      RPFATAL(res, "Unable to communicate with fork server");
+  }
 
-    }
+  if ((res = read(afl->cmplog_fsrv_st_fd, &status, 4)) != 4) {
+
+    if (afl->stop_soon) return 0;
+    SAYF("\n" cLRD "[-] " cRST
+         "Unable to communicate with fork server. Some possible reasons:\n\n"
+         "    - You've run out of memory. Use -m to increase the the memory "
+         "limit\n"
+         "      to something higher than %lld.\n"
+         "    - The binary or one of the libraries it uses manages to create\n"
+         "      threads before the forkserver initializes.\n"
+         "    - The binary, at least in some circumstances, exits in a way "
+         "that\n"
+         "      also kills the parent process - raise() could be the "
+         "culprit.\n\n"
+         "If all else fails you can disable the fork server via "
+         "AFL_NO_FORKSRV=1.\n",
+         afl->fsrv.mem_limit);
+    RPFATAL(res, "Unable to communicate with fork server");
 
   }
 
   if (!WIFSTOPPED(status)) afl->cmplog_child_pid = 0;
 
-  getitimer(ITIMER_REAL, &it);
-  exec_ms =
-      (u64)timeout - (it.it_value.tv_sec * 1000 + it.it_value.tv_usec / 1000);
+  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.it_value.tv_sec = 0;
-  it.it_value.tv_usec = 0;
-
-  setitimer(ITIMER_REAL, &it, NULL);
+  it.tv_sec = 0;
+  it.tv_usec = 0;
 
   ++afl->total_execs;
 
@@ -584,7 +489,7 @@ u8 run_cmplog_target(afl_state_t *afl, u32 timeout) {
   classify_counts((u32 *)afl->fsrv.trace_bits);
 #endif                                                     /* ^WORD_SIZE_64 */
 
-  prev_timed_out = afl->fsrv.child_timed_out;
+  afl->cmplog_prev_timed_out = afl->fsrv.child_timed_out;
 
   /* Report outcome to caller. */
 
diff --git a/src/afl-fuzz-extras.c b/src/afl-fuzz-extras.c
index ff4c0ae2..4dd1647c 100644
--- a/src/afl-fuzz-extras.c
+++ b/src/afl-fuzz-extras.c
@@ -55,6 +55,8 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len,
   u8 *  lptr;
   u32   cur_line = 0;
 
+  u8 val_bufs[2][STRINGIFY_VAL_SIZE_MAX];
+
   f = fopen(fname, "r");
 
   if (!f) PFATAL("Unable to open '%s'", fname);
@@ -170,8 +172,10 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len,
     afl->extras[afl->extras_cnt].len = klen;
 
     if (afl->extras[afl->extras_cnt].len > MAX_DICT_FILE)
-      FATAL("Keyword too big in line %u (%s, limit is %s)", cur_line, DMS(klen),
-            DMS(MAX_DICT_FILE));
+      FATAL(
+          "Keyword too big in line %u (%s, limit is %s)", cur_line,
+          stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), klen),
+          stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), MAX_DICT_FILE));
 
     if (*min_len > klen) *min_len = klen;
     if (*max_len < klen) *max_len = klen;
@@ -193,6 +197,8 @@ void load_extras(afl_state_t *afl, u8 *dir) {
   u32            min_len = MAX_DICT_FILE, max_len = 0, dict_level = 0;
   u8 *           x;
 
+  u8 val_bufs[2][STRINGIFY_VAL_SIZE_MAX];
+
   /* If the name ends with @, extract level and continue. */
 
   if ((x = strchr(dir, '@'))) {
@@ -238,8 +244,10 @@ void load_extras(afl_state_t *afl, u8 *dir) {
     }
 
     if (st.st_size > MAX_DICT_FILE)
-      FATAL("Extra '%s' is too big (%s, limit is %s)", fn, DMS(st.st_size),
-            DMS(MAX_DICT_FILE));
+      FATAL(
+          "Extra '%s' is too big (%s, limit is %s)", fn,
+          stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), st.st_size),
+          stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), MAX_DICT_FILE));
 
     if (min_len > st.st_size) min_len = st.st_size;
     if (max_len < st.st_size) max_len = st.st_size;
@@ -273,11 +281,12 @@ check_and_sort:
         compare_extras_len);
 
   OKF("Loaded %u extra tokens, size range %s to %s.", afl->extras_cnt,
-      DMS(min_len), DMS(max_len));
+      stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), min_len),
+      stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), max_len));
 
   if (max_len > 32)
     WARNF("Some tokens are relatively large (%s) - consider trimming.",
-          DMS(max_len));
+          stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), max_len));
 
   if (afl->extras_cnt > MAX_DET_EXTRAS)
     WARNF("More than %d tokens - will use them probabilistically.",
@@ -378,7 +387,7 @@ void maybe_add_auto(afl_state_t *afl, u8 *mem, u32 len) {
 
   } else {
 
-    i = MAX_AUTO_EXTRAS / 2 + UR(afl, (MAX_AUTO_EXTRAS + 1) / 2);
+    i = MAX_AUTO_EXTRAS / 2 + rand_below(afl, (MAX_AUTO_EXTRAS + 1) / 2);
 
     ck_free(afl->a_extras[i].data);
 
diff --git a/src/afl-fuzz-globals.c b/src/afl-fuzz-globals.c
index efffa749..88633a1b 100644
--- a/src/afl-fuzz-globals.c
+++ b/src/afl-fuzz-globals.c
@@ -30,8 +30,9 @@ s8  interesting_8[] = {INTERESTING_8};
 s16 interesting_16[] = {INTERESTING_8, INTERESTING_16};
 s32 interesting_32[] = {INTERESTING_8, INTERESTING_16, INTERESTING_32};
 
-char *power_names[POWER_SCHEDULES_NUM] = {"explore", "fast",    "coe",  "lin",
-                                          "quad",    "exploit", "mmopt"};
+char *power_names[POWER_SCHEDULES_NUM] = {
+
+    "explore", "fast", "coe", "lin", "quad", "exploit", "mmopt", "rare"};
 
 u8 *doc_path = NULL;                    /* gath to documentation dir        */
 
@@ -78,6 +79,8 @@ list_t afl_states = {.element_prealloc_count = 0};
 
 void afl_state_init(afl_state_t *afl) {
 
+  memset(afl, 0, sizeof(afl_state_t));
+
   afl->w_init = 0.9;
   afl->w_end = 0.3;
   afl->g_max = 5000;
@@ -114,6 +117,29 @@ void afl_state_init(afl_state_t *afl) {
   afl->fsrv.child_pid = -1;
   afl->fsrv.out_dir_fd = -1;
 
+  afl->cmplog_prev_timed_out = 0;
+
+  /* statis file */
+  afl->last_bitmap_cvg = 0;
+  afl->last_stability = 0;
+  afl->last_eps = 0;
+
+  /* plot file saves from last run */
+  afl->plot_prev_qp = 0;
+  afl->plot_prev_pf = 0;
+  afl->plot_prev_pnf = 0;
+  afl->plot_prev_ce = 0;
+  afl->plot_prev_md = 0;
+  afl->plot_prev_qc = 0;
+  afl->plot_prev_uc = 0;
+  afl->plot_prev_uh = 0;
+
+  afl->stats_last_stats_ms = 0;
+  afl->stats_last_plot_ms = 0;
+  afl->stats_last_ms = 0;
+  afl->stats_last_execs = 0;
+  afl->stats_avg_exec = -1;
+
   init_mopt_globals(afl);
 
   list_append(&afl_states, afl);
diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c
index 6b5fa24f..038c4393 100644
--- a/src/afl-fuzz-init.c
+++ b/src/afl-fuzz-init.c
@@ -304,7 +304,7 @@ static void shuffle_ptrs(afl_state_t *afl, void **ptrs, u32 cnt) {
 
   for (i = 0; i < cnt - 2; ++i) {
 
-    u32   j = i + UR(afl, cnt - i);
+    u32   j = i + rand_below(afl, cnt - i);
     void *s = ptrs[i];
     ptrs[i] = ptrs[j];
     ptrs[j] = s;
@@ -323,6 +323,8 @@ void read_testcases(afl_state_t *afl) {
   u32             i;
   u8 *            fn1;
 
+  u8 val_buf[2][STRINGIFY_VAL_SIZE_MAX];
+
   /* Auto-detect non-in-place resumption attempts. */
 
   fn1 = alloc_printf("%s/queue", afl->in_dir);
@@ -389,8 +391,9 @@ void read_testcases(afl_state_t *afl) {
     }
 
     if (st.st_size > MAX_FILE)
-      FATAL("Test case '%s' is too big (%s, limit is %s)", fn2, DMS(st.st_size),
-            DMS(MAX_FILE));
+      FATAL("Test case '%s' is too big (%s, limit is %s)", fn2,
+            stringify_mem_size(val_buf[0], sizeof(val_buf[0]), st.st_size),
+            stringify_mem_size(val_buf[1], sizeof(val_buf[1]), MAX_FILE));
 
     /* Check for metadata that indicates that deterministic fuzzing
        is complete for this entry. We don't want to repeat deterministic
@@ -553,6 +556,8 @@ void perform_dry_run(afl_state_t *afl) {
 
         if (afl->fsrv.mem_limit) {
 
+          u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
+
           SAYF("\n" cLRD "[-] " cRST
                "Oops, the program crashed with one of the test cases provided. "
                "There are\n"
@@ -593,8 +598,9 @@ void perform_dry_run(afl_state_t *afl) {
                "other options\n"
                "      fail, poke <afl-users@googlegroups.com> for "
                "troubleshooting tips.\n",
-               DMS(afl->fsrv.mem_limit << 20), afl->fsrv.mem_limit - 1,
-               doc_path);
+               stringify_mem_size(val_buf, sizeof(val_buf),
+                                  afl->fsrv.mem_limit << 20),
+               afl->fsrv.mem_limit - 1, doc_path);
 
         } else {
 
@@ -797,7 +803,7 @@ void pivot_inputs(afl_state_t *afl) {
 
 u32 find_start_position(afl_state_t *afl) {
 
-  static u8 tmp[4096];                   /* Ought to be enough for anybody. */
+  u8 tmp[4096] = {0};                    /* Ought to be enough for anybody. */
 
   u8 *fn, *off;
   s32 fd, i;
@@ -834,7 +840,7 @@ u32 find_start_position(afl_state_t *afl) {
 
 void find_timeout(afl_state_t *afl) {
 
-  static u8 tmp[4096];                   /* Ought to be enough for anybody. */
+  u8 tmp[4096] = {0};                    /* Ought to be enough for anybody. */
 
   u8 *fn, *off;
   s32 fd, i;
@@ -902,7 +908,7 @@ static u8 delete_files(u8 *path, u8 *prefix) {
 
 double get_runnable_processes(void) {
 
-  static double res;
+  double res = 0;
 
 #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \
     defined(__NetBSD__) || defined(__DragonFly__)
@@ -1049,7 +1055,7 @@ static void handle_existing_out_dir(afl_state_t *afl) {
 
     /* Let's see how much work is at stake. */
 
-    if (!afl->in_place_resume &&
+    if (!afl->in_place_resume && last_update > start_time2 &&
         last_update - start_time2 > OUTPUT_GRACE * 60) {
 
       SAYF("\n" cLRD "[-] " cRST
@@ -1787,7 +1793,7 @@ void fix_up_sync(afl_state_t *afl) {
 
 static void handle_resize(int sig) {
 
-  LIST_FOREACH(&afl_states, afl_state_t, { el->clear_screen; });
+  LIST_FOREACH(&afl_states, afl_state_t, { el->clear_screen = 1; });
 
 }
 
@@ -2008,7 +2014,7 @@ void check_binary(afl_state_t *afl, u8 *fname) {
 
   }
 
-  if (memmem(f_data, f_len, "libasan.so", 10) ||
+  if (memmem(f_data, f_len, "__asan_init", 11) ||
       memmem(f_data, f_len, "__msan_init", 11))
     afl->fsrv.uses_asan = 1;
 
@@ -2125,11 +2131,6 @@ void setup_signal_handlers(void) {
   sigaction(SIGINT, &sa, NULL);
   sigaction(SIGTERM, &sa, NULL);
 
-  /* Exec timeout notifications. */
-
-  sa.sa_handler = handle_timeout;
-  sigaction(SIGALRM, &sa, NULL);
-
   /* Window resize */
 
   sa.sa_handler = handle_resize;
diff --git a/src/afl-fuzz-misc.c b/src/afl-fuzz-misc.c
deleted file mode 100644
index 29e8bd82..00000000
--- a/src/afl-fuzz-misc.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
-   american fuzzy lop++ - misc stuffs from Mordor
-   ----------------------------------------------
-
-   Originally written by Michal Zalewski
-
-   Now maintained by Marc Heuse <mh@mh-sec.de>,
-                        Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
-                        Andrea Fioraldi <andreafioraldi@gmail.com>
-
-   Copyright 2016, 2017 Google Inc. All rights reserved.
-   Copyright 2019-2020 AFLplusplus Project. All rights reserved.
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at:
-
-     http://www.apache.org/licenses/LICENSE-2.0
-
-   This is the real deal: the program takes an instrumented binary and
-   attempts a variety of basic fuzzing tricks, paying close attention to
-   how they affect the execution path.
-
- */
-
-#include "afl-fuzz.h"
-
-/* Describe integer. Uses 12 cyclic static buffers for return values. The value
-   returned should be five characters or less for all the integers we reasonably
-   expect to see. */
-
-u8 *DI(u64 val) {
-
-  static u8 tmp[12][16];
-  static u8 cur;
-
-  cur = (cur + 1) % 12;
-
-#define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast)    \
-  do {                                                    \
-                                                          \
-    if (val < (_divisor) * (_limit_mult)) {               \
-                                                          \
-      sprintf(tmp[cur], _fmt, ((_cast)val) / (_divisor)); \
-      return tmp[cur];                                    \
-                                                          \
-    }                                                     \
-                                                          \
-  } 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(tmp[cur], "infty");
-  return tmp[cur];
-
-}
-
-/* Describe float. Similar to the above, except with a single
-   static buffer. */
-
-u8 *DF(double val) {
-
-  static u8 tmp[16];
-
-  if (val < 99.995) {
-
-    sprintf(tmp, "%0.02f", val);
-    return tmp;
-
-  }
-
-  if (val < 999.95) {
-
-    sprintf(tmp, "%0.01f", val);
-    return tmp;
-
-  }
-
-  return DI((u64)val);
-
-}
-
-/* Describe integer as memory size. */
-
-u8 *DMS(u64 val) {
-
-  static u8 tmp[12][16];
-  static u8 cur;
-
-  cur = (cur + 1) % 12;
-
-  /* 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(tmp[cur], "infty");
-  return tmp[cur];
-
-}
-
-/* Describe time delta. Returns one static buffer, 34 chars of less. */
-
-u8 *DTD(u64 cur_ms, u64 event_ms) {
-
-  static u8 tmp[64];
-  u64       delta;
-  s32       t_d, t_h, t_m, t_s;
-
-  if (!event_ms) return "none seen yet";
-
-  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;
-
-  sprintf(tmp, "%s days, %d hrs, %d min, %d sec", DI(t_d), t_h, t_m, t_s);
-  return tmp;
-
-}
-
diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c
index 9071404d..0ded4ba1 100644
--- a/src/afl-fuzz-mutators.c
+++ b/src/afl-fuzz-mutators.c
@@ -27,7 +27,7 @@
 
 void load_custom_mutator(afl_state_t *, const char *);
 #ifdef USE_PYTHON
-void load_custom_mutator_py(afl_state_t *, const char *);
+void load_custom_mutator_py(afl_state_t *, char *);
 #endif
 
 void setup_custom_mutator(afl_state_t *afl) {
@@ -59,10 +59,7 @@ void setup_custom_mutator(afl_state_t *afl) {
       FATAL(
           "MOpt and Python mutator are mutually exclusive. We accept pull "
           "requests that integrates MOpt with the optional mutators "
-          "(custom/radamsa/redquenn/...).");
-
-    if (init_py_module(afl, module_name))
-      FATAL("Failed to initialize Python module");
+          "(custom/radamsa/redqueen/...).");
 
     load_custom_mutator_py(afl, module_name);
 
@@ -79,18 +76,13 @@ void destroy_custom_mutator(afl_state_t *afl) {
 
   if (afl->mutator) {
 
+    afl->mutator->afl_custom_deinit(afl->mutator->data);
+
     if (afl->mutator->dh)
       dlclose(afl->mutator->dh);
-    else {
-
-      /* Python mutator */
-#ifdef USE_PYTHON
-      finalize_py_module(afl);
-#endif
-
-    }
 
     ck_free(afl->mutator);
+    afl->mutator = NULL;
 
   }
 
@@ -109,10 +101,13 @@ void load_custom_mutator(afl_state_t *afl, const char *fn) {
   afl->mutator->dh = dh;
 
   /* Mutator */
-  /* "afl_custom_init", optional for backward compatibility */
+  /* "afl_custom_init", required */
   afl->mutator->afl_custom_init = dlsym(dh, "afl_custom_init");
-  if (!afl->mutator->afl_custom_init)
-    WARNF("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.");
 
   /* "afl_custom_fuzz" or "afl_custom_mutator", required */
   afl->mutator->afl_custom_fuzz = dlsym(dh, "afl_custom_fuzz");
@@ -186,25 +181,24 @@ 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, UR(afl, 0xFFFFFFFF));
+    afl->mutator->afl_custom_init(afl, rand_below(afl, 0xFFFFFFFF));
 
 }
 
 u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
 
-  static u8 tmp[64];
-  static u8 clean_trace[MAP_SIZE];
-
   u8  needs_write = 0, fault = 0;
   u32 trim_exec = 0;
   u32 orig_len = q->len;
 
-  afl->stage_name = tmp;
+  u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
+
+  afl->stage_name = afl->stage_name_buf;
   afl->bytes_trim_in += q->len;
 
   /* Initialize trimming in the custom mutator */
   afl->stage_cur = 0;
-  afl->stage_max = afl->mutator->afl_custom_init_trim(afl, in_buf, q->len);
+  afl->stage_max = afl->mutator->afl_custom_init_trim(afl->mutator->data, in_buf, q->len);
 
   if (afl->not_on_tty && afl->debug)
     SAYF("[Custom Trimming] START: Max %d iterations, %u bytes", afl->stage_max,
@@ -212,7 +206,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
 
   while (afl->stage_cur < afl->stage_max) {
 
-    sprintf(tmp, "ptrim %s", DI(trim_exec));
+    sprintf(afl->stage_name_buf, "ptrim %s", u_stringify_int(val_buf, trim_exec));
 
     u32 cksum;
 
@@ -251,7 +245,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
       if (!needs_write) {
 
         needs_write = 1;
-        memcpy(clean_trace, afl->fsrv.trace_bits, MAP_SIZE);
+        memcpy(afl->clean_trace_custom, afl->fsrv.trace_bits, MAP_SIZE);
 
       }
 
@@ -299,7 +293,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
     ck_write(fd, in_buf, q->len, q->fname);
     close(fd);
 
-    memcpy(afl->fsrv.trace_bits, clean_trace, MAP_SIZE);
+    memcpy(afl->fsrv.trace_bits, afl->clean_trace_custom, MAP_SIZE);
     update_bitmap_score(afl, q);
 
   }
@@ -310,54 +304,3 @@ abort_trimming:
   return fault;
 
 }
-
-#ifdef USE_PYTHON
-void load_custom_mutator_py(afl_state_t *afl, const char *module_name) {
-
-  PyObject **py_functions = afl->py_functions;
-
-  afl->mutator = ck_alloc(sizeof(struct custom_mutator));
-
-  afl->mutator->name = module_name;
-  ACTF("Loading Python mutator library from '%s'...", module_name);
-
-  if (py_functions[PY_FUNC_INIT]) afl->mutator->afl_custom_init = init_py;
-
-  /* "afl_custom_fuzz" should not be NULL, but the interface of Python mutator
-     is quite different from the custom mutator. */
-  afl->mutator->afl_custom_fuzz = fuzz_py;
-
-  if (py_functions[PY_FUNC_PRE_SAVE])
-    afl->mutator->afl_custom_pre_save = pre_save_py;
-
-  if (py_functions[PY_FUNC_INIT_TRIM])
-    afl->mutator->afl_custom_init_trim = init_trim_py;
-
-  if (py_functions[PY_FUNC_POST_TRIM])
-    afl->mutator->afl_custom_post_trim = post_trim_py;
-
-  if (py_functions[PY_FUNC_TRIM]) afl->mutator->afl_custom_trim = trim_py;
-
-  if (py_functions[PY_FUNC_HAVOC_MUTATION])
-    afl->mutator->afl_custom_havoc_mutation = havoc_mutation_py;
-
-  if (py_functions[PY_FUNC_HAVOC_MUTATION_PROBABILITY])
-    afl->mutator->afl_custom_havoc_mutation_probability =
-        havoc_mutation_probability_py;
-
-  if (py_functions[PY_FUNC_QUEUE_GET])
-    afl->mutator->afl_custom_queue_get = queue_get_py;
-
-  if (py_functions[PY_FUNC_QUEUE_NEW_ENTRY])
-    afl->mutator->afl_custom_queue_new_entry = queue_new_entry_py;
-
-  OKF("Python mutator '%s' installed successfully.", module_name);
-
-  /* Initialize the custom mutator */
-  if (afl->mutator->afl_custom_init)
-    afl->mutator->afl_custom_init(afl, UR(afl, 0xFFFFFFFF));
-
-}
-
-#endif
-
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index 92210c8b..cc150cfe 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -31,7 +31,7 @@ int select_algorithm(afl_state_t *afl) {
 
   int i_puppet, j_puppet;
 
-  double sele = ((double)(UR(afl, 10000)) * 0.0001);
+  double sele = ((double)(rand_below(afl, 10000)) * 0.0001);
   j_puppet = 0;
   for (i_puppet = 0; i_puppet < operator_num; ++i_puppet) {
 
@@ -67,9 +67,9 @@ static u32 choose_block_len(afl_state_t *afl, u32 limit) {
   u32 min_value, max_value;
   u32 rlim = MIN(afl->queue_cycle, 3);
 
-  if (!afl->run_over10m) rlim = 1;
+  if (unlikely(!afl->run_over10m)) rlim = 1;
 
-  switch (UR(afl, rlim)) {
+  switch (rand_below(afl, rlim)) {
 
     case 0:
       min_value = 1;
@@ -83,7 +83,7 @@ static u32 choose_block_len(afl_state_t *afl, u32 limit) {
 
     default:
 
-      if (UR(afl, 10)) {
+      if (rand_below(afl, 10)) {
 
         min_value = HAVOC_BLK_MEDIUM;
         max_value = HAVOC_BLK_LARGE;
@@ -99,7 +99,7 @@ static u32 choose_block_len(afl_state_t *afl, u32 limit) {
 
   if (min_value >= limit) min_value = 1;
 
-  return min_value + UR(afl, MIN(max_value, limit) - min_value + 1);
+  return min_value + rand_below(afl, MIN(max_value, limit) - min_value + 1);
 
 }
 
@@ -356,7 +356,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
 
 #else
 
-  if (afl->mutator && afl->mutator->afl_custom_queue_get) {
+  if (unlikely(afl->mutator) && unlikely(afl->mutator->afl_custom_queue_get)) {
 
     /* The custom mutator will decide to skip this test case or not. */
 
@@ -365,7 +365,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
 
   }
 
-  if (afl->pending_favored) {
+  if (likely(afl->pending_favored)) {
 
     /* If we have any favored, non-fuzzed new arrivals in the queue,
        possibly skip to them at the expense of already-fuzzed or non-favored
@@ -373,7 +373,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
 
     if (((afl->queue_cur->was_fuzzed > 0 || afl->queue_cur->fuzz_level > 0) ||
          !afl->queue_cur->favored) &&
-        UR(afl, 100) < SKIP_TO_NEW_PROB)
+        rand_below(afl, 100) < SKIP_TO_NEW_PROB)
       return 1;
 
   } else if (!afl->dumb_mode && !afl->queue_cur->favored &&
@@ -387,11 +387,11 @@ u8 fuzz_one_original(afl_state_t *afl) {
     if (afl->queue_cycle > 1 &&
         (afl->queue_cur->fuzz_level == 0 || afl->queue_cur->was_fuzzed)) {
 
-      if (UR(afl, 100) < SKIP_NFAV_NEW_PROB) return 1;
+      if (rand_below(afl, 100) < SKIP_NFAV_NEW_PROB) return 1;
 
     } else {
 
-      if (UR(afl, 100) < SKIP_NFAV_OLD_PROB) return 1;
+      if (rand_below(afl, 100) < SKIP_NFAV_OLD_PROB) return 1;
 
     }
 
@@ -399,7 +399,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
 
 #endif                                                     /* ^IGNORE_FINDS */
 
-  if (afl->not_on_tty) {
+  if (unlikely(afl->not_on_tty)) {
 
     ACTF("Fuzzing test case #%u (%u total, %llu uniq crashes found)...",
          afl->current_entry, afl->queued_paths, afl->unique_crashes);
@@ -411,13 +411,13 @@ u8 fuzz_one_original(afl_state_t *afl) {
 
   fd = open(afl->queue_cur->fname, O_RDONLY);
 
-  if (fd < 0) PFATAL("Unable to open '%s'", afl->queue_cur->fname);
+  if (unlikely(fd < 0)) PFATAL("Unable to open '%s'", afl->queue_cur->fname);
 
   len = afl->queue_cur->len;
 
   orig_in = in_buf = mmap(0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
 
-  if (orig_in == MAP_FAILED)
+  if (unlikely(orig_in == MAP_FAILED))
     PFATAL("Unable to mmap '%s' with len %d", afl->queue_cur->fname, len);
 
   close(fd);
@@ -436,7 +436,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
    * CALIBRATION (only if failed earlier on) *
    *******************************************/
 
-  if (afl->queue_cur->cal_failed) {
+  if (unlikely(afl->queue_cur->cal_failed)) {
 
     u8 res = FAULT_TMOUT;
 
@@ -445,11 +445,12 @@ u8 fuzz_one_original(afl_state_t *afl) {
       res =
           calibrate_case(afl, afl->queue_cur, in_buf, afl->queue_cycle - 1, 0);
 
-      if (res == FAULT_ERROR) FATAL("Unable to execute target application");
+      if (unlikely(res == FAULT_ERROR))
+        FATAL("Unable to execute target application");
 
     }
 
-    if (afl->stop_soon || res != afl->crash_mode) {
+    if (unlikely(afl->stop_soon) || res != afl->crash_mode) {
 
       ++afl->cur_skipped_paths;
       goto abandon_entry;
@@ -466,9 +467,10 @@ u8 fuzz_one_original(afl_state_t *afl) {
 
     u8 res = trim_case(afl, afl->queue_cur, in_buf);
 
-    if (res == FAULT_ERROR) FATAL("Unable to execute target application");
+    if (unlikely(res == FAULT_ERROR))
+      FATAL("Unable to execute target application");
 
-    if (afl->stop_soon) {
+    if (unlikely(afl->stop_soon)) {
 
       ++afl->cur_skipped_paths;
       goto abandon_entry;
@@ -491,9 +493,9 @@ u8 fuzz_one_original(afl_state_t *afl) {
 
   orig_perf = perf_score = calculate_score(afl, afl->queue_cur);
 
-  if (perf_score == 0) goto abandon_entry;
+  if (unlikely(perf_score == 0)) goto abandon_entry;
 
-  if (afl->use_radamsa > 1) goto radamsa_stage;
+  if (unlikely(afl->use_radamsa > 1)) goto radamsa_stage;
 
   if (afl->shm.cmplog_mode) {
 
@@ -1401,7 +1403,7 @@ skip_interest:
          map. */
 
       if ((afl->extras_cnt > MAX_DET_EXTRAS &&
-           UR(afl, afl->extras_cnt) >= MAX_DET_EXTRAS) ||
+           rand_below(afl, afl->extras_cnt) >= MAX_DET_EXTRAS) ||
           afl->extras[j].len > len - i ||
           !memcmp(afl->extras[j].data, out_buf + i, afl->extras[j].len) ||
           !memchr(eff_map + EFF_APOS(i), 1,
@@ -1549,8 +1551,8 @@ custom_mutator_stage:
    * CUSTOM MUTATORS *
    *******************/
 
-  if (!afl->mutator) goto havoc_stage;
-  if (!afl->mutator->afl_custom_fuzz) goto havoc_stage;
+  if (likely(!afl->mutator)) goto havoc_stage;
+  if (likely(!afl->mutator->afl_custom_fuzz)) goto havoc_stage;
 
   afl->stage_name = "custom mutator";
   afl->stage_short = "custom";
@@ -1573,7 +1575,7 @@ custom_mutator_stage:
     /* Pick a random other queue entry for passing to external API */
     do {
 
-      tid = UR(afl, afl->queued_paths);
+      tid = rand_below(afl, afl->queued_paths);
 
     } while (tid == afl->current_entry && afl->queued_paths > 1);
 
@@ -1603,7 +1605,7 @@ custom_mutator_stage:
 
     /* Read the additional testcase into a new buffer. */
     fd = open(target->fname, O_RDONLY);
-    if (fd < 0) PFATAL("Unable to open '%s'", target->fname);
+    if (unlikely(fd < 0)) PFATAL("Unable to open '%s'", target->fname);
     new_buf = ck_alloc_nozero(target->len);
     ck_read(fd, new_buf, target->len, target->fname);
     close(fd);
@@ -1649,7 +1651,7 @@ custom_mutator_stage:
   afl->stage_finds[STAGE_CUSTOM_MUTATOR] += new_hit_cnt - orig_hit_cnt;
   afl->stage_cycles[STAGE_CUSTOM_MUTATOR] += afl->stage_max;
 
-  if (afl->custom_only) {
+  if (likely(afl->custom_only)) {
 
     /* Skip other stages */
     ret_val = 0;
@@ -1679,8 +1681,8 @@ havoc_stage:
 
     perf_score = orig_perf;
 
-    snprintf(afl->stage_name_buf64, 64, "splice %u", splice_cycle);
-    afl->stage_name = afl->stage_name_buf64;
+    snprintf(afl->stage_name_buf, STAGE_BUF_SIZE, "splice %u", splice_cycle);
+    afl->stage_name = afl->stage_name_buf;
     afl->stage_short = "splice";
     afl->stage_max = SPLICE_HAVOC * perf_score / afl->havoc_div / 100;
 
@@ -1713,34 +1715,35 @@ havoc_stage:
 
   for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) {
 
-    u32 use_stacking = 1 << (1 + UR(afl, HAVOC_STACK_POW2));
+    u32 use_stacking = 1 << (1 + rand_below(afl, HAVOC_STACK_POW2));
 
     afl->stage_cur_val = use_stacking;
 
     for (i = 0; i < use_stacking; ++i) {
 
-      if (stacked_custom && UR(afl, 100) < stacked_custom_prob) {
+      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);
 
       }
 
-      switch (UR(afl, 15 + ((afl->extras_cnt + afl->a_extras_cnt) ? 2 : 0))) {
+      switch (rand_below(
+          afl, 15 + ((afl->extras_cnt + afl->a_extras_cnt) ? 2 : 0))) {
 
         case 0:
 
           /* Flip a single bit somewhere. Spooky! */
 
-          FLIP_BIT(out_buf, UR(afl, temp_len << 3));
+          FLIP_BIT(out_buf, rand_below(afl, temp_len << 3));
           break;
 
         case 1:
 
           /* Set byte to interesting value. */
 
-          out_buf[UR(afl, temp_len)] =
-              interesting_8[UR(afl, sizeof(interesting_8))];
+          out_buf[rand_below(afl, temp_len)] =
+              interesting_8[rand_below(afl, sizeof(interesting_8))];
           break;
 
         case 2:
@@ -1749,15 +1752,15 @@ havoc_stage:
 
           if (temp_len < 2) break;
 
-          if (UR(afl, 2)) {
+          if (rand_below(afl, 2)) {
 
-            *(u16 *)(out_buf + UR(afl, temp_len - 1)) =
-                interesting_16[UR(afl, sizeof(interesting_16) >> 1)];
+            *(u16 *)(out_buf + rand_below(afl, temp_len - 1)) =
+                interesting_16[rand_below(afl, sizeof(interesting_16) >> 1)];
 
           } else {
 
-            *(u16 *)(out_buf + UR(afl, temp_len - 1)) =
-                SWAP16(interesting_16[UR(afl, sizeof(interesting_16) >> 1)]);
+            *(u16 *)(out_buf + rand_below(afl, temp_len - 1)) = SWAP16(
+                interesting_16[rand_below(afl, sizeof(interesting_16) >> 1)]);
 
           }
 
@@ -1769,15 +1772,15 @@ havoc_stage:
 
           if (temp_len < 4) break;
 
-          if (UR(afl, 2)) {
+          if (rand_below(afl, 2)) {
 
-            *(u32 *)(out_buf + UR(afl, temp_len - 3)) =
-                interesting_32[UR(afl, sizeof(interesting_32) >> 2)];
+            *(u32 *)(out_buf + rand_below(afl, temp_len - 3)) =
+                interesting_32[rand_below(afl, sizeof(interesting_32) >> 2)];
 
           } else {
 
-            *(u32 *)(out_buf + UR(afl, temp_len - 3)) =
-                SWAP32(interesting_32[UR(afl, sizeof(interesting_32) >> 2)]);
+            *(u32 *)(out_buf + rand_below(afl, temp_len - 3)) = SWAP32(
+                interesting_32[rand_below(afl, sizeof(interesting_32) >> 2)]);
 
           }
 
@@ -1787,14 +1790,14 @@ havoc_stage:
 
           /* Randomly subtract from byte. */
 
-          out_buf[UR(afl, temp_len)] -= 1 + UR(afl, ARITH_MAX);
+          out_buf[rand_below(afl, temp_len)] -= 1 + rand_below(afl, ARITH_MAX);
           break;
 
         case 5:
 
           /* Randomly add to byte. */
 
-          out_buf[UR(afl, temp_len)] += 1 + UR(afl, ARITH_MAX);
+          out_buf[rand_below(afl, temp_len)] += 1 + rand_below(afl, ARITH_MAX);
           break;
 
         case 6:
@@ -1803,16 +1806,16 @@ havoc_stage:
 
           if (temp_len < 2) break;
 
-          if (UR(afl, 2)) {
+          if (rand_below(afl, 2)) {
 
-            u32 pos = UR(afl, temp_len - 1);
+            u32 pos = rand_below(afl, temp_len - 1);
 
-            *(u16 *)(out_buf + pos) -= 1 + UR(afl, ARITH_MAX);
+            *(u16 *)(out_buf + pos) -= 1 + rand_below(afl, ARITH_MAX);
 
           } else {
 
-            u32 pos = UR(afl, temp_len - 1);
-            u16 num = 1 + UR(afl, ARITH_MAX);
+            u32 pos = rand_below(afl, temp_len - 1);
+            u16 num = 1 + rand_below(afl, ARITH_MAX);
 
             *(u16 *)(out_buf + pos) =
                 SWAP16(SWAP16(*(u16 *)(out_buf + pos)) - num);
@@ -1827,16 +1830,16 @@ havoc_stage:
 
           if (temp_len < 2) break;
 
-          if (UR(afl, 2)) {
+          if (rand_below(afl, 2)) {
 
-            u32 pos = UR(afl, temp_len - 1);
+            u32 pos = rand_below(afl, temp_len - 1);
 
-            *(u16 *)(out_buf + pos) += 1 + UR(afl, ARITH_MAX);
+            *(u16 *)(out_buf + pos) += 1 + rand_below(afl, ARITH_MAX);
 
           } else {
 
-            u32 pos = UR(afl, temp_len - 1);
-            u16 num = 1 + UR(afl, ARITH_MAX);
+            u32 pos = rand_below(afl, temp_len - 1);
+            u16 num = 1 + rand_below(afl, ARITH_MAX);
 
             *(u16 *)(out_buf + pos) =
                 SWAP16(SWAP16(*(u16 *)(out_buf + pos)) + num);
@@ -1851,16 +1854,16 @@ havoc_stage:
 
           if (temp_len < 4) break;
 
-          if (UR(afl, 2)) {
+          if (rand_below(afl, 2)) {
 
-            u32 pos = UR(afl, temp_len - 3);
+            u32 pos = rand_below(afl, temp_len - 3);
 
-            *(u32 *)(out_buf + pos) -= 1 + UR(afl, ARITH_MAX);
+            *(u32 *)(out_buf + pos) -= 1 + rand_below(afl, ARITH_MAX);
 
           } else {
 
-            u32 pos = UR(afl, temp_len - 3);
-            u32 num = 1 + UR(afl, ARITH_MAX);
+            u32 pos = rand_below(afl, temp_len - 3);
+            u32 num = 1 + rand_below(afl, ARITH_MAX);
 
             *(u32 *)(out_buf + pos) =
                 SWAP32(SWAP32(*(u32 *)(out_buf + pos)) - num);
@@ -1875,16 +1878,16 @@ havoc_stage:
 
           if (temp_len < 4) break;
 
-          if (UR(afl, 2)) {
+          if (rand_below(afl, 2)) {
 
-            u32 pos = UR(afl, temp_len - 3);
+            u32 pos = rand_below(afl, temp_len - 3);
 
-            *(u32 *)(out_buf + pos) += 1 + UR(afl, ARITH_MAX);
+            *(u32 *)(out_buf + pos) += 1 + rand_below(afl, ARITH_MAX);
 
           } else {
 
-            u32 pos = UR(afl, temp_len - 3);
-            u32 num = 1 + UR(afl, ARITH_MAX);
+            u32 pos = rand_below(afl, temp_len - 3);
+            u32 num = 1 + rand_below(afl, ARITH_MAX);
 
             *(u32 *)(out_buf + pos) =
                 SWAP32(SWAP32(*(u32 *)(out_buf + pos)) + num);
@@ -1899,7 +1902,7 @@ havoc_stage:
              why not. We use XOR with 1-255 to eliminate the
              possibility of a no-op. */
 
-          out_buf[UR(afl, temp_len)] ^= 1 + UR(afl, 255);
+          out_buf[rand_below(afl, temp_len)] ^= 1 + rand_below(afl, 255);
           break;
 
         case 11 ... 12: {
@@ -1916,7 +1919,7 @@ havoc_stage:
 
           del_len = choose_block_len(afl, temp_len - 1);
 
-          del_from = UR(afl, temp_len - del_len + 1);
+          del_from = rand_below(afl, temp_len - del_len + 1);
 
           memmove(out_buf + del_from, out_buf + del_from + del_len,
                   temp_len - del_from - del_len);
@@ -1933,14 +1936,14 @@ havoc_stage:
 
             /* Clone bytes (75%) or insert a block of constant bytes (25%). */
 
-            u8  actually_clone = UR(afl, 4);
+            u8  actually_clone = rand_below(afl, 4);
             u32 clone_from, clone_to, clone_len;
             u8 *new_buf;
 
             if (actually_clone) {
 
               clone_len = choose_block_len(afl, temp_len);
-              clone_from = UR(afl, temp_len - clone_len + 1);
+              clone_from = rand_below(afl, temp_len - clone_len + 1);
 
             } else {
 
@@ -1949,7 +1952,7 @@ havoc_stage:
 
             }
 
-            clone_to = UR(afl, temp_len);
+            clone_to = rand_below(afl, temp_len);
 
             new_buf = ck_alloc_nozero(temp_len + clone_len);
 
@@ -1963,7 +1966,8 @@ havoc_stage:
               memcpy(new_buf + clone_to, out_buf + clone_from, clone_len);
             else
               memset(new_buf + clone_to,
-                     UR(afl, 2) ? UR(afl, 256) : out_buf[UR(afl, temp_len)],
+                     rand_below(afl, 2) ? rand_below(afl, 256)
+                                        : out_buf[rand_below(afl, temp_len)],
                      clone_len);
 
             /* Tail */
@@ -1989,10 +1993,10 @@ havoc_stage:
 
           copy_len = choose_block_len(afl, temp_len - 1);
 
-          copy_from = UR(afl, temp_len - copy_len + 1);
-          copy_to = UR(afl, temp_len - copy_len + 1);
+          copy_from = rand_below(afl, temp_len - copy_len + 1);
+          copy_to = rand_below(afl, temp_len - copy_len + 1);
 
-          if (UR(afl, 4)) {
+          if (rand_below(afl, 4)) {
 
             if (copy_from != copy_to)
               memmove(out_buf + copy_to, out_buf + copy_from, copy_len);
@@ -2000,7 +2004,8 @@ havoc_stage:
           } else
 
             memset(out_buf + copy_to,
-                   UR(afl, 2) ? UR(afl, 256) : out_buf[UR(afl, temp_len)],
+                   rand_below(afl, 2) ? rand_below(afl, 256)
+                                      : out_buf[rand_below(afl, temp_len)],
                    copy_len);
 
           break;
@@ -2014,18 +2019,18 @@ havoc_stage:
 
           /* Overwrite bytes with an extra. */
 
-          if (!afl->extras_cnt || (afl->a_extras_cnt && UR(afl, 2))) {
+          if (!afl->extras_cnt || (afl->a_extras_cnt && rand_below(afl, 2))) {
 
             /* No user-specified extras or odds in our favor. Let's use an
                auto-detected one. */
 
-            u32 use_extra = UR(afl, afl->a_extras_cnt);
+            u32 use_extra = rand_below(afl, afl->a_extras_cnt);
             u32 extra_len = afl->a_extras[use_extra].len;
             u32 insert_at;
 
             if (extra_len > temp_len) break;
 
-            insert_at = UR(afl, temp_len - extra_len + 1);
+            insert_at = rand_below(afl, temp_len - extra_len + 1);
             memcpy(out_buf + insert_at, afl->a_extras[use_extra].data,
                    extra_len);
 
@@ -2033,13 +2038,13 @@ havoc_stage:
 
             /* No auto extras or odds in our favor. Use the dictionary. */
 
-            u32 use_extra = UR(afl, afl->extras_cnt);
+            u32 use_extra = rand_below(afl, afl->extras_cnt);
             u32 extra_len = afl->extras[use_extra].len;
             u32 insert_at;
 
             if (extra_len > temp_len) break;
 
-            insert_at = UR(afl, temp_len - extra_len + 1);
+            insert_at = rand_below(afl, temp_len - extra_len + 1);
             memcpy(out_buf + insert_at, afl->extras[use_extra].data, extra_len);
 
           }
@@ -2050,15 +2055,15 @@ havoc_stage:
 
         case 16: {
 
-          u32 use_extra, extra_len, insert_at = UR(afl, temp_len + 1);
+          u32 use_extra, extra_len, insert_at = rand_below(afl, temp_len + 1);
           u8 *new_buf;
 
           /* Insert an extra. Do the same dice-rolling stuff as for the
              previous case. */
 
-          if (!afl->extras_cnt || (afl->a_extras_cnt && UR(afl, 2))) {
+          if (!afl->extras_cnt || (afl->a_extras_cnt && rand_below(afl, 2))) {
 
-            use_extra = UR(afl, afl->a_extras_cnt);
+            use_extra = rand_below(afl, afl->a_extras_cnt);
             extra_len = afl->a_extras[use_extra].len;
 
             if (temp_len + extra_len >= MAX_FILE) break;
@@ -2074,7 +2079,7 @@ havoc_stage:
 
           } else {
 
-            use_extra = UR(afl, afl->extras_cnt);
+            use_extra = rand_below(afl, afl->extras_cnt);
             extra_len = afl->extras[use_extra].len;
 
             if (temp_len + extra_len >= MAX_FILE) break;
@@ -2182,7 +2187,7 @@ retry_splicing:
 
     do {
 
-      tid = UR(afl, afl->queued_paths);
+      tid = rand_below(afl, afl->queued_paths);
 
     } while (tid == afl->current_entry);
 
@@ -2214,7 +2219,7 @@ retry_splicing:
 
     fd = open(target->fname, O_RDONLY);
 
-    if (fd < 0) PFATAL("Unable to open '%s'", target->fname);
+    if (unlikely(fd < 0)) PFATAL("Unable to open '%s'", target->fname);
 
     new_buf = ck_alloc_nozero(target->len);
 
@@ -2237,7 +2242,7 @@ retry_splicing:
 
     /* Split somewhere between the first and last differing byte. */
 
-    split_at = f_diff + UR(afl, l_diff - f_diff);
+    split_at = f_diff + rand_below(afl, l_diff - f_diff);
 
     /* Do the thing. */
 
@@ -2263,7 +2268,7 @@ retry_splicing:
 
 radamsa_stage:
 
-  if (!afl->use_radamsa || !afl->radamsa_mutate_ptr) goto abandon_entry;
+  if (likely(!afl->use_radamsa || !afl->radamsa_mutate_ptr)) goto abandon_entry;
 
   afl->stage_name = "radamsa";
   afl->stage_short = "radamsa";
@@ -2391,7 +2396,7 @@ u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
        cases. */
 
     if ((afl->queue_cur->was_fuzzed || !afl->queue_cur->favored) &&
-        UR(afl, 100) < SKIP_TO_NEW_PROB)
+        rand_below(afl, 100) < SKIP_TO_NEW_PROB)
       return 1;
 
   } else if (!afl->dumb_mode && !afl->queue_cur->favored &&
@@ -2404,11 +2409,11 @@ u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
 
     if (afl->queue_cycle > 1 && !afl->queue_cur->was_fuzzed) {
 
-      if (UR(afl, 100) < SKIP_NFAV_NEW_PROB) return 1;
+      if (rand_below(afl, 100) < SKIP_NFAV_NEW_PROB) return 1;
 
     } else {
 
-      if (UR(afl, 100) < SKIP_NFAV_OLD_PROB) return 1;
+      if (rand_below(afl, 100) < SKIP_NFAV_OLD_PROB) return 1;
 
     }
 
@@ -3407,7 +3412,7 @@ skip_interest:
          map. */
 
       if ((afl->extras_cnt > MAX_DET_EXTRAS &&
-           UR(afl, afl->extras_cnt) >= MAX_DET_EXTRAS) ||
+           rand_below(afl, afl->extras_cnt) >= MAX_DET_EXTRAS) ||
           afl->extras[j].len > len - i ||
           !memcmp(afl->extras[j].data, out_buf + i, afl->extras[j].len) ||
           !memchr(eff_map + EFF_APOS(i), 1,
@@ -3573,9 +3578,9 @@ pacemaker_fuzzing:
 
     perf_score = orig_perf;
 
-    snprintf(afl->stage_name_buf64, 64, MOpt_globals.splice_stageformat,
-             splice_cycle);
-    afl->stage_name = afl->stage_name_buf64;
+    snprintf(afl->stage_name_buf, STAGE_BUF_SIZE,
+             MOpt_globals.splice_stageformat, splice_cycle);
+    afl->stage_name = afl->stage_name_buf;
     afl->stage_short = MOpt_globals.splice_stagenameshort;
     afl->stage_max = SPLICE_HAVOC * perf_score / afl->havoc_div / 100;
 
@@ -3594,7 +3599,8 @@ pacemaker_fuzzing:
         afl->orig_hit_cnt_puppet = afl->queued_paths + afl->unique_crashes;
         afl->last_limit_time_start = get_cur_time();
         afl->SPLICE_CYCLES_puppet =
-            (UR(afl, SPLICE_CYCLES_puppet_up - SPLICE_CYCLES_puppet_low + 1) +
+            (rand_below(
+                 afl, SPLICE_CYCLES_puppet_up - SPLICE_CYCLES_puppet_low + 1) +
              SPLICE_CYCLES_puppet_low);
 
       }
@@ -3623,9 +3629,9 @@ pacemaker_fuzzing:
       } else {
 
         perf_score = orig_perf;
-        snprintf(afl->stage_name_buf64, 64, MOpt_globals.splice_stageformat,
-                 splice_cycle);
-        afl->stage_name = afl->stage_name_buf64;
+        snprintf(afl->stage_name_buf, STAGE_BUF_SIZE,
+                 MOpt_globals.splice_stageformat, splice_cycle);
+        afl->stage_name = afl->stage_name_buf;
         afl->stage_short = MOpt_globals.splice_stagenameshort;
         afl->stage_max = SPLICE_HAVOC * perf_score / afl->havoc_div / 100;
 
@@ -3642,7 +3648,7 @@ pacemaker_fuzzing:
       for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max;
            ++afl->stage_cur) {
 
-        u32 use_stacking = 1 << (1 + UR(afl, HAVOC_STACK_POW2));
+        u32 use_stacking = 1 << (1 + rand_below(afl, HAVOC_STACK_POW2));
 
         afl->stage_cur_val = use_stacking;
 
@@ -3658,13 +3664,13 @@ pacemaker_fuzzing:
 
             case 0:
               /* Flip a single bit somewhere. Spooky! */
-              FLIP_BIT(out_buf, UR(afl, temp_len << 3));
+              FLIP_BIT(out_buf, rand_below(afl, temp_len << 3));
               MOpt_globals.cycles_v2[STAGE_FLIP1] += 1;
               break;
 
             case 1:
               if (temp_len < 2) break;
-              temp_len_puppet = UR(afl, (temp_len << 3) - 1);
+              temp_len_puppet = rand_below(afl, (temp_len << 3) - 1);
               FLIP_BIT(out_buf, temp_len_puppet);
               FLIP_BIT(out_buf, temp_len_puppet + 1);
               MOpt_globals.cycles_v2[STAGE_FLIP2] += 1;
@@ -3672,7 +3678,7 @@ pacemaker_fuzzing:
 
             case 2:
               if (temp_len < 2) break;
-              temp_len_puppet = UR(afl, (temp_len << 3) - 3);
+              temp_len_puppet = rand_below(afl, (temp_len << 3) - 3);
               FLIP_BIT(out_buf, temp_len_puppet);
               FLIP_BIT(out_buf, temp_len_puppet + 1);
               FLIP_BIT(out_buf, temp_len_puppet + 2);
@@ -3682,55 +3688,57 @@ pacemaker_fuzzing:
 
             case 3:
               if (temp_len < 4) break;
-              out_buf[UR(afl, temp_len)] ^= 0xFF;
+              out_buf[rand_below(afl, temp_len)] ^= 0xFF;
               MOpt_globals.cycles_v2[STAGE_FLIP8] += 1;
               break;
 
             case 4:
               if (temp_len < 8) break;
-              *(u16 *)(out_buf + UR(afl, temp_len - 1)) ^= 0xFFFF;
+              *(u16 *)(out_buf + rand_below(afl, temp_len - 1)) ^= 0xFFFF;
               MOpt_globals.cycles_v2[STAGE_FLIP16] += 1;
               break;
 
             case 5:
               if (temp_len < 8) break;
-              *(u32 *)(out_buf + UR(afl, temp_len - 3)) ^= 0xFFFFFFFF;
+              *(u32 *)(out_buf + rand_below(afl, temp_len - 3)) ^= 0xFFFFFFFF;
               MOpt_globals.cycles_v2[STAGE_FLIP32] += 1;
               break;
 
             case 6:
-              out_buf[UR(afl, temp_len)] -= 1 + UR(afl, ARITH_MAX);
-              out_buf[UR(afl, temp_len)] += 1 + UR(afl, ARITH_MAX);
+              out_buf[rand_below(afl, temp_len)] -=
+                  1 + rand_below(afl, ARITH_MAX);
+              out_buf[rand_below(afl, temp_len)] +=
+                  1 + rand_below(afl, ARITH_MAX);
               MOpt_globals.cycles_v2[STAGE_ARITH8] += 1;
               break;
 
             case 7:
               /* Randomly subtract from word, random endian. */
               if (temp_len < 8) break;
-              if (UR(afl, 2)) {
+              if (rand_below(afl, 2)) {
 
-                u32 pos = UR(afl, temp_len - 1);
-                *(u16 *)(out_buf + pos) -= 1 + UR(afl, ARITH_MAX);
+                u32 pos = rand_below(afl, temp_len - 1);
+                *(u16 *)(out_buf + pos) -= 1 + rand_below(afl, ARITH_MAX);
 
               } else {
 
-                u32 pos = UR(afl, temp_len - 1);
-                u16 num = 1 + UR(afl, ARITH_MAX);
+                u32 pos = rand_below(afl, temp_len - 1);
+                u16 num = 1 + rand_below(afl, ARITH_MAX);
                 *(u16 *)(out_buf + pos) =
                     SWAP16(SWAP16(*(u16 *)(out_buf + pos)) - num);
 
               }
 
               /* Randomly add to word, random endian. */
-              if (UR(afl, 2)) {
+              if (rand_below(afl, 2)) {
 
-                u32 pos = UR(afl, temp_len - 1);
-                *(u16 *)(out_buf + pos) += 1 + UR(afl, ARITH_MAX);
+                u32 pos = rand_below(afl, temp_len - 1);
+                *(u16 *)(out_buf + pos) += 1 + rand_below(afl, ARITH_MAX);
 
               } else {
 
-                u32 pos = UR(afl, temp_len - 1);
-                u16 num = 1 + UR(afl, ARITH_MAX);
+                u32 pos = rand_below(afl, temp_len - 1);
+                u16 num = 1 + rand_below(afl, ARITH_MAX);
                 *(u16 *)(out_buf + pos) =
                     SWAP16(SWAP16(*(u16 *)(out_buf + pos)) + num);
 
@@ -3742,15 +3750,15 @@ pacemaker_fuzzing:
             case 8:
               /* Randomly subtract from dword, random endian. */
               if (temp_len < 8) break;
-              if (UR(afl, 2)) {
+              if (rand_below(afl, 2)) {
 
-                u32 pos = UR(afl, temp_len - 3);
-                *(u32 *)(out_buf + pos) -= 1 + UR(afl, ARITH_MAX);
+                u32 pos = rand_below(afl, temp_len - 3);
+                *(u32 *)(out_buf + pos) -= 1 + rand_below(afl, ARITH_MAX);
 
               } else {
 
-                u32 pos = UR(afl, temp_len - 3);
-                u32 num = 1 + UR(afl, ARITH_MAX);
+                u32 pos = rand_below(afl, temp_len - 3);
+                u32 num = 1 + rand_below(afl, ARITH_MAX);
                 *(u32 *)(out_buf + pos) =
                     SWAP32(SWAP32(*(u32 *)(out_buf + pos)) - num);
 
@@ -3758,15 +3766,15 @@ pacemaker_fuzzing:
 
               /* Randomly add to dword, random endian. */
               // if (temp_len < 4) break;
-              if (UR(afl, 2)) {
+              if (rand_below(afl, 2)) {
 
-                u32 pos = UR(afl, temp_len - 3);
-                *(u32 *)(out_buf + pos) += 1 + UR(afl, ARITH_MAX);
+                u32 pos = rand_below(afl, temp_len - 3);
+                *(u32 *)(out_buf + pos) += 1 + rand_below(afl, ARITH_MAX);
 
               } else {
 
-                u32 pos = UR(afl, temp_len - 3);
-                u32 num = 1 + UR(afl, ARITH_MAX);
+                u32 pos = rand_below(afl, temp_len - 3);
+                u32 num = 1 + rand_below(afl, ARITH_MAX);
                 *(u32 *)(out_buf + pos) =
                     SWAP32(SWAP32(*(u32 *)(out_buf + pos)) + num);
 
@@ -3778,23 +3786,25 @@ pacemaker_fuzzing:
             case 9:
               /* Set byte to interesting value. */
               if (temp_len < 4) break;
-              out_buf[UR(afl, temp_len)] =
-                  interesting_8[UR(afl, sizeof(interesting_8))];
+              out_buf[rand_below(afl, temp_len)] =
+                  interesting_8[rand_below(afl, sizeof(interesting_8))];
               MOpt_globals.cycles_v2[STAGE_INTEREST8] += 1;
               break;
 
             case 10:
               /* Set word to interesting value, randomly choosing endian. */
               if (temp_len < 8) break;
-              if (UR(afl, 2)) {
+              if (rand_below(afl, 2)) {
 
-                *(u16 *)(out_buf + UR(afl, temp_len - 1)) =
-                    interesting_16[UR(afl, sizeof(interesting_16) >> 1)];
+                *(u16 *)(out_buf + rand_below(afl, temp_len - 1)) =
+                    interesting_16[rand_below(afl,
+                                              sizeof(interesting_16) >> 1)];
 
               } else {
 
-                *(u16 *)(out_buf + UR(afl, temp_len - 1)) = SWAP16(
-                    interesting_16[UR(afl, sizeof(interesting_16) >> 1)]);
+                *(u16 *)(out_buf + rand_below(afl, temp_len - 1)) =
+                    SWAP16(interesting_16[rand_below(
+                        afl, sizeof(interesting_16) >> 1)]);
 
               }
 
@@ -3806,15 +3816,17 @@ pacemaker_fuzzing:
 
               if (temp_len < 8) break;
 
-              if (UR(afl, 2)) {
+              if (rand_below(afl, 2)) {
 
-                *(u32 *)(out_buf + UR(afl, temp_len - 3)) =
-                    interesting_32[UR(afl, sizeof(interesting_32) >> 2)];
+                *(u32 *)(out_buf + rand_below(afl, temp_len - 3)) =
+                    interesting_32[rand_below(afl,
+                                              sizeof(interesting_32) >> 2)];
 
               } else {
 
-                *(u32 *)(out_buf + UR(afl, temp_len - 3)) = SWAP32(
-                    interesting_32[UR(afl, sizeof(interesting_32) >> 2)]);
+                *(u32 *)(out_buf + rand_below(afl, temp_len - 3)) =
+                    SWAP32(interesting_32[rand_below(
+                        afl, sizeof(interesting_32) >> 2)]);
 
               }
 
@@ -3827,7 +3839,7 @@ pacemaker_fuzzing:
                  why not. We use XOR with 1-255 to eliminate the
                  possibility of a no-op. */
 
-              out_buf[UR(afl, temp_len)] ^= 1 + UR(afl, 255);
+              out_buf[rand_below(afl, temp_len)] ^= 1 + rand_below(afl, 255);
               MOpt_globals.cycles_v2[STAGE_RANDOMBYTE] += 1;
               break;
 
@@ -3845,7 +3857,7 @@ pacemaker_fuzzing:
 
               del_len = choose_block_len(afl, temp_len - 1);
 
-              del_from = UR(afl, temp_len - del_len + 1);
+              del_from = rand_below(afl, temp_len - del_len + 1);
 
               memmove(out_buf + del_from, out_buf + del_from + del_len,
                       temp_len - del_from - del_len);
@@ -3863,14 +3875,14 @@ pacemaker_fuzzing:
                 /* Clone bytes (75%) or insert a block of constant bytes (25%).
                  */
 
-                u8  actually_clone = UR(afl, 4);
+                u8  actually_clone = rand_below(afl, 4);
                 u32 clone_from, clone_to, clone_len;
                 u8 *new_buf;
 
                 if (actually_clone) {
 
                   clone_len = choose_block_len(afl, temp_len);
-                  clone_from = UR(afl, temp_len - clone_len + 1);
+                  clone_from = rand_below(afl, temp_len - clone_len + 1);
 
                 } else {
 
@@ -3879,7 +3891,7 @@ pacemaker_fuzzing:
 
                 }
 
-                clone_to = UR(afl, temp_len);
+                clone_to = rand_below(afl, temp_len);
 
                 new_buf = ck_alloc_nozero(temp_len + clone_len);
 
@@ -3893,7 +3905,9 @@ pacemaker_fuzzing:
                   memcpy(new_buf + clone_to, out_buf + clone_from, clone_len);
                 else
                   memset(new_buf + clone_to,
-                         UR(afl, 2) ? UR(afl, 256) : out_buf[UR(afl, temp_len)],
+                         rand_below(afl, 2)
+                             ? rand_below(afl, 256)
+                             : out_buf[rand_below(afl, temp_len)],
                          clone_len);
 
                 /* Tail */
@@ -3920,10 +3934,10 @@ pacemaker_fuzzing:
 
               copy_len = choose_block_len(afl, temp_len - 1);
 
-              copy_from = UR(afl, temp_len - copy_len + 1);
-              copy_to = UR(afl, temp_len - copy_len + 1);
+              copy_from = rand_below(afl, temp_len - copy_len + 1);
+              copy_to = rand_below(afl, temp_len - copy_len + 1);
 
-              if (UR(afl, 4)) {
+              if (rand_below(afl, 4)) {
 
                 if (copy_from != copy_to)
                   memmove(out_buf + copy_to, out_buf + copy_from, copy_len);
@@ -3931,7 +3945,8 @@ pacemaker_fuzzing:
               } else
 
                 memset(out_buf + copy_to,
-                       UR(afl, 2) ? UR(afl, 256) : out_buf[UR(afl, temp_len)],
+                       rand_below(afl, 2) ? rand_below(afl, 256)
+                                          : out_buf[rand_below(afl, temp_len)],
                        copy_len);
               MOpt_globals.cycles_v2[STAGE_OverWrite75] += 1;
               break;
@@ -4041,7 +4056,7 @@ pacemaker_fuzzing:
 
         do {
 
-          tid = UR(afl, afl->queued_paths);
+          tid = rand_below(afl, afl->queued_paths);
 
         } while (tid == afl->current_entry);
 
@@ -4096,7 +4111,7 @@ pacemaker_fuzzing:
 
         /* Split somewhere between the first and last differing byte. */
 
-        split_at = f_diff + UR(afl, l_diff - f_diff);
+        split_at = f_diff + rand_below(afl, l_diff - f_diff);
 
         /* Do the thing. */
 
@@ -4120,7 +4135,8 @@ pacemaker_fuzzing:
 
       if (splice_cycle >= afl->SPLICE_CYCLES_puppet)
         afl->SPLICE_CYCLES_puppet =
-            (UR(afl, SPLICE_CYCLES_puppet_up - SPLICE_CYCLES_puppet_low + 1) +
+            (rand_below(
+                 afl, SPLICE_CYCLES_puppet_up - SPLICE_CYCLES_puppet_low + 1) +
              SPLICE_CYCLES_puppet_low);
 
       afl->splicing_with = -1;
diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c
index 595c1ed0..d3027d2b 100644
--- a/src/afl-fuzz-python.c
+++ b/src/afl-fuzz-python.c
@@ -28,9 +28,84 @@
 /* Python stuff */
 #ifdef USE_PYTHON
 
-int init_py_module(afl_state_t *afl, u8 *module_name) {
+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) {
+
+  size_t    mutated_size;
+  PyObject *py_args, *py_value;
+  py_args = PyTuple_New(3);
+
+  /* buf */
+  py_value = PyByteArray_FromStringAndSize(*buf, buf_size);
+  if (!py_value) {
+
+    Py_DECREF(py_args);
+    FATAL("Failed to convert arguments");
+
+  }
+
+  PyTuple_SetItem(py_args, 0, py_value);
+
+  /* add_buf */
+  py_value = PyByteArray_FromStringAndSize(add_buf, add_buf_size);
+  if (!py_value) {
+
+    Py_DECREF(py_args);
+    FATAL("Failed to convert arguments");
+
+  }
+
+  PyTuple_SetItem(py_args, 1, py_value);
+
+  /* max_size */
+#if PY_MAJOR_VERSION >= 3
+  py_value = PyLong_FromLong(max_size);
+#else
+  py_value = PyInt_FromLong(max_size);
+#endif
+  if (!py_value) {
+
+    Py_DECREF(py_args);
+    FATAL("Failed to convert arguments");
+
+  }
+
+  PyTuple_SetItem(py_args, 2, py_value);
+
+  py_value = PyObject_CallObject(((py_mutator_t *)py_mutator)->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);
+    Py_DECREF(py_value);
+    return mutated_size;
+
+  } else {
+
+    PyErr_Print();
+    FATAL("Call failed");
+
+  }
+
+}
 
-  if (!module_name) return 1;
+
+static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
+
+  if (!module_name) return NULL;
+
+  py_mutator_t *py = calloc(1, sizeof(py_mutator_t));
+  if (!py) PFATAL("Could not allocate memory for python mutator!");
 
   Py_Initialize();
 
@@ -40,17 +115,18 @@ int init_py_module(afl_state_t *afl, u8 *module_name) {
   PyObject *py_name = PyString_FromString(module_name);
 #endif
 
-  afl->py_module = PyImport_Import(py_name);
+  py->py_module = PyImport_Import(py_name);
   Py_DECREF(py_name);
 
-  PyObject * py_module = afl->py_module;
-  PyObject **py_functions = afl->py_functions;
+  PyObject * py_module = py->py_module;
+  PyObject **py_functions = py->py_functions;
 
-  if (afl->py_module != NULL) {
+  if (py_module != NULL) {
 
     u8 py_notrim = 0, py_idx;
-    py_functions[PY_FUNC_INIT] = PyObject_GetAttrString(afl->py_module, "init");
-    py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(afl->py_module, "fuzz");
+    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");
     py_functions[PY_FUNC_INIT_TRIM] =
@@ -96,7 +172,7 @@ int init_py_module(afl_state_t *afl, u8 *module_name) {
                   "Cannot find/call function with index %d in external "
                   "Python module.\n",
                   py_idx);
-          return 1;
+          return NULL;
 
         }
 
@@ -119,23 +195,27 @@ int init_py_module(afl_state_t *afl, u8 *module_name) {
 
     PyErr_Print();
     fprintf(stderr, "Failed to load \"%s\"\n", module_name);
-    return 1;
+    return NULL;
 
   }
 
-  return 0;
+  return py;
 
 }
 
-void finalize_py_module(afl_state_t *afl) {
+void finalize_py_module(void *py_mutator) {
+
+  py_mutator_t *py = (py_mutator_t *)py_mutator;
 
-  if (afl->py_module != NULL) {
+  if (py->py_module != NULL) {
+
+    deinit_py(py_mutator);
 
     u32 i;
     for (i = 0; i < PY_FUNC_COUNT; ++i)
-      Py_XDECREF(afl->py_functions[i]);
+      Py_XDECREF(py->py_functions[i]);
 
-    Py_DECREF(afl->py_module);
+    Py_DECREF(py->py_module);
 
   }
 
@@ -143,7 +223,7 @@ void finalize_py_module(afl_state_t *afl) {
 
 }
 
-void init_py(afl_state_t *afl, unsigned int seed) {
+static void init_py(afl_state_t *afl, py_mutator_t *py_mutator, unsigned int seed) {
 
   PyObject *py_args, *py_value;
 
@@ -158,14 +238,13 @@ void init_py(afl_state_t *afl, unsigned int seed) {
   if (!py_value) {
 
     Py_DECREF(py_args);
-    fprintf(stderr, "Cannot convert argument\n");
-    return;
+    FATAL("Cannot convert argument in python init.");
 
   }
 
   PyTuple_SetItem(py_args, 0, py_value);
 
-  py_value = PyObject_CallObject(afl->py_functions[PY_FUNC_INIT], py_args);
+  py_value = PyObject_CallObject(py_mutator->py_functions[PY_FUNC_INIT], py_args);
 
   Py_DECREF(py_args);
 
@@ -173,79 +252,90 @@ void init_py(afl_state_t *afl, unsigned int seed) {
 
     PyErr_Print();
     fprintf(stderr, "Call failed\n");
-    return;
+    FATAL("Custom py mutator INIT failed.");
 
   }
 
 }
 
-size_t fuzz_py(afl_state_t *afl, u8 **buf, size_t buf_size, u8 *add_buf,
-               size_t add_buf_size, size_t max_size) {
+void deinit_py(void *py_mutator) {
 
-  size_t    mutated_size;
   PyObject *py_args, *py_value;
-  py_args = PyTuple_New(3);
 
-  /* buf */
-  py_value = PyByteArray_FromStringAndSize(*buf, buf_size);
-  if (!py_value) {
+  py_args = PyTuple_New(0);
+  py_value = PyObject_CallObject(
+      ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_DEINIT], py_args);
+  Py_DECREF(py_args);
 
-    Py_DECREF(py_args);
-    FATAL("Failed to convert arguments");
+  if (py_value != NULL) {
+
+    Py_DECREF(py_value);
+
+  } else {
+
+    PyErr_Print();
+    FATAL("Call failed");
 
   }
 
-  PyTuple_SetItem(py_args, 0, py_value);
+}
 
-  /* add_buf */
-  py_value = PyByteArray_FromStringAndSize(add_buf, add_buf_size);
-  if (!py_value) {
+void load_custom_mutator_py(afl_state_t *afl, char *module_name) {
 
-    Py_DECREF(py_args);
-    FATAL("Failed to convert arguments");
+  afl->mutator = ck_alloc(sizeof(struct custom_mutator));
 
+  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.");
   }
 
-  PyTuple_SetItem(py_args, 1, py_value);
+  PyObject **py_functions = py_mutator->py_functions;
 
-  /* max_size */
-#if PY_MAJOR_VERSION >= 3
-  py_value = PyLong_FromLong(max_size);
-#else
-  py_value = PyInt_FromLong(max_size);
-#endif
-  if (!py_value) {
+  if (py_functions[PY_FUNC_INIT]) afl->mutator->afl_custom_init = unsupported;
 
-    Py_DECREF(py_args);
-    FATAL("Failed to convert arguments");
+  if (py_functions[PY_FUNC_DEINIT]) afl->mutator->afl_custom_deinit = deinit_py;
 
-  }
+  /* "afl_custom_fuzz" should not be NULL, but the interface of Python mutator
+     is quite different from the custom mutator. */
+  afl->mutator->afl_custom_fuzz = fuzz_py;
 
-  PyTuple_SetItem(py_args, 2, py_value);
+  if (py_functions[PY_FUNC_PRE_SAVE])
+    afl->mutator->afl_custom_pre_save = pre_save_py;
 
-  py_value = PyObject_CallObject(afl->py_functions[PY_FUNC_FUZZ], py_args);
+  if (py_functions[PY_FUNC_INIT_TRIM])
+    afl->mutator->afl_custom_init_trim = init_trim_py;
 
-  Py_DECREF(py_args);
+  if (py_functions[PY_FUNC_POST_TRIM])
+    afl->mutator->afl_custom_post_trim = post_trim_py;
 
-  if (py_value != NULL) {
+  if (py_functions[PY_FUNC_TRIM]) afl->mutator->afl_custom_trim = trim_py;
 
-    mutated_size = PyByteArray_Size(py_value);
-    if (buf_size < mutated_size) *buf = ck_realloc(*buf, mutated_size);
+  if (py_functions[PY_FUNC_HAVOC_MUTATION])
+    afl->mutator->afl_custom_havoc_mutation = havoc_mutation_py;
 
-    memcpy(*buf, PyByteArray_AsString(py_value), mutated_size);
-    Py_DECREF(py_value);
-    return mutated_size;
+  if (py_functions[PY_FUNC_HAVOC_MUTATION_PROBABILITY])
+    afl->mutator->afl_custom_havoc_mutation_probability =
+        havoc_mutation_probability_py;
 
-  } else {
+  if (py_functions[PY_FUNC_QUEUE_GET])
+    afl->mutator->afl_custom_queue_get = queue_get_py;
 
-    PyErr_Print();
-    FATAL("Call failed");
+  if (py_functions[PY_FUNC_QUEUE_NEW_ENTRY])
+    afl->mutator->afl_custom_queue_new_entry = queue_new_entry_py;
 
-  }
+  OKF("Python mutator '%s' installed successfully.", module_name);
+
+  /* Initialize the custom mutator */
+  init_py(afl, py_mutator, rand_below(afl, 0xFFFFFFFF));
 
 }
 
-size_t pre_save_py(afl_state_t *afl, u8 *buf, size_t buf_size, u8 **out_buf) {
+
+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;
@@ -260,7 +350,7 @@ size_t pre_save_py(afl_state_t *afl, u8 *buf, size_t buf_size, u8 **out_buf) {
 
   PyTuple_SetItem(py_args, 0, py_value);
 
-  py_value = PyObject_CallObject(afl->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);
 
@@ -281,7 +371,7 @@ size_t pre_save_py(afl_state_t *afl, u8 *buf, size_t buf_size, u8 **out_buf) {
 
 }
 
-u32 init_trim_py(afl_state_t *afl, u8 *buf, size_t buf_size) {
+u32 init_trim_py(void *py_mutator, u8 *buf, size_t buf_size) {
 
   PyObject *py_args, *py_value;
 
@@ -296,7 +386,7 @@ u32 init_trim_py(afl_state_t *afl, u8 *buf, size_t buf_size) {
 
   PyTuple_SetItem(py_args, 0, py_value);
 
-  py_value = PyObject_CallObject(afl->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) {
@@ -318,7 +408,7 @@ u32 init_trim_py(afl_state_t *afl, u8 *buf, size_t buf_size) {
 
 }
 
-u32 post_trim_py(afl_state_t *afl, u8 success) {
+u32 post_trim_py(void *py_mutator, u8 success) {
 
   PyObject *py_args, *py_value;
 
@@ -334,7 +424,7 @@ u32 post_trim_py(afl_state_t *afl, u8 success) {
 
   PyTuple_SetItem(py_args, 0, py_value);
 
-  py_value = PyObject_CallObject(afl->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) {
@@ -356,12 +446,12 @@ u32 post_trim_py(afl_state_t *afl, u8 success) {
 
 }
 
-void trim_py(afl_state_t *afl, u8 **out_buf, size_t *out_buf_size) {
+void trim_py(void *py_mutator, u8 **out_buf, size_t *out_buf_size) {
 
   PyObject *py_args, *py_value;
 
   py_args = PyTuple_New(0);
-  py_value = PyObject_CallObject(afl->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) {
@@ -380,7 +470,7 @@ void trim_py(afl_state_t *afl, u8 **out_buf, size_t *out_buf_size) {
 
 }
 
-size_t havoc_mutation_py(afl_state_t *afl, u8 **buf, size_t buf_size,
+size_t havoc_mutation_py(void *py_mutator, u8 **buf, size_t buf_size,
                          size_t max_size) {
 
   size_t    mutated_size;
@@ -414,7 +504,7 @@ size_t havoc_mutation_py(afl_state_t *afl, u8 **buf, size_t buf_size,
   PyTuple_SetItem(py_args, 1, py_value);
 
   py_value =
-      PyObject_CallObject(afl->py_functions[PY_FUNC_HAVOC_MUTATION], py_args);
+      PyObject_CallObject(((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_HAVOC_MUTATION], py_args);
 
   Py_DECREF(py_args);
 
@@ -437,13 +527,13 @@ size_t havoc_mutation_py(afl_state_t *afl, u8 **buf, size_t buf_size,
 
 }
 
-u8 havoc_mutation_probability_py(afl_state_t *afl) {
+u8 havoc_mutation_probability_py(void *py_mutator) {
 
   PyObject *py_args, *py_value;
 
   py_args = PyTuple_New(0);
   py_value = PyObject_CallObject(
-      afl->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) {
@@ -461,7 +551,7 @@ u8 havoc_mutation_probability_py(afl_state_t *afl) {
 
 }
 
-u8 queue_get_py(afl_state_t *afl, const u8 *filename) {
+u8 queue_get_py(void *py_mutator, const u8 *filename) {
 
   PyObject *py_args, *py_value;
 
@@ -483,7 +573,7 @@ u8 queue_get_py(afl_state_t *afl, const u8 *filename) {
   PyTuple_SetItem(py_args, 0, py_value);
 
   // Call Python function
-  py_value = PyObject_CallObject(afl->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) {
@@ -509,7 +599,7 @@ u8 queue_get_py(afl_state_t *afl, const u8 *filename) {
 
 }
 
-void queue_new_entry_py(afl_state_t *afl, const u8 *filename_new_queue,
+void queue_new_entry_py(void *py_mutator, const u8 *filename_new_queue,
                         const u8 *filename_orig_queue) {
 
   PyObject *py_args, *py_value;
@@ -553,7 +643,7 @@ void queue_new_entry_py(afl_state_t *afl, const u8 *filename_new_queue,
 
   // Call
   py_value =
-      PyObject_CallObject(afl->py_functions[PY_FUNC_QUEUE_NEW_ENTRY], py_args);
+      PyObject_CallObject(((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_QUEUE_NEW_ENTRY], py_args);
   Py_DECREF(py_args);
 
   if (py_value == NULL) {
diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c
index cfeab798..f49e1f1e 100644
--- a/src/afl-fuzz-queue.c
+++ b/src/afl-fuzz-queue.c
@@ -185,12 +185,16 @@ void destroy_queue(afl_state_t *afl) {
 void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
 
   u32 i;
-  u64 fav_factor = q->exec_us * q->len;
+  u64 fav_factor;
   u64 fuzz_p2 = next_p2(q->n_fuzz);
 
+  if (afl->schedule == MMOPT || afl->schedule == RARE)
+    fav_factor = q->len << 2;
+  else
+    fav_factor = q->exec_us * q->len;
+
   /* For every byte set in afl->fsrv.trace_bits[], see if there is a previous
      winner, and how it compares to us. */
-
   for (i = 0; i < MAP_SIZE; ++i)
 
     if (afl->fsrv.trace_bits[i]) {
@@ -198,20 +202,20 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
       if (afl->top_rated[i]) {
 
         /* 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_fav_factor =
-            afl->top_rated[i]->exec_us * afl->top_rated[i]->len;
 
-        if (fuzz_p2 > top_rated_fuzz_p2) {
+        if (afl->schedule == MMOPT || afl->schedule == RARE)
+          top_rated_fav_factor = afl->top_rated[i]->len << 2;
+        else
+          top_rated_fav_factor =
+              afl->top_rated[i]->exec_us * afl->top_rated[i]->len;
 
+        if (fuzz_p2 > top_rated_fuzz_p2)
           continue;
-
-        } else if (fuzz_p2 == top_rated_fuzz_p2) {
-
+        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;
 
@@ -254,7 +258,7 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
 void cull_queue(afl_state_t *afl) {
 
   struct queue_entry *q;
-  static u8           temp_v[MAP_SIZE >> 3];
+  u8                  temp_v[MAP_SIZE >> 3];
   u32                 i;
 
   if (afl->dumb_mode || !afl->score_changed) return;
@@ -328,7 +332,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) {
+  if (afl->schedule != MMOPT && afl->schedule != RARE) {
 
     if (q->exec_us * 0.1 > avg_exec_us)
       perf_score = 10;
@@ -448,8 +452,29 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) {
       break;
 
     case MMOPT:
+      /* -- this was a more complex setup, which is good, but competed with
+         -- rare. the simpler algo however is good when rare is not.
+        // the newer the entry, the higher the pref_score
+        perf_score *= (1 + (double)((double)q->depth /
+        (double)afl->queued_paths));
+        // with special focus on the last 8 entries
+        if (afl->max_depth - q->depth < 8) perf_score *= (1 + ((8 -
+        (afl->max_depth - q->depth)) / 5));
+      */
+      // put focus on the last 5 entries
+      if (afl->max_depth - q->depth < 5) perf_score *= 2;
+
+      break;
+
+    case RARE:
 
-      if (afl->max_depth - q->depth < 5) perf_score *= 1.5;
+      // increase the score for every bitmap byte for which this entry
+      // is the top contender
+      perf_score += (q->tc_ref * 10);
+      // the more often fuzz result paths are equal to this queue entry,
+      // reduce its value
+      perf_score *=
+          (1 - (double)((double)q->n_fuzz / (double)afl->total_execs));
 
       break;
 
diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c
index c910e75e..b069fa77 100644
--- a/src/afl-fuzz-redqueen.c
+++ b/src/afl-fuzz-redqueen.c
@@ -97,7 +97,7 @@ static void rand_replace(afl_state_t *afl, u8 *buf, u32 len) {
 
   u32 i;
   for (i = 0; i < len; ++i)
-    buf[i] = UR(afl, 256);
+    buf[i] = rand_below(afl, 256);
 
 }
 
diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c
index cdec75e8..8c4b5941 100644
--- a/src/afl-fuzz-run.c
+++ b/src/afl-fuzz-run.c
@@ -28,14 +28,7 @@
 #include <signal.h>
 
 /* Execute target application, monitoring for timeouts. Return status
-   information. The called program will update afl->fsrv.trace_bits[]. */
-
-void timeout_handle(union sigval timer_data) {
-
-  pid_t child_pid = timer_data.sival_int;
-  if (child_pid > 0) kill(child_pid, SIGKILL);
-
-}
+   information. The called program will update afl->fsrv.trace_bits. */
 
 u8 run_target(afl_state_t *afl, u32 timeout) {
 
@@ -44,11 +37,9 @@ u8 run_target(afl_state_t *afl, u32 timeout) {
 
   fd_set readfds;
 
-  static struct timeval it;
-  static u32            prev_timed_out = 0;
-
-  int status = 0;
-  u32 tb4;
+  struct timeval it;
+  int            status = 0;
+  u32            tb4;
 
   afl->fsrv.child_timed_out = 0;
 
@@ -63,7 +54,7 @@ u8 run_target(afl_state_t *afl, u32 timeout) {
   /* we have the fork server (or faux server) up and running, so simply
       tell it to have at it, and then read back PID. */
 
-  if ((res = write(afl->fsrv.fsrv_ctl_fd, &prev_timed_out, 4)) != 4) {
+  if ((res = write(afl->fsrv.fsrv_ctl_fd, &afl->fsrv.prev_timed_out, 4)) != 4) {
 
     if (afl->stop_soon) return 0;
     RPFATAL(res, "Unable to request new process from fork server (OOM?)");
@@ -144,7 +135,7 @@ u8 run_target(afl_state_t *afl, u32 timeout) {
   classify_counts((u32 *)afl->fsrv.trace_bits);
 #endif                                                     /* ^WORD_SIZE_64 */
 
-  prev_timed_out = afl->fsrv.child_timed_out;
+  afl->fsrv.prev_timed_out = afl->fsrv.child_timed_out;
 
   /* Report outcome to caller. */
 
@@ -299,8 +290,6 @@ static void write_with_gap(afl_state_t *afl, void *mem, u32 len, u32 skip_at,
 u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
                   u32 handicap, u8 from_queue) {
 
-  static u8 first_trace[MAP_SIZE];
-
   u8 fault = 0, new_bits = 0, var_detected = 0,
      first_run = (q->exec_cksum == 0);
 
@@ -331,7 +320,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
       afl->shm.cmplog_mode)
     init_cmplog_forkserver(afl);
 
-  if (q->exec_cksum) memcpy(first_trace, afl->fsrv.trace_bits, MAP_SIZE);
+  if (q->exec_cksum) memcpy(afl->first_trace, afl->fsrv.trace_bits, MAP_SIZE);
 
   start_us = get_cur_time_us();
 
@@ -372,7 +361,8 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
 
         for (i = 0; i < MAP_SIZE; ++i) {
 
-          if (!afl->var_bytes[i] && first_trace[i] != afl->fsrv.trace_bits[i]) {
+          if (!afl->var_bytes[i] &&
+              afl->first_trace[i] != afl->fsrv.trace_bits[i]) {
 
             afl->var_bytes[i] = 1;
             afl->stage_max = CAL_CYCLES_LONG;
@@ -386,7 +376,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
       } else {
 
         q->exec_cksum = cksum;
-        memcpy(first_trace, afl->fsrv.trace_bits, MAP_SIZE);
+        memcpy(afl->first_trace, afl->fsrv.trace_bits, MAP_SIZE);
 
       }
 
@@ -471,8 +461,6 @@ void sync_fuzzers(afl_state_t *afl) {
 
   while ((sd_ent = readdir(sd))) {
 
-    static u8 stage_tmp[128];
-
     DIR *          qd;
     struct dirent *qd_ent;
     u8 *           qd_path, *qd_synced_path;
@@ -511,8 +499,9 @@ void sync_fuzzers(afl_state_t *afl) {
 
     /* Show stats */
 
-    sprintf(stage_tmp, "sync %u", ++sync_cnt);
-    afl->stage_name = stage_tmp;
+    snprintf(afl->stage_name_buf, STAGE_BUF_SIZE, "sync %u", ++sync_cnt);
+
+    afl->stage_name = afl->stage_name_buf;
     afl->stage_cur = 0;
     afl->stage_max = 0;
 
@@ -608,21 +597,20 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
   if (afl->mutator && afl->mutator->afl_custom_trim)
     return trim_case_custom(afl, q, in_buf);
 
-  static u8 tmp[64];
-  static u8 clean_trace[MAP_SIZE];
-
   u8  needs_write = 0, fault = 0;
   u32 trim_exec = 0;
   u32 remove_len;
   u32 len_p2;
 
+  u8 val_bufs[2][STRINGIFY_VAL_SIZE_MAX];
+
   /* Although the trimmer will be less useful when variable behavior is
      detected, it will still work to some extent, so we don't check for
      this. */
 
   if (q->len < 5) return 0;
 
-  afl->stage_name = tmp;
+  afl->stage_name = afl->stage_name_buf;
   afl->bytes_trim_in += q->len;
 
   /* Select initial chunk len, starting with large steps. */
@@ -638,7 +626,9 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
 
     u32 remove_pos = remove_len;
 
-    sprintf(tmp, "trim %s/%s", DI(remove_len), DI(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));
 
     afl->stage_cur = 0;
     afl->stage_max = q->len / remove_len;
@@ -680,7 +670,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
         if (!needs_write) {
 
           needs_write = 1;
-          memcpy(clean_trace, afl->fsrv.trace_bits, MAP_SIZE);
+          memcpy(afl->clean_trace, afl->fsrv.trace_bits, MAP_SIZE);
 
         }
 
@@ -722,7 +712,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
     ck_write(fd, in_buf, q->len, q->fname);
     close(fd);
 
-    memcpy(afl->fsrv.trace_bits, clean_trace, MAP_SIZE);
+    memcpy(afl->fsrv.trace_bits, afl->clean_trace, MAP_SIZE);
     update_bitmap_score(afl, q);
 
   }
diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c
index 63cca14d..dc16df8f 100644
--- a/src/afl-fuzz-stats.c
+++ b/src/afl-fuzz-stats.c
@@ -30,12 +30,12 @@
 void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
                       double eps) {
 
-  static double        last_bcvg, last_stab, last_eps;
-  static struct rusage rus;
+  struct rusage rus;
 
-  u8 *  fn = alloc_printf("%s/fuzzer_stats", afl->out_dir);
-  s32   fd;
-  FILE *f;
+  unsigned long long int cur_time = get_cur_time();
+  u8 *                   fn = alloc_printf("%s/fuzzer_stats", afl->out_dir);
+  s32                    fd;
+  FILE *                 f;
 
   fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600);
 
@@ -52,15 +52,15 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
 
   if (!bitmap_cvg && !stability && !eps) {
 
-    bitmap_cvg = last_bcvg;
-    stability = last_stab;
-    eps = last_eps;
+    bitmap_cvg = afl->last_bitmap_cvg;
+    stability = afl->last_stability;
+    eps = afl->last_eps;
 
   } else {
 
-    last_bcvg = bitmap_cvg;
-    last_stab = stability;
-    last_eps = eps;
+    afl->last_bitmap_cvg = bitmap_cvg;
+    afl->last_stability = stability;
+    afl->last_eps = eps;
 
   }
 
@@ -70,8 +70,10 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
       f,
       "start_time        : %llu\n"
       "last_update       : %llu\n"
+      "run_time          : %llu\n"
       "fuzzer_pid        : %d\n"
       "cycles_done       : %llu\n"
+      "cycles_wo_finds   : %llu\n"
       "execs_done        : %llu\n"
       "execs_per_sec     : %0.02f\n"
       //          "real_execs_per_sec: %0.02f\n"  // damn the name is too long
@@ -100,10 +102,11 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
       "\n"
       "target_mode       : %s%s%s%s%s%s%s%s\n"
       "command_line      : %s\n",
-      afl->start_time / 1000, get_cur_time() / 1000, getpid(),
-      afl->queue_cycle ? (afl->queue_cycle - 1) : 0, afl->total_execs,
-      /*eps,*/ afl->total_execs /
-          ((double)(get_cur_time() - afl->start_time) / 1000),
+      afl->start_time / 1000, cur_time / 1000,
+      (cur_time - afl->start_time) / 1000, getpid(),
+      afl->queue_cycle ? (afl->queue_cycle - 1) : 0, afl->cycles_wo_finds,
+      afl->total_execs,
+      afl->total_execs / ((double)(get_cur_time() - afl->start_time) / 1000),
       afl->queued_paths, afl->queued_favored, afl->queued_discovered,
       afl->queued_imported, afl->max_depth, afl->current_entry,
       afl->pending_favored, afl->pending_not_fuzzed, afl->queued_variable,
@@ -137,23 +140,24 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
 
 void maybe_update_plot_file(afl_state_t *afl, double bitmap_cvg, double eps) {
 
-  static u32 prev_qp, prev_pf, prev_pnf, prev_ce, prev_md;
-  static u64 prev_qc, prev_uc, prev_uh;
-
-  if (prev_qp == afl->queued_paths && prev_pf == afl->pending_favored &&
-      prev_pnf == afl->pending_not_fuzzed && prev_ce == afl->current_entry &&
-      prev_qc == afl->queue_cycle && prev_uc == afl->unique_crashes &&
-      prev_uh == afl->unique_hangs && prev_md == afl->max_depth)
+  if (afl->plot_prev_qp == afl->queued_paths &&
+      afl->plot_prev_pf == afl->pending_favored &&
+      afl->plot_prev_pnf == afl->pending_not_fuzzed &&
+      afl->plot_prev_ce == afl->current_entry &&
+      afl->plot_prev_qc == afl->queue_cycle &&
+      afl->plot_prev_uc == afl->unique_crashes &&
+      afl->plot_prev_uh == afl->unique_hangs &&
+      afl->plot_prev_md == afl->max_depth)
     return;
 
-  prev_qp = afl->queued_paths;
-  prev_pf = afl->pending_favored;
-  prev_pnf = afl->pending_not_fuzzed;
-  prev_ce = afl->current_entry;
-  prev_qc = afl->queue_cycle;
-  prev_uc = afl->unique_crashes;
-  prev_uh = afl->unique_hangs;
-  prev_md = afl->max_depth;
+  afl->plot_prev_qp = afl->queued_paths;
+  afl->plot_prev_pf = afl->pending_favored;
+  afl->plot_prev_pnf = afl->pending_not_fuzzed;
+  afl->plot_prev_ce = afl->current_entry;
+  afl->plot_prev_qc = afl->queue_cycle;
+  afl->plot_prev_uc = afl->unique_crashes;
+  afl->plot_prev_uh = afl->unique_hangs;
+  afl->plot_prev_md = afl->max_depth;
 
   /* Fields in the file:
 
@@ -192,21 +196,25 @@ static void check_term_size(afl_state_t *afl) {
 
 void show_stats(afl_state_t *afl) {
 
-  static u64    last_stats_ms, last_plot_ms, last_ms, last_execs;
-  static double avg_exec;
-  double        t_byte_ratio, stab_ratio;
+  double t_byte_ratio, stab_ratio;
 
   u64 cur_ms;
   u32 t_bytes, t_bits;
 
   u32 banner_len, banner_pad;
   u8  tmp[256];
+  u8  time_tmp[64];
+
+  u8 val_buf[8][STRINGIFY_VAL_SIZE_MAX];
+#define IB(i) (val_buf[(i)])
 
   cur_ms = get_cur_time();
 
   /* If not enough time has passed since last UI update, bail out. */
 
-  if (cur_ms - last_ms < 1000 / UI_TARGET_HZ && !afl->force_ui_update) return;
+  if (cur_ms - afl->stats_last_ms < 1000 / UI_TARGET_HZ &&
+      !afl->force_ui_update)
+    return;
 
   /* Check if we're past the 10 minute mark. */
 
@@ -214,31 +222,33 @@ void show_stats(afl_state_t *afl) {
 
   /* Calculate smoothed exec speed stats. */
 
-  if (!last_execs) {
+  if (!afl->stats_last_execs) {
 
-    avg_exec = ((double)afl->total_execs) * 1000 / (cur_ms - afl->start_time);
+    afl->stats_avg_exec =
+        ((double)afl->total_execs) * 1000 / (cur_ms - afl->start_time);
 
   } else {
 
-    double cur_avg =
-        ((double)(afl->total_execs - last_execs)) * 1000 / (cur_ms - last_ms);
+    double cur_avg = ((double)(afl->total_execs - afl->stats_last_execs)) *
+                     1000 / (cur_ms - afl->stats_last_ms);
 
     /* If there is a dramatic (5x+) jump in speed, reset the indicator
        more quickly. */
 
-    if (cur_avg * 5 < avg_exec || cur_avg / 5 > avg_exec) avg_exec = cur_avg;
+    if (cur_avg * 5 < afl->stats_avg_exec || cur_avg / 5 > afl->stats_avg_exec)
+      afl->stats_avg_exec = cur_avg;
 
-    avg_exec = avg_exec * (1.0 - 1.0 / AVG_SMOOTHING) +
-               cur_avg * (1.0 / AVG_SMOOTHING);
+    afl->stats_avg_exec = afl->stats_avg_exec * (1.0 - 1.0 / AVG_SMOOTHING) +
+                          cur_avg * (1.0 / AVG_SMOOTHING);
 
   }
 
-  last_ms = cur_ms;
-  last_execs = afl->total_execs;
+  afl->stats_last_ms = cur_ms;
+  afl->stats_last_execs = afl->total_execs;
 
   /* Tell the callers when to contact us (as measured in execs). */
 
-  afl->stats_update_freq = avg_exec / (UI_TARGET_HZ * 10);
+  afl->stats_update_freq = afl->stats_avg_exec / (UI_TARGET_HZ * 10);
   if (!afl->stats_update_freq) afl->stats_update_freq = 1;
 
   /* Do some bitmap stats. */
@@ -253,10 +263,10 @@ void show_stats(afl_state_t *afl) {
 
   /* Roughly every minute, update fuzzer stats and save auto tokens. */
 
-  if (cur_ms - last_stats_ms > STATS_UPDATE_SEC * 1000) {
+  if (cur_ms - afl->stats_last_stats_ms > STATS_UPDATE_SEC * 1000) {
 
-    last_stats_ms = cur_ms;
-    write_stats_file(afl, t_byte_ratio, stab_ratio, avg_exec);
+    afl->stats_last_stats_ms = cur_ms;
+    write_stats_file(afl, t_byte_ratio, stab_ratio, afl->stats_avg_exec);
     save_auto(afl);
     write_bitmap(afl);
 
@@ -264,10 +274,10 @@ void show_stats(afl_state_t *afl) {
 
   /* Every now and then, write plot data. */
 
-  if (cur_ms - last_plot_ms > PLOT_UPDATE_SEC * 1000) {
+  if (cur_ms - afl->stats_last_plot_ms > PLOT_UPDATE_SEC * 1000) {
 
-    last_plot_ms = cur_ms;
-    maybe_update_plot_file(afl, t_byte_ratio, avg_exec);
+    afl->stats_last_plot_ms = cur_ms;
+    maybe_update_plot_file(afl, t_byte_ratio, afl->stats_avg_exec);
 
   }
 
@@ -384,9 +394,10 @@ void show_stats(afl_state_t *afl) {
 
   }
 
+  u_stringify_time_diff(time_tmp, cur_ms, afl->start_time);
   SAYF(bV bSTOP "        run time : " cRST "%-33s " bSTG bV bSTOP
                 "  cycles done : %s%-5s " bSTG              bV "\n",
-       DTD(cur_ms, afl->start_time), tmp, DI(afl->queue_cycle - 1));
+       time_tmp, tmp, u_stringify_int(IB(0), afl->queue_cycle - 1));
 
   /* We want to warn people about not seeing new paths after a full cycle,
      except when resuming fuzzing or running in non-instrumented mode. */
@@ -395,8 +406,9 @@ void show_stats(afl_state_t *afl) {
       (afl->last_path_time || afl->resuming_fuzz || afl->queue_cycle == 1 ||
        afl->in_bitmap || afl->crash_mode)) {
 
-    SAYF(bV bSTOP "   last new path : " cRST "%-33s ",
-         DTD(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 {
 
@@ -413,25 +425,26 @@ void show_stats(afl_state_t *afl) {
   }
 
   SAYF(bSTG bV bSTOP "  total paths : " cRST "%-5s " bSTG bV "\n",
-       DI(afl->queued_paths));
+       u_stringify_int(IB(0), afl->queued_paths));
 
   /* Highlight crashes in red if found, denote going over the KEEP_UNIQUE_CRASH
      limit with a '+' appended to the count. */
 
-  sprintf(tmp, "%s%s", DI(afl->unique_crashes),
+  sprintf(tmp, "%s%s", u_stringify_int(IB(0), afl->unique_crashes),
           (afl->unique_crashes >= KEEP_UNIQUE_CRASH) ? "+" : "");
 
+  u_stringify_time_diff(time_tmp, cur_ms, afl->last_crash_time);
   SAYF(bV bSTOP " last uniq crash : " cRST "%-33s " bSTG bV bSTOP
                 " uniq crashes : %s%-6s" bSTG               bV "\n",
-       DTD(cur_ms, afl->last_crash_time), afl->unique_crashes ? cLRD : cRST,
-       tmp);
+       time_tmp, afl->unique_crashes ? cLRD : cRST, tmp);
 
-  sprintf(tmp, "%s%s", DI(afl->unique_hangs),
+  sprintf(tmp, "%s%s", u_stringify_int(IB(0), afl->unique_hangs),
           (afl->unique_hangs >= KEEP_UNIQUE_HANG) ? "+" : "");
 
+  u_stringify_time_diff(time_tmp, cur_ms, afl->last_hang_time);
   SAYF(bV bSTOP "  last uniq hang : " cRST "%-33s " bSTG bV bSTOP
                 "   uniq hangs : " cRST "%-6s" bSTG         bV "\n",
-       DTD(cur_ms, afl->last_hang_time), tmp);
+       time_tmp, tmp);
 
   SAYF(bVR bH bSTOP            cCYA
        " cycle progress " bSTG bH10 bH5 bH2 bH2 bHB bH bSTOP cCYA
@@ -441,7 +454,7 @@ void show_stats(afl_state_t *afl) {
      together, but then cram them into a fixed-width field - so we need to
      put them in a temporary buffer first. */
 
-  sprintf(tmp, "%s%s%u (%0.01f%%)", DI(afl->current_entry),
+  sprintf(tmp, "%s%s%u (%0.01f%%)", u_stringify_int(IB(0), afl->current_entry),
           afl->queue_cur->favored ? "." : "*", afl->queue_cur->fuzz_level,
           ((double)afl->current_entry * 100) / afl->queued_paths);
 
@@ -455,7 +468,7 @@ void show_stats(afl_state_t *afl) {
                          : ((t_bytes < 200 && !afl->dumb_mode) ? cPIN : cRST),
        tmp);
 
-  sprintf(tmp, "%s (%0.02f%%)", DI(afl->cur_skipped_paths),
+  sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->cur_skipped_paths),
           ((double)afl->cur_skipped_paths * 100) / afl->queued_paths);
 
   SAYF(bV bSTOP " paths timed out : " cRST "%-16s " bSTG bV, tmp);
@@ -468,7 +481,7 @@ void show_stats(afl_state_t *afl) {
        " stage progress " bSTG bH10 bH5 bH2 bH2 bX bH bSTOP cCYA
        " findings in depth " bSTG bH10 bH5 bH2 bH2 bVL "\n");
 
-  sprintf(tmp, "%s (%0.02f%%)", DI(afl->queued_favored),
+  sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->queued_favored),
           ((double)afl->queued_favored) * 100 / afl->queued_paths);
 
   /* Yeah... it's still going on... halp? */
@@ -479,59 +492,65 @@ void show_stats(afl_state_t *afl) {
 
   if (!afl->stage_max) {
 
-    sprintf(tmp, "%s/-", DI(afl->stage_cur));
+    sprintf(tmp, "%s/-", u_stringify_int(IB(0), afl->stage_cur));
 
   } else {
 
-    sprintf(tmp, "%s/%s (%0.02f%%)", DI(afl->stage_cur), DI(afl->stage_max),
+    sprintf(tmp, "%s/%s (%0.02f%%)", u_stringify_int(IB(0), afl->stage_cur),
+            u_stringify_int(IB(1), afl->stage_max),
             ((double)afl->stage_cur) * 100 / afl->stage_max);
 
   }
 
   SAYF(bV bSTOP " stage execs : " cRST "%-21s" bSTG bV bSTOP, tmp);
 
-  sprintf(tmp, "%s (%0.02f%%)", DI(afl->queued_with_cov),
+  sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->queued_with_cov),
           ((double)afl->queued_with_cov) * 100 / afl->queued_paths);
 
   SAYF("  new edges on : " cRST "%-22s" bSTG bV "\n", tmp);
 
-  sprintf(tmp, "%s (%s%s unique)", DI(afl->total_crashes),
-          DI(afl->unique_crashes),
+  sprintf(tmp, "%s (%s%s unique)", u_stringify_int(IB(0), afl->total_crashes),
+          u_stringify_int(IB(1), afl->unique_crashes),
           (afl->unique_crashes >= KEEP_UNIQUE_CRASH) ? "+" : "");
 
   if (afl->crash_mode) {
 
     SAYF(bV bSTOP " total execs : " cRST "%-20s " bSTG bV bSTOP
                   "   new crashes : %s%-22s" bSTG         bV "\n",
-         DI(afl->total_execs), afl->unique_crashes ? cLRD : cRST, tmp);
+         u_stringify_int(IB(0), afl->total_execs),
+         afl->unique_crashes ? cLRD : cRST, tmp);
 
   } else {
 
     SAYF(bV bSTOP " total execs : " cRST "%-20s " bSTG bV bSTOP
                   " total crashes : %s%-22s" bSTG         bV "\n",
-         DI(afl->total_execs), afl->unique_crashes ? cLRD : cRST, tmp);
+         u_stringify_int(IB(0), afl->total_execs),
+         afl->unique_crashes ? cLRD : cRST, tmp);
 
   }
 
   /* Show a warning about slow execution. */
 
-  if (avg_exec < 100) {
+  if (afl->stats_avg_exec < 100) {
 
-    sprintf(tmp, "%s/sec (%s)", DF(avg_exec),
-            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", DF(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)", DI(afl->total_tmouts),
-          DI(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);
 
@@ -547,70 +566,80 @@ void show_stats(afl_state_t *afl) {
 
   } else {
 
-    sprintf(
-        tmp, "%s/%s, %s/%s, %s/%s", DI(afl->stage_finds[STAGE_FLIP1]),
-        DI(afl->stage_cycles[STAGE_FLIP1]), DI(afl->stage_finds[STAGE_FLIP2]),
-        DI(afl->stage_cycles[STAGE_FLIP2]), DI(afl->stage_finds[STAGE_FLIP4]),
-        DI(afl->stage_cycles[STAGE_FLIP4]));
+    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]));
 
   }
 
   SAYF(bV bSTOP "   bit flips : " cRST "%-36s " bSTG bV bSTOP
                 "    levels : " cRST "%-10s" bSTG       bV "\n",
-       tmp, DI(afl->max_depth));
+       tmp, u_stringify_int(IB(0), afl->max_depth));
 
   if (!afl->skip_deterministic)
-    sprintf(
-        tmp, "%s/%s, %s/%s, %s/%s", DI(afl->stage_finds[STAGE_FLIP8]),
-        DI(afl->stage_cycles[STAGE_FLIP8]), DI(afl->stage_finds[STAGE_FLIP16]),
-        DI(afl->stage_cycles[STAGE_FLIP16]), DI(afl->stage_finds[STAGE_FLIP32]),
-        DI(afl->stage_cycles[STAGE_FLIP32]));
+    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]));
 
   SAYF(bV bSTOP "  byte flips : " cRST "%-36s " bSTG bV bSTOP
                 "   pending : " cRST "%-10s" bSTG       bV "\n",
-       tmp, DI(afl->pending_not_fuzzed));
+       tmp, u_stringify_int(IB(0), afl->pending_not_fuzzed));
 
   if (!afl->skip_deterministic)
-    sprintf(tmp, "%s/%s, %s/%s, %s/%s", DI(afl->stage_finds[STAGE_ARITH8]),
-            DI(afl->stage_cycles[STAGE_ARITH8]),
-            DI(afl->stage_finds[STAGE_ARITH16]),
-            DI(afl->stage_cycles[STAGE_ARITH16]),
-            DI(afl->stage_finds[STAGE_ARITH32]),
-            DI(afl->stage_cycles[STAGE_ARITH32]));
+    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]));
 
   SAYF(bV bSTOP " arithmetics : " cRST "%-36s " bSTG bV bSTOP
                 "  pend fav : " cRST "%-10s" bSTG       bV "\n",
-       tmp, DI(afl->pending_favored));
+       tmp, u_stringify_int(IB(0), afl->pending_favored));
 
   if (!afl->skip_deterministic)
-    sprintf(tmp, "%s/%s, %s/%s, %s/%s", DI(afl->stage_finds[STAGE_INTEREST8]),
-            DI(afl->stage_cycles[STAGE_INTEREST8]),
-            DI(afl->stage_finds[STAGE_INTEREST16]),
-            DI(afl->stage_cycles[STAGE_INTEREST16]),
-            DI(afl->stage_finds[STAGE_INTEREST32]),
-            DI(afl->stage_cycles[STAGE_INTEREST32]));
+    sprintf(tmp, "%s/%s, %s/%s, %s/%s",
+            u_stringify_int(IB(0), afl->stage_finds[STAGE_INTEREST8]),
+            u_stringify_int(IB(1), afl->stage_cycles[STAGE_INTEREST8]),
+            u_stringify_int(IB(2), afl->stage_finds[STAGE_INTEREST16]),
+            u_stringify_int(IB(3), afl->stage_cycles[STAGE_INTEREST16]),
+            u_stringify_int(IB(4), afl->stage_finds[STAGE_INTEREST32]),
+            u_stringify_int(IB(5), afl->stage_cycles[STAGE_INTEREST32]));
 
   SAYF(bV bSTOP "  known ints : " cRST "%-36s " bSTG bV bSTOP
                 " own finds : " cRST "%-10s" bSTG       bV "\n",
-       tmp, DI(afl->queued_discovered));
+       tmp, u_stringify_int(IB(0), afl->queued_discovered));
 
   if (!afl->skip_deterministic)
-    sprintf(tmp, "%s/%s, %s/%s, %s/%s", DI(afl->stage_finds[STAGE_EXTRAS_UO]),
-            DI(afl->stage_cycles[STAGE_EXTRAS_UO]),
-            DI(afl->stage_finds[STAGE_EXTRAS_UI]),
-            DI(afl->stage_cycles[STAGE_EXTRAS_UI]),
-            DI(afl->stage_finds[STAGE_EXTRAS_AO]),
-            DI(afl->stage_cycles[STAGE_EXTRAS_AO]));
+    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]));
 
   SAYF(bV bSTOP "  dictionary : " cRST "%-36s " bSTG bV bSTOP
                 "  imported : " cRST "%-10s" bSTG       bV "\n",
-       tmp, afl->sync_id ? DI(afl->queued_imported) : (u8 *)"n/a");
+       tmp,
+       afl->sync_id ? u_stringify_int(IB(0), afl->queued_imported) : (u8 *)"n/a");
 
-  sprintf(
-      tmp, "%s/%s, %s/%s, %s/%s", DI(afl->stage_finds[STAGE_HAVOC]),
-      DI(afl->stage_cycles[STAGE_HAVOC]), DI(afl->stage_finds[STAGE_SPLICE]),
-      DI(afl->stage_cycles[STAGE_SPLICE]), DI(afl->stage_finds[STAGE_RADAMSA]),
-      DI(afl->stage_cycles[STAGE_RADAMSA]));
+  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]));
 
   SAYF(bV bSTOP "   havoc/rad : " cRST "%-36s " bSTG bV bSTOP, tmp);
 
@@ -631,23 +660,25 @@ void show_stats(afl_state_t *afl) {
   if (afl->shm.cmplog_mode) {
 
     sprintf(tmp, "%s/%s, %s/%s, %s/%s, %s/%s",
-            DI(afl->stage_finds[STAGE_PYTHON]),
-            DI(afl->stage_cycles[STAGE_PYTHON]),
-            DI(afl->stage_finds[STAGE_CUSTOM_MUTATOR]),
-            DI(afl->stage_cycles[STAGE_CUSTOM_MUTATOR]),
-            DI(afl->stage_finds[STAGE_COLORIZATION]),
-            DI(afl->stage_cycles[STAGE_COLORIZATION]),
-            DI(afl->stage_finds[STAGE_ITS]), DI(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);
 
   } else {
 
-    sprintf(tmp, "%s/%s, %s/%s", DI(afl->stage_finds[STAGE_PYTHON]),
-            DI(afl->stage_cycles[STAGE_PYTHON]),
-            DI(afl->stage_finds[STAGE_CUSTOM_MUTATOR]),
-            DI(afl->stage_cycles[STAGE_CUSTOM_MUTATOR]));
+    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]));
 
     SAYF(bV bSTOP "   py/custom : " cRST "%-36s " bSTG bVR bH20 bH2 bH bRB "\n",
          tmp);
@@ -663,7 +694,7 @@ void show_stats(afl_state_t *afl) {
     sprintf(tmp, "%0.02f%%/%s, ",
             ((double)(afl->bytes_trim_in - afl->bytes_trim_out)) * 100 /
                 afl->bytes_trim_in,
-            DI(afl->trim_execs));
+            u_stringify_int(IB(0), afl->trim_execs));
 
   }
 
@@ -688,8 +719,9 @@ void show_stats(afl_state_t *afl) {
 
   if (afl->mutator) {
 
-    sprintf(tmp, "%s/%s", DI(afl->stage_finds[STAGE_CUSTOM_MUTATOR]),
-            DI(afl->stage_cycles[STAGE_CUSTOM_MUTATOR]));
+    sprintf(tmp, "%s/%s",
+            u_stringify_int(IB(0), afl->stage_finds[STAGE_CUSTOM_MUTATOR]),
+            u_stringify_int(IB(1), afl->stage_cycles[STAGE_CUSTOM_MUTATOR]));
     SAYF(bV bSTOP " custom mut. : " cRST "%-36s " bSTG bV RESET_G1, tmp);
 
   } else {
@@ -744,6 +776,8 @@ void show_stats(afl_state_t *afl) {
   /* Last line */
   SAYF(SET_G1 "\n" bSTG bLB bH30 bH20 bH2 bRB bSTOP cRST RESET_G1);
 
+#undef IB
+
   /* Hallelujah! */
 
   fflush(0);
@@ -762,6 +796,9 @@ void show_init_stats(afl_state_t *afl) {
   u64                 avg_us = 0;
   u32                 max_len = 0;
 
+  u8 val_bufs[4][STRINGIFY_VAL_SIZE_MAX];
+#define IB(i) val_bufs[(i)], sizeof(val_bufs[(i)])
+
   if (afl->total_cal_cycles) avg_us = afl->total_cal_us / afl->total_cal_cycles;
 
   while (q) {
@@ -797,10 +834,10 @@ void show_init_stats(afl_state_t *afl) {
 
     if (max_len > 50 * 1024)
       WARNF(cLRD "Some test cases are huge (%s) - see %s/perf_tips.md!",
-            DMS(max_len), doc_path);
+            stringify_mem_size(IB(0), max_len), doc_path);
     else if (max_len > 10 * 1024)
-      WARNF("Some test cases are big (%s) - see %s/perf_tips.md.", DMS(max_len),
-            doc_path);
+      WARNF("Some test cases are big (%s) - see %s/perf_tips.md.",
+            stringify_mem_size(IB(0), max_len), doc_path);
 
     if (afl->useless_at_start && !afl->in_bitmap)
       WARNF(cLRD "Some test cases look useless. Consider using a smaller set.");
@@ -824,7 +861,8 @@ void show_init_stats(afl_state_t *afl) {
       max_bits,
       ((double)afl->total_bitmap_size) /
           (afl->total_bitmap_entries ? afl->total_bitmap_entries : 1),
-      DI(min_us), DI(max_us), DI(avg_us));
+      stringify_int(IB(0), min_us), stringify_int(IB(1), max_us),
+      stringify_int(IB(2), avg_us));
 
   if (!afl->timeout_given) {
 
@@ -868,6 +906,7 @@ void show_init_stats(afl_state_t *afl) {
     afl->hang_tmout = MIN(EXEC_TIMEOUT, afl->fsrv.exec_tmout * 2 + 100);
 
   OKF("All set and ready to roll!");
+#undef IB
 
 }
 
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index 10fee76c..ba56ff67 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -96,8 +96,8 @@ static void usage(afl_state_t *afl, u8 *argv0, int more_help) {
       "Execution control settings:\n"
       "  -p schedule   - power schedules recompute a seed's performance "
       "score.\n"
-      "                  <explore (default), fast, coe, lin, quad, exploit, "
-      "mmopt>\n"
+      "                  <explore(default), fast, coe, lin, quad, exploit, "
+      "mmopt, rare>\n"
       "                  see docs/power_schedules.md\n"
       "  -f file       - location read by the fuzzed program (stdin)\n"
       "  -t msec       - timeout for each run (auto-scaled, 50-%d ms)\n"
@@ -230,8 +230,7 @@ int main(int argc, char **argv_orig, char **envp) {
   u64    prev_queued = 0;
   u32    sync_interval_cnt = 0, seek_to, show_help = 0;
   u8 *   extras_dir = 0;
-  u8     mem_limit_given = 0;
-  u8     exit_1 = !!get_afl_env("AFL_BENCH_JUST_ONE");
+  u8     mem_limit_given = 0, exit_1 = 0;
   char **use_argv;
 
   struct timeval  tv;
@@ -246,11 +245,12 @@ int main(int argc, char **argv_orig, char **envp) {
   afl_fsrv_init(&afl->fsrv);
 
   read_afl_environment(afl, envp);
+  exit_1 = !!afl->afl_env.afl_bench_just_one;
 
   SAYF(cCYA "afl-fuzz" VERSION cRST
             " based on afl by Michal Zalewski and a big online community\n");
 
-  doc_path = access(DOC_PATH, F_OK) ? (u8 *)"docs" : doc_path;
+  doc_path = access(DOC_PATH, F_OK) != 0 ? (u8 *)"docs" : (u8 *)DOC_PATH;
 
   gettimeofday(&tv, &tz);
   afl->init_seed = tv.tv_sec ^ tv.tv_usec ^ getpid();
@@ -304,6 +304,10 @@ int main(int argc, char **argv_orig, char **envp) {
 
           afl->schedule = MMOPT;
 
+        } else if (!stricmp(optarg, "rare")) {
+
+          afl->schedule = RARE;
+
         } else if (!stricmp(optarg, "explore") || !stricmp(optarg, "default") ||
 
                    !stricmp(optarg, "normal") || !stricmp(optarg, "afl")) {
@@ -760,8 +764,9 @@ int main(int argc, char **argv_orig, char **envp) {
     case LIN: OKF("Using linear power schedule (LIN)"); break;
     case QUAD: OKF("Using quadratic power schedule (QUAD)"); break;
     case MMOPT: OKF("Using modified MOpt power schedule (MMOPT)"); break;
+    case RARE: OKF("Using rare edge focus power schedule (RARE)"); break;
     case EXPLORE:
-      OKF("Using exploration-based constant power schedule (EXPLORE)");
+      OKF("Using exploration-based constant power schedule (EXPLORE, default)");
       break;
     default: FATAL("Unknown power schedule"); break;
 
@@ -1046,9 +1051,9 @@ int main(int argc, char **argv_orig, char **envp) {
 
       }
 
-      show_stats(afl);
+      // show_stats(afl);
 
-      if (afl->not_on_tty) {
+      if (unlikely(afl->not_on_tty)) {
 
         ACTF("Entering queue cycle %llu.", afl->queue_cycle);
         fflush(stdout);
@@ -1119,7 +1124,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
   }
 
-  if (afl->queue_cur) show_stats(afl);
+  // if (afl->queue_cur) show_stats(afl);
 
   /*
    * ATTENTION - the following 10 lines were copied from a PR to Google's afl
@@ -1144,12 +1149,12 @@ int main(int argc, char **argv_orig, char **envp) {
   }
 
   write_bitmap(afl);
-  write_stats_file(afl, 0, 0, 0);
   maybe_update_plot_file(afl, 0, 0);
   save_auto(afl);
 
 stop_fuzzing:
 
+  write_stats_file(afl, 0, 0, 0);
   afl->force_ui_update = 1;  // ensure the screen is reprinted
   show_stats(afl);           // print the screen one last time
 
diff --git a/src/afl-gotcpu.c b/src/afl-gotcpu.c
index 70ed4dbc..6c2fa147 100644
--- a/src/afl-gotcpu.c
+++ b/src/afl-gotcpu.c
@@ -90,7 +90,7 @@ static u64 get_cpu_usage_us(void) {
 
 static u32 measure_preemption(u32 target_ms) {
 
-  static volatile u32 v1, v2;
+  volatile u32 v1, v2 = 0;
 
   u64 st_t, en_t, st_c, en_c, real_delta, slice_delta;
   s32 loop_repeats = 0;
diff --git a/src/afl-showmap.c b/src/afl-showmap.c
index 0051bbec..caacefe4 100644
--- a/src/afl-showmap.c
+++ b/src/afl-showmap.c
@@ -263,9 +263,8 @@ static void write_to_testcase(afl_forkserver_t *fsrv, void *mem, u32 len) {
 static u8 run_target_forkserver(afl_forkserver_t *fsrv, char **argv, u8 *mem,
                                 u32 len) {
 
-  static struct itimerval it;
-  static u32              prev_timed_out = 0;
-  int                     status = 0;
+  struct itimerval it;
+  int              status = 0;
 
   memset(fsrv->trace_bits, 0, MAP_SIZE);
   MEM_BARRIER();
@@ -277,7 +276,7 @@ static u8 run_target_forkserver(afl_forkserver_t *fsrv, char **argv, u8 *mem,
   /* we have the fork server up and running, so simply
      tell it to have at it, and then read back PID. */
 
-  if ((res = write(fsrv->fsrv_ctl_fd, &prev_timed_out, 4)) != 4) {
+  if ((res = write(fsrv->fsrv_ctl_fd, &fsrv->prev_timed_out, 4)) != 4) {
 
     if (stop_soon) return 0;
     RPFATAL(res, "Unable to request new process from fork server (OOM?)");
@@ -579,11 +578,6 @@ static void setup_signal_handlers(void) {
   sigaction(SIGINT, &sa, NULL);
   sigaction(SIGTERM, &sa, NULL);
 
-  /* Exec timeout notifications. */
-
-  sa.sa_handler = handle_timeout;
-  sigaction(SIGALRM, &sa, NULL);
-
 }
 
 /* Show banner. */
diff --git a/src/afl-tmin.c b/src/afl-tmin.c
index 17e9af5a..2275aef5 100644
--- a/src/afl-tmin.c
+++ b/src/afl-tmin.c
@@ -247,160 +247,14 @@ static void write_to_testcase(afl_forkserver_t *fsrv, void *mem, u32 len) {
 
 }
 
-/* Handle timeout signal. */
-/*
-static void handle_timeout(int sig) {
-
-  if (child_pid > 0) {
-
-  child_timed_out = 1;
-    kill(child_pid, SIGKILL);
-
-  } else if (child_pid == -1 && forksrv_pid > 0) {
-
-    child_timed_out = 1;
-    kill(forksrv_pid, SIGKILL);
-
-  }
-
-}
-
-*/
-
-/* start the app and it's forkserver */
-/*
-static void init_forkserver(char **argv) {
-
-  static struct itimerval it;
-  int st_pipe[2], ctl_pipe[2];
-  int status = 0;
-  s32 rlen;
-
-  ACTF("Spinning up the fork server...");
-  if (pipe(st_pipe) || pipe(ctl_pipe)) PFATAL("pipe() failed");
-
-  forksrv_pid = fork();
-
-  if (forksrv_pid < 0) PFATAL("fork() failed");
-
-  if (!forksrv_pid) {
-
-    struct rlimit r;
-
-    if (dup2(use_stdin ? out_fd : dev_null_fd, 0) < 0 ||
-        dup2(dev_null_fd, 1) < 0 ||
-        dup2(dev_null_fd, 2) < 0) {
-
-      *(u32*)trace_bits = EXEC_FAIL_SIG;
-      PFATAL("dup2() failed");
-
-    }
-
-    close(dev_null_fd);
-    close(out_fd);
-
-    setsid();
-
-    if (mem_limit) {
-
-      r.rlim_max = r.rlim_cur = ((rlim_t)mem_limit) << 20;
-
-#ifdef RLIMIT_AS
-
-      setrlimit(RLIMIT_AS, &r); // Ignore errors
-
-#else
-
-      setrlimit(RLIMIT_DATA, &r); // Ignore errors
-
-#endif // ^RLIMIT_AS
-
-    }
-
-    r.rlim_max = r.rlim_cur = 0;
-    setrlimit(RLIMIT_CORE, &r); // Ignore errors
-
-    // Set up control and status pipes, close the unneeded original fds.
-
-    if (dup2(ctl_pipe[0], FORKSRV_FD) < 0) PFATAL("dup2() failed");
-    if (dup2(st_pipe[1], FORKSRV_FD + 1) < 0) PFATAL("dup2() failed");
-
-    close(ctl_pipe[0]);
-    close(ctl_pipe[1]);
-    close(st_pipe[0]);
-    close(st_pipe[1]);
-
-    execv(fsrv->target_path, argv);
-
-    *(u32*)trace_bits = EXEC_FAIL_SIG;
-    exit(0);
-
-  }
-
-  // Close the unneeded endpoints.
-
-  close(ctl_pipe[0]);
-  close(st_pipe[1]);
-
-  fsrv_ctl_fd = ctl_pipe[1];
-  fsrv_st_fd  = st_pipe[0];
-
-  // Configure timeout, wait for child, cancel timeout.
-
-  if (exec_tmout) {
-
-    child_timed_out = 0;
-    it.it_value.tv_sec = (exec_tmout * FORK_WAIT_MULT / 1000);
-    it.it_value.tv_usec = ((exec_tmout * FORK_WAIT_MULT) % 1000) * 1000;
-
-  }
-
-  setitimer(ITIMER_REAL, &it, NULL);
-
-  rlen = read(fsrv_st_fd, &status, 4);
-
-  it.it_value.tv_sec = 0;
-  it.it_value.tv_usec = 0;
-  setitimer(ITIMER_REAL, &it, NULL);
-
-  // If we have a four-byte "hello" message from the server, we're all set.
-  // Otherwise, try to figure out what went wrong.
-
-  if (rlen == 4) {
-
-    ACTF("All right - fork server is up.");
-    return;
-
-  }
-
-  if (waitpid(forksrv_pid, &status, 0) <= 0)
-    PFATAL("waitpid() failed");
-
-  u8 child_crashed;
-
-  if (WIFSIGNALED(status))
-    child_crashed = 1;
-
-  if (child_timed_out)
-    SAYF(cLRD "\n+++ Program timed off +++\n" cRST);
-  else if (stop_soon)
-    SAYF(cLRD "\n+++ Program aborted by user +++\n" cRST);
-  else if (child_crashed)
-    SAYF(cLRD "\n+++ Program killed by signal %u +++\n" cRST, WTERMSIG(status));
-
-}
-
-*/
-
 /* Execute target application. Returns 0 if the changes are a dud, or
    1 if they should be kept. */
 
 static u8 run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len,
                      u8 first_run) {
 
-  static struct itimerval it;
-  static u32              prev_timed_out = 0;
-  int                     status = 0;
+  struct itimerval it;
+  int              status = 0;
 
   u32 cksum;
 
@@ -416,7 +270,7 @@ static u8 run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len,
   /* we have the fork server up and running, so simply
      tell it to have at it, and then read back PID. */
 
-  if ((res = write(fsrv->fsrv_ctl_fd, &prev_timed_out, 4)) != 4) {
+  if ((res = write(fsrv->fsrv_ctl_fd, &fsrv->prev_timed_out, 4)) != 4) {
 
     if (stop_soon) return 0;
     RPFATAL(res, "Unable to request new process from fork server (OOM?)");
@@ -962,11 +816,6 @@ static void setup_signal_handlers(void) {
   sigaction(SIGINT, &sa, NULL);
   sigaction(SIGTERM, &sa, NULL);
 
-  /* Exec timeout notifications. */
-
-  sa.sa_handler = handle_timeout;
-  sigaction(SIGALRM, &sa, NULL);
-
 }
 
 /* Display usage hints. */