about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/afl-cc.c498
-rw-r--r--src/afl-forkserver.c6
-rw-r--r--src/afl-fuzz-init.c32
-rw-r--r--src/afl-fuzz-one.c18
-rw-r--r--src/afl-fuzz-queue.c92
-rw-r--r--src/afl-fuzz.c143
-rw-r--r--src/afl-ld-lto.c4
-rw-r--r--src/afl-showmap.c31
8 files changed, 577 insertions, 247 deletions
diff --git a/src/afl-cc.c b/src/afl-cc.c
index d1001187..972ac8cd 100644
--- a/src/afl-cc.c
+++ b/src/afl-cc.c
@@ -31,6 +31,8 @@
 #include <strings.h>
 #include <limits.h>
 #include <assert.h>
+#include <ctype.h>
+#include <sys/stat.h>
 
 #if (LLVM_MAJOR - 0 == 0)
   #undef LLVM_MAJOR
@@ -76,6 +78,7 @@ enum {
   INSTRUMENT_OPT_NGRAM = 16,
   INSTRUMENT_OPT_CALLER = 32,
   INSTRUMENT_OPT_CTX_K = 64,
+  INSTRUMENT_OPT_CODECOV = 128,
 
 };
 
@@ -375,15 +378,304 @@ void parse_fsanitize(char *string) {
 
 }
 
+static u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0,
+          shared_linking = 0, preprocessor_only = 0, have_unroll = 0,
+          have_o = 0, have_pic = 0, have_c = 0, partial_linking = 0,
+          non_dash = 0;
+
+static void process_params(u32 argc, char **argv) {
+
+  if (cc_par_cnt + argc >= 1024) { FATAL("Too many command line parameters"); }
+
+  if (lto_mode && argc > 1) {
+
+    u32 idx;
+    for (idx = 1; idx < argc; idx++) {
+
+      if (!strncasecmp(argv[idx], "-fpic", 5)) have_pic = 1;
+
+    }
+
+  }
+
+  // for (u32 x = 0; x < argc; ++x) fprintf(stderr, "[%u] %s\n", x, argv[x]);
+
+  /* Process the argument list. */
+
+  u8 skip_next = 0;
+  while (--argc) {
+
+    u8 *cur = *(++argv);
+
+    if (skip_next) {
+
+      skip_next = 0;
+      continue;
+
+    }
+
+    if (cur[0] != '-') { non_dash = 1; }
+    if (!strncmp(cur, "--afl", 5)) continue;
+
+    if (lto_mode && !strncmp(cur, "-flto=thin", 10)) {
+
+      FATAL(
+          "afl-clang-lto cannot work with -flto=thin. Switch to -flto=full or "
+          "use afl-clang-fast!");
+
+    }
+
+    if (lto_mode && !strncmp(cur, "-fuse-ld=", 9)) continue;
+    if (lto_mode && !strncmp(cur, "--ld-path=", 10)) continue;
+    if (!strncmp(cur, "-fno-unroll", 11)) continue;
+    if (strstr(cur, "afl-compiler-rt") || strstr(cur, "afl-llvm-rt")) continue;
+    if (!strcmp(cur, "-Wl,-z,defs") || !strcmp(cur, "-Wl,--no-undefined") ||
+        !strcmp(cur, "--no-undefined")) {
+
+      continue;
+
+    }
+
+    if (compiler_mode == GCC_PLUGIN && !strcmp(cur, "-pipe")) { continue; }
+
+    if (!strcmp(cur, "-z") || !strcmp(cur, "-Wl,-z")) {
+
+      u8 *param = *(argv + 1);
+      if (!strcmp(param, "defs") || !strcmp(param, "-Wl,defs")) {
+
+        skip_next = 1;
+        continue;
+
+      }
+
+    }
+
+    if ((compiler_mode == GCC || compiler_mode == GCC_PLUGIN) &&
+        !strncmp(cur, "-stdlib=", 8)) {
+
+      if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); }
+      continue;
+
+    }
+
+    if (!strncmp(cur, "-fsanitize-coverage-", 20) && strstr(cur, "list=")) {
+
+      have_instr_list = 1;
+
+    }
+
+    if (!strncmp(cur, "-fsanitize=", strlen("-fsanitize=")) &&
+        strchr(cur, ',')) {
+
+      parse_fsanitize(cur);
+      if (!cur || strlen(cur) <= strlen("-fsanitize=")) { continue; }
+
+    } else if ((!strncmp(cur, "-fsanitize=fuzzer-",
+
+                         strlen("-fsanitize=fuzzer-")) ||
+                !strncmp(cur, "-fsanitize-coverage",
+                         strlen("-fsanitize-coverage"))) &&
+               (strncmp(cur, "sanitize-coverage-allow",
+                        strlen("sanitize-coverage-allow")) &&
+                strncmp(cur, "sanitize-coverage-deny",
+                        strlen("sanitize-coverage-deny")) &&
+                instrument_mode != INSTRUMENT_LLVMNATIVE)) {
+
+      if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); }
+      continue;
+
+    }
+
+    if (need_aflpplib || !strcmp(cur, "-fsanitize=fuzzer")) {
+
+      u8 *afllib = find_object("libAFLDriver.a", argv[0]);
+
+      if (!be_quiet) {
+
+        OKF("Found '-fsanitize=fuzzer', replacing with libAFLDriver.a");
+
+      }
+
+      if (!afllib) {
+
+        if (!be_quiet) {
+
+          WARNF(
+              "Cannot find 'libAFLDriver.a' to replace '-fsanitize=fuzzer' in "
+              "the flags - this will fail!");
+
+        }
+
+      } else {
+
+        cc_params[cc_par_cnt++] = afllib;
+
+#ifdef __APPLE__
+        cc_params[cc_par_cnt++] = "-undefined";
+        cc_params[cc_par_cnt++] = "dynamic_lookup";
+#endif
+
+      }
+
+      if (need_aflpplib) {
+
+        need_aflpplib = 0;
+
+      } else {
+
+        continue;
+
+      }
+
+    }
+
+    if (!strcmp(cur, "-m32")) bit_mode = 32;
+    if (!strcmp(cur, "armv7a-linux-androideabi")) bit_mode = 32;
+    if (!strcmp(cur, "-m64")) bit_mode = 64;
+
+    if (!strcmp(cur, "-fsanitize=address") || !strcmp(cur, "-fsanitize=memory"))
+      asan_set = 1;
+
+    if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1;
+
+    if (!strcmp(cur, "-x")) x_set = 1;
+    if (!strcmp(cur, "-E")) preprocessor_only = 1;
+    if (!strcmp(cur, "-shared")) shared_linking = 1;
+    if (!strcmp(cur, "-dynamiclib")) shared_linking = 1;
+    if (!strcmp(cur, "--target=wasm32-wasi")) passthrough = 1;
+    if (!strcmp(cur, "-Wl,-r")) partial_linking = 1;
+    if (!strcmp(cur, "-Wl,-i")) partial_linking = 1;
+    if (!strcmp(cur, "-Wl,--relocatable")) partial_linking = 1;
+    if (!strcmp(cur, "-r")) partial_linking = 1;
+    if (!strcmp(cur, "--relocatable")) partial_linking = 1;
+    if (!strcmp(cur, "-c")) have_c = 1;
+
+    if (!strncmp(cur, "-O", 2)) have_o = 1;
+    if (!strncmp(cur, "-funroll-loop", 13)) have_unroll = 1;
+
+    if (*cur == '@') {
+
+      // response file support.
+      // we have two choices - move everything to the command line or
+      // rewrite the response files to temporary files and delete them
+      // afterwards. We choose the first for easiness.
+      // We do *not* support quotes in the rsp files to cope with spaces in
+      // filenames etc! If you need that then send a patch!
+      u8 *filename = cur + 1;
+      if (debug) { DEBUGF("response file=%s\n", filename); }
+      FILE       *f = fopen(filename, "r");
+      struct stat st;
+
+      // Check not found or empty? let the compiler complain if so.
+      if (!f || fstat(fileno(f), &st) < 0 || st.st_size < 1) {
+
+        cc_params[cc_par_cnt++] = cur;
+        continue;
+
+      }
+
+      u8    *tmpbuf = malloc(st.st_size + 1), *ptr;
+      char **args = malloc(sizeof(char *) * (st.st_size >> 1));
+      int    count = 1, cont = 0, cont_act = 0;
+
+      while (fgets(tmpbuf, st.st_size, f)) {
+
+        ptr = tmpbuf;
+        // no leading whitespace
+        while (isspace(*ptr)) {
+
+          ++ptr;
+          cont_act = 0;
+
+        }
+
+        // no comments, no empty lines
+        if (*ptr == '#' || *ptr == '\n' || !*ptr) { continue; }
+        // remove LF
+        if (ptr[strlen(ptr) - 1] == '\n') { ptr[strlen(ptr) - 1] = 0; }
+        // remove CR
+        if (*ptr && ptr[strlen(ptr) - 1] == '\r') { ptr[strlen(ptr) - 1] = 0; }
+        // handle \ at end of line
+        if (*ptr && ptr[strlen(ptr) - 1] == '\\') {
+
+          cont = 1;
+          ptr[strlen(ptr) - 1] = 0;
+
+        }
+
+        // remove whitespace at end
+        while (*ptr && isspace(ptr[strlen(ptr) - 1])) {
+
+          ptr[strlen(ptr) - 1] = 0;
+          cont = 0;
+
+        }
+
+        if (*ptr) {
+
+          do {
+
+            u8 *value = ptr;
+            while (*ptr && !isspace(*ptr)) {
+
+              ++ptr;
+
+            }
+
+            while (*ptr && isspace(*ptr)) {
+
+              *ptr++ = 0;
+
+            }
+
+            if (cont_act) {
+
+              u32 len = strlen(args[count - 1]) + strlen(value) + 1;
+              u8 *tmp = malloc(len);
+              snprintf(tmp, len, "%s%s", args[count - 1], value);
+              free(args[count - 1]);
+              args[count - 1] = tmp;
+              cont_act = 0;
+
+            } else {
+
+              args[count++] = strdup(value);
+
+            }
+
+          } while (*ptr);
+
+        }
+
+        if (cont) {
+
+          cont_act = 1;
+          cont = 0;
+
+        }
+
+      }
+
+      if (count) { process_params(count, args); }
+
+      // we cannot free args[]
+      free(tmpbuf);
+
+      continue;
+
+    }
+
+    cc_params[cc_par_cnt++] = cur;
+
+  }
+
+}
+
 /* Copy argv to cc_params, making the necessary edits. */
 
 static void edit_params(u32 argc, char **argv, char **envp) {
 
-  u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0, shared_linking = 0,
-     preprocessor_only = 0, have_unroll = 0, have_o = 0, have_pic = 0,
-     have_c = 0, partial_linking = 0;
-
-  cc_params = ck_alloc((argc + 128) * sizeof(u8 *));
+  cc_params = ck_alloc(1024 * sizeof(u8 *));
 
   if (lto_mode) {
 
@@ -642,7 +934,7 @@ static void edit_params(u32 argc, char **argv, char **envp) {
     }
 
     //#if LLVM_MAJOR >= 13
-    //    // Use the old pass manager in LLVM 14 which the afl++ passes still
+    //    // Use the old pass manager in LLVM 14 which the AFL++ passes still
     //    use. cc_params[cc_par_cnt++] = "-flegacy-pass-manager";
     //#endif
 
@@ -751,7 +1043,21 @@ static void edit_params(u32 argc, char **argv, char **envp) {
       } else if (instrument_mode == INSTRUMENT_LLVMNATIVE) {
 
 #if LLVM_MAJOR >= 4
-        cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
+        if (instrument_opt_mode & INSTRUMENT_OPT_CODECOV) {
+
+  #if LLVM_MAJOR >= 6
+          cc_params[cc_par_cnt++] =
+              "-fsanitize-coverage=trace-pc-guard,bb,no-prune,pc-table";
+  #else
+          FATAL("pcguard instrumentation with pc-table requires llvm 6.0.1+");
+  #endif
+
+        } else {
+
+          cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
+
+        }
+
 #else
         FATAL("pcguard instrumentation requires llvm 4.0.1+");
 #endif
@@ -816,159 +1122,15 @@ static void edit_params(u32 argc, char **argv, char **envp) {
 
       }
 
-      if (!have_pic) cc_params[cc_par_cnt++] = "-fPIC";
-
     }
 
   }
 
-  /* Detect stray -v calls from ./configure scripts. */
-
-  u8 skip_next = 0, non_dash = 0;
-  while (--argc) {
-
-    u8 *cur = *(++argv);
-
-    if (skip_next) {
-
-      skip_next = 0;
-      continue;
-
-    }
-
-    if (cur[0] != '-') { non_dash = 1; }
-    if (!strncmp(cur, "--afl", 5)) continue;
-    if (lto_mode && !strncmp(cur, "-fuse-ld=", 9)) continue;
-    if (lto_mode && !strncmp(cur, "--ld-path=", 10)) continue;
-    if (!strncmp(cur, "-fno-unroll", 11)) continue;
-    if (strstr(cur, "afl-compiler-rt") || strstr(cur, "afl-llvm-rt")) continue;
-    if (!strcmp(cur, "-Wl,-z,defs") || !strcmp(cur, "-Wl,--no-undefined") ||
-        !strcmp(cur, "--no-undefined")) {
-
-      continue;
-
-    }
-
-    if (compiler_mode == GCC_PLUGIN && !strcmp(cur, "-pipe")) { continue; }
-
-    if (!strcmp(cur, "-z") || !strcmp(cur, "-Wl,-z")) {
-
-      u8 *param = *(argv + 1);
-      if (!strcmp(param, "defs") || !strcmp(param, "-Wl,defs")) {
-
-        skip_next = 1;
-        continue;
-
-      }
-
-    }
-
-    if ((compiler_mode == GCC || compiler_mode == GCC_PLUGIN) &&
-        !strncmp(cur, "-stdlib=", 8)) {
-
-      if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); }
-      continue;
-
-    }
-
-    if (!strncmp(cur, "-fsanitize-coverage-", 20) && strstr(cur, "list=")) {
-
-      have_instr_list = 1;
-
-    }
-
-    if (!strncmp(cur, "-fsanitize=", strlen("-fsanitize=")) &&
-        strchr(cur, ',')) {
-
-      parse_fsanitize(cur);
-      if (!cur || strlen(cur) <= strlen("-fsanitize=")) { continue; }
-
-    } else if ((!strncmp(cur, "-fsanitize=fuzzer-",
-
-                         strlen("-fsanitize=fuzzer-")) ||
-                !strncmp(cur, "-fsanitize-coverage",
-                         strlen("-fsanitize-coverage"))) &&
-               (strncmp(cur, "sanitize-coverage-allow",
-                        strlen("sanitize-coverage-allow")) &&
-                strncmp(cur, "sanitize-coverage-deny",
-                        strlen("sanitize-coverage-deny")) &&
-                instrument_mode != INSTRUMENT_LLVMNATIVE)) {
-
-      if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); }
-      continue;
-
-    }
-
-    if (need_aflpplib || !strcmp(cur, "-fsanitize=fuzzer")) {
-
-      u8 *afllib = find_object("libAFLDriver.a", argv[0]);
-
-      if (!be_quiet) {
-
-        OKF("Found '-fsanitize=fuzzer', replacing with libAFLDriver.a");
-
-      }
-
-      if (!afllib) {
-
-        if (!be_quiet) {
-
-          WARNF(
-              "Cannot find 'libAFLDriver.a' to replace '-fsanitize=fuzzer' in "
-              "the flags - this will fail!");
-
-        }
-
-      } else {
-
-        cc_params[cc_par_cnt++] = afllib;
-
-#ifdef __APPLE__
-        cc_params[cc_par_cnt++] = "-undefined";
-        cc_params[cc_par_cnt++] = "dynamic_lookup";
-#endif
-
-      }
-
-      if (need_aflpplib) {
-
-        need_aflpplib = 0;
-
-      } else {
-
-        continue;
-
-      }
+  /* Inspect the command line parameters. */
 
-    }
+  process_params(argc, argv);
 
-    if (!strcmp(cur, "-m32")) bit_mode = 32;
-    if (!strcmp(cur, "armv7a-linux-androideabi")) bit_mode = 32;
-    if (!strcmp(cur, "-m64")) bit_mode = 64;
-
-    if (!strcmp(cur, "-fsanitize=address") || !strcmp(cur, "-fsanitize=memory"))
-      asan_set = 1;
-
-    if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1;
-
-    if (!strcmp(cur, "-x")) x_set = 1;
-    if (!strcmp(cur, "-E")) preprocessor_only = 1;
-    if (!strcmp(cur, "-shared")) shared_linking = 1;
-    if (!strcmp(cur, "-dynamiclib")) shared_linking = 1;
-    if (!strcmp(cur, "--target=wasm32-wasi")) passthrough = 1;
-    if (!strcmp(cur, "-Wl,-r")) partial_linking = 1;
-    if (!strcmp(cur, "-Wl,-i")) partial_linking = 1;
-    if (!strcmp(cur, "-Wl,--relocatable")) partial_linking = 1;
-    if (!strcmp(cur, "-r")) partial_linking = 1;
-    if (!strcmp(cur, "--relocatable")) partial_linking = 1;
-    if (!strcmp(cur, "-c")) have_c = 1;
-
-    if (!strncmp(cur, "-O", 2)) have_o = 1;
-    if (!strncmp(cur, "-funroll-loop", 13)) have_unroll = 1;
-
-    cc_params[cc_par_cnt++] = cur;
-
-  }
+  if (!have_pic) { cc_params[cc_par_cnt++] = "-fPIC"; }
 
   // in case LLVM is installed not via a package manager or "make install"
   // e.g. compiled download or compiled from github then its ./lib directory
@@ -1651,13 +1813,17 @@ int main(int argc, char **argv, char **envp) {
           instrument_mode = INSTRUMENT_CLASSIC;
           lto_mode = 1;
 
-        } else if (!instrument_mode || instrument_mode == INSTRUMENT_AFL)
+        } else if (!instrument_mode || instrument_mode == INSTRUMENT_AFL) {
 
           instrument_mode = INSTRUMENT_AFL;
-        else
+
+        } else {
+
           FATAL("main instrumentation mode already set with %s",
                 instrument_mode_string[instrument_mode]);
 
+        }
+
       }
 
       if (strncasecmp(ptr2, "pc-guard", strlen("pc-guard")) == 0 ||
@@ -1682,6 +1848,23 @@ int main(int argc, char **argv, char **envp) {
 
       }
 
+      if (strncasecmp(ptr2, "llvmcodecov", strlen("llvmcodecov")) == 0 ||
+          strncasecmp(ptr2, "llvm-codecov", strlen("llvm-codecov")) == 0) {
+
+        if (!instrument_mode || instrument_mode == INSTRUMENT_LLVMNATIVE) {
+
+          instrument_mode = INSTRUMENT_LLVMNATIVE;
+          instrument_opt_mode |= INSTRUMENT_OPT_CODECOV;
+
+        } else {
+
+          FATAL("main instrumentation mode already set with %s",
+                instrument_mode_string[instrument_mode]);
+
+        }
+
+      }
+
       if (strncasecmp(ptr2, "cfg", strlen("cfg")) == 0 ||
           strncasecmp(ptr2, "instrim", strlen("instrim")) == 0) {
 
@@ -2241,7 +2424,8 @@ int main(int argc, char **argv, char **envp) {
         "(requires LLVM 11 or higher)");
 #endif
 
-  if (instrument_opt_mode && instrument_mode != INSTRUMENT_CLASSIC)
+  if (instrument_opt_mode && instrument_opt_mode != INSTRUMENT_OPT_CODECOV &&
+      instrument_mode != INSTRUMENT_CLASSIC)
     FATAL(
         "CALLER, CTX and NGRAM instrumentation options can only be used with "
         "the LLVM CLASSIC instrumentation mode.");
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index aa8c8622..30c8901c 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -489,7 +489,7 @@ static void report_error_and_exit(int error) {
       break;
     case FS_ERROR_OLD_CMPLOG:
       FATAL(
-          "the -c cmplog target was instrumented with an too old afl++ "
+          "the -c cmplog target was instrumented with an too old AFL++ "
           "version, you need to recompile it.");
       break;
     case FS_ERROR_OLD_CMPLOG_QEMU:
@@ -987,7 +987,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
 
     if ((status & FS_OPT_ENABLED) == FS_OPT_ENABLED) {
 
-      // workaround for recent afl++ versions
+      // workaround for recent AFL++ versions
       if ((status & FS_OPT_OLD_AFLPP_WORKAROUND) == FS_OPT_OLD_AFLPP_WORKAROUND)
         status = (status & 0xf0ffffff);
 
@@ -1059,7 +1059,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
 
           FATAL(
               "Target's coverage map size of %u is larger than the one this "
-              "afl++ is set with (%u). Either set AFL_MAP_SIZE=%u and restart "
+              "AFL++ is set with (%u). Either set AFL_MAP_SIZE=%u and restart "
               " afl-fuzz, or change MAP_SIZE_POW2 in config.h and recompile "
               "afl-fuzz",
               tmp_map_size, fsrv->map_size, tmp_map_size);
diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c
index bd591c8f..baf56a5f 100644
--- a/src/afl-fuzz-init.c
+++ b/src/afl-fuzz-init.c
@@ -716,6 +716,8 @@ void read_testcases(afl_state_t *afl, u8 *directory) {
 
   }
 
+  // if (getenv("MYTEST")) afl->in_place_resume = 1;
+
   if (nl_cnt) {
 
     u32 done = 0;
@@ -827,6 +829,8 @@ void read_testcases(afl_state_t *afl, u8 *directory) {
 
   }
 
+  // if (getenv("MYTEST")) afl->in_place_resume = 0;
+
   free(nl);                                                  /* not tracked */
 
   if (!afl->queued_items && directory == NULL) {
@@ -908,8 +912,10 @@ void perform_dry_run(afl_state_t *afl) {
 
     if (res == afl->crash_mode || res == FSRV_RUN_NOBITS) {
 
-      SAYF(cGRA "    len = %u, map size = %u, exec speed = %llu us\n" cRST,
-           q->len, q->bitmap_size, q->exec_us);
+      SAYF(cGRA
+           "    len = %u, map size = %u, exec speed = %llu us, hash = "
+           "%016llx\n" cRST,
+           q->len, q->bitmap_size, q->exec_us, q->exec_cksum);
 
     }
 
@@ -1164,14 +1170,14 @@ void perform_dry_run(afl_state_t *afl) {
 
   u32 duplicates = 0, i;
 
-  for (idx = 0; idx < afl->queued_items; idx++) {
+  for (idx = 0; idx < afl->queued_items - 1; idx++) {
 
     q = afl->queue_buf[idx];
     if (!q || q->disabled || q->cal_failed || !q->exec_cksum) { continue; }
-
     u32 done = 0;
+
     for (i = idx + 1;
-         i < afl->queued_items && !done && likely(afl->queue_buf[i]); i++) {
+         likely(i < afl->queued_items && afl->queue_buf[i] && !done); ++i) {
 
       struct queue_entry *p = afl->queue_buf[i];
       if (p->disabled || p->cal_failed || !p->exec_cksum) { continue; }
@@ -1194,6 +1200,13 @@ void perform_dry_run(afl_state_t *afl) {
           p->disabled = 1;
           p->perf_score = 0;
 
+          if (afl->debug) {
+
+            WARNF("Same coverage - %s is kept active, %s is disabled.",
+                  q->fname, p->fname);
+
+          }
+
         } else {
 
           if (!q->was_fuzzed) {
@@ -1207,7 +1220,14 @@ void perform_dry_run(afl_state_t *afl) {
           q->disabled = 1;
           q->perf_score = 0;
 
-          done = 1;
+          if (afl->debug) {
+
+            WARNF("Same coverage - %s is kept active, %s is disabled.",
+                  p->fname, q->fname);
+
+          }
+
+          done = 1;  // end inner loop because outer loop entry is disabled now
 
         }
 
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index ee562f96..c6e9a295 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -842,6 +842,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
 
   eff_map = afl_realloc(AFL_BUF_PARAM(eff), EFF_ALEN(len));
   if (unlikely(!eff_map)) { PFATAL("alloc"); }
+  memset(eff_map, 0, EFF_ALEN(len));
   eff_map[0] = 1;
 
   if (EFF_APOS(len - 1) != 0) {
@@ -2047,20 +2048,22 @@ custom_mutator_stage:
   afl->queue_cur->stats_mutated += afl->stage_max;
 #endif
 
-  if (likely(afl->custom_only)) {
+  /****************
+   * RANDOM HAVOC *
+   ****************/
+
+havoc_stage:
+
+  if (unlikely(afl->custom_only)) {
 
+    /* Force UI update */
+    show_stats(afl);
     /* Skip other stages */
     ret_val = 0;
     goto abandon_entry;
 
   }
 
-  /****************
-   * RANDOM HAVOC *
-   ****************/
-
-havoc_stage:
-
   afl->stage_cur_byte = -1;
 
   /* The havoc stage mutation code is also invoked when splicing files; if the
@@ -3570,6 +3573,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
 
   eff_map = afl_realloc(AFL_BUF_PARAM(eff), EFF_ALEN(len));
   if (unlikely(!eff_map)) { PFATAL("alloc"); }
+  memset(eff_map, 0, EFF_ALEN(len));
   eff_map[0] = 1;
 
   if (EFF_APOS(len - 1) != 0) {
diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c
index 8ad7cd97..b10bf749 100644
--- a/src/afl-fuzz-queue.c
+++ b/src/afl-fuzz-queue.c
@@ -49,11 +49,13 @@ inline u32 select_next_queue_entry(afl_state_t *afl) {
 
   u32    s = rand_below(afl, afl->queued_items);
   double p = rand_next_percent(afl);
+
   /*
   fprintf(stderr, "select: p=%f s=%u ... p < prob[s]=%f ? s=%u : alias[%u]=%u"
   " ==> %u\n", p, s, afl->alias_probability[s], s, s, afl->alias_table[s], p <
   afl->alias_probability[s] ? s : afl->alias_table[s]);
   */
+
   return (p < afl->alias_probability[s] ? s : afl->alias_table[s]);
 
 }
@@ -87,25 +89,28 @@ double compute_weight(afl_state_t *afl, struct queue_entry *q,
 
 void create_alias_table(afl_state_t *afl) {
 
-  u32    n = afl->queued_items, i = 0, a, g;
+  u32    n = afl->queued_items, i = 0, nSmall = 0, nLarge = n - 1;
   double sum = 0;
 
+  double *P = (double *)afl_realloc(AFL_BUF_PARAM(out), n * sizeof(double));
+  u32 *Small = (int *)afl_realloc(AFL_BUF_PARAM(out_scratch), n * sizeof(u32));
+  u32 *Large = (int *)afl_realloc(AFL_BUF_PARAM(in_scratch), n * sizeof(u32));
+
   afl->alias_table =
       (u32 *)afl_realloc((void **)&afl->alias_table, n * sizeof(u32));
   afl->alias_probability = (double *)afl_realloc(
       (void **)&afl->alias_probability, n * sizeof(double));
-  double *P = (double *)afl_realloc(AFL_BUF_PARAM(out), n * sizeof(double));
-  int    *S = (int *)afl_realloc(AFL_BUF_PARAM(out_scratch), n * sizeof(u32));
-  int    *L = (int *)afl_realloc(AFL_BUF_PARAM(in_scratch), n * sizeof(u32));
 
-  if (!P || !S || !L || !afl->alias_table || !afl->alias_probability) {
+  if (!P || !Small || !Large || !afl->alias_table || !afl->alias_probability) {
 
     FATAL("could not acquire memory for alias table");
 
   }
 
-  memset((void *)afl->alias_table, 0, n * sizeof(u32));
   memset((void *)afl->alias_probability, 0, n * sizeof(double));
+  memset((void *)afl->alias_table, 0, n * sizeof(u32));
+  memset((void *)Small, 0, n * sizeof(u32));
+  memset((void *)Large, 0, n * sizeof(u32));
 
   if (likely(afl->schedule < RARE)) {
 
@@ -166,7 +171,15 @@ void create_alias_table(afl_state_t *afl) {
     for (i = 0; i < n; i++) {
 
       // weight is always 0 for disabled entries
-      P[i] = (afl->queue_buf[i]->weight * n) / sum;
+      if (unlikely(afl->queue_buf[i]->disabled)) {
+
+        P[i] = 0;
+
+      } else {
+
+        P[i] = (afl->queue_buf[i]->weight * n) / sum;
+
+      }
 
     }
 
@@ -176,60 +189,81 @@ void create_alias_table(afl_state_t *afl) {
 
       struct queue_entry *q = afl->queue_buf[i];
 
-      if (likely(!q->disabled)) { q->perf_score = calculate_score(afl, q); }
+      if (likely(!q->disabled)) {
+
+        q->perf_score = calculate_score(afl, q);
+        sum += q->perf_score;
 
-      sum += q->perf_score;
+      }
 
     }
 
     for (i = 0; i < n; i++) {
 
       // perf_score is always 0 for disabled entries
-      P[i] = (afl->queue_buf[i]->perf_score * n) / sum;
+      if (unlikely(afl->queue_buf[i]->disabled)) {
+
+        P[i] = 0;
+
+      } else {
+
+        P[i] = (afl->queue_buf[i]->perf_score * n) / sum;
+
+      }
 
     }
 
   }
 
-  int nS = 0, nL = 0, s;
-  for (s = (s32)n - 1; s >= 0; --s) {
+  // Done collecting weightings in P, now create the arrays.
+
+  for (s32 j = (s32)(n - 1); j >= 0; j--) {
 
-    if (P[s] < 1) {
+    if (P[j] < 1) {
 
-      S[nS++] = s;
+      Small[nSmall++] = (u32)j;
 
     } else {
 
-      L[nL++] = s;
+      Large[nLarge--] = (u32)j;
 
     }
 
   }
 
-  while (nS && nL) {
+  while (nSmall && nLarge != n - 1) {
+
+    u32 small = Small[--nSmall];
+    u32 large = Large[++nLarge];
+
+    afl->alias_probability[small] = P[small];
+    afl->alias_table[small] = large;
 
-    a = S[--nS];
-    g = L[--nL];
-    afl->alias_probability[a] = P[a];
-    afl->alias_table[a] = g;
-    P[g] = P[g] + P[a] - 1;
-    if (P[g] < 1) {
+    P[large] = P[large] - (1 - P[small]);
 
-      S[nS++] = g;
+    if (P[large] < 1) {
+
+      Small[nSmall++] = large;
 
     } else {
 
-      L[nL++] = g;
+      Large[nLarge--] = large;
 
     }
 
   }
 
-  while (nL)
-    afl->alias_probability[L[--nL]] = 1;
+  while (nSmall) {
+
+    afl->alias_probability[Small[--nSmall]] = 1;
+
+  }
 
-  while (nS)
-    afl->alias_probability[S[--nS]] = 1;
+  while (nLarge != n - 1) {
+
+    afl->alias_probability[Large[++nLarge]] = 1;
+
+  }
 
   afl->reinit_table = 0;
 
@@ -264,7 +298,7 @@ void create_alias_table(afl_state_t *afl) {
   */
   /*
   fprintf(stderr, "  entry  alias  probability  perf_score   weight
-  filename\n"); for (u32 i = 0; i < n; ++i) fprintf(stderr, "  %5u  %5u  %11u
+  filename\n"); for (i = 0; i < n; ++i) fprintf(stderr, "  %5u  %5u  %11u
   %0.9f  %0.9f  %s\n", i, afl->alias_table[i], afl->alias_probability[i],
   afl->queue_buf[i]->perf_score, afl->queue_buf[i]->weight,
             afl->queue_buf[i]->fname);
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index 71d2afd8..4339ddd2 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -124,7 +124,8 @@ static void usage(u8 *argv0, int more_help) {
       "\n%s [ options ] -- /path/to/fuzzed_app [ ... ]\n\n"
 
       "Required parameters:\n"
-      "  -i dir        - input directory with test cases\n"
+      "  -i dir        - input directory with test cases (or '-' to resume, "
+      "also see AFL_AUTORESUME)\n"
       "  -o dir        - output directory for fuzzer findings\n\n"
 
       "Execution control settings:\n"
@@ -1280,16 +1281,16 @@ int main(int argc, char **argv_orig, char **envp) {
 
   if (afl->fsrv.mem_limit && afl->shm.cmplog_mode) afl->fsrv.mem_limit += 260;
 
-  OKF("afl++ is maintained by Marc \"van Hauser\" Heuse, Heiko \"hexcoder\" "
-      "Eißfeldt, Andrea Fioraldi and Dominik Maier");
-  OKF("afl++ is open source, get it at "
+  OKF("AFL++ is maintained by Marc \"van Hauser\" Heuse, Dominik Maier, Andrea "
+      "Fioraldi and Heiko \"hexcoder\" Eißfeldt");
+  OKF("AFL++ is open source, get it at "
       "https://github.com/AFLplusplus/AFLplusplus");
-  OKF("NOTE: afl++ >= v3 has changed defaults and behaviours - see README.md");
+  OKF("NOTE: AFL++ >= v3 has changed defaults and behaviours - see README.md");
 
   #ifdef __linux__
   if (afl->fsrv.nyx_mode) {
 
-    OKF("afl++ Nyx mode is enabled (developed and mainted by Sergej Schumilo)");
+    OKF("AFL++ Nyx mode is enabled (developed and mainted by Sergej Schumilo)");
     OKF("Nyx is open source, get it at https://github.com/Nyx-Fuzz");
 
   }
@@ -1529,29 +1530,6 @@ int main(int argc, char **argv_orig, char **envp) {
 
   }
 
-  if (afl->limit_time_sig > 0 && afl->custom_mutators_count) {
-
-    if (afl->custom_only) {
-
-      FATAL("Custom mutators are incompatible with MOpt (-L)");
-
-    }
-
-    u32 custom_fuzz = 0;
-    LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
-
-      if (el->afl_custom_fuzz) { custom_fuzz = 1; }
-
-    });
-
-    if (custom_fuzz) {
-
-      WARNF("afl_custom_fuzz is incompatible with MOpt (-L)");
-
-    }
-
-  }
-
   if (afl->afl_env.afl_max_det_extras) {
 
     s32 max_det_extras = atoi(afl->afl_env.afl_max_det_extras);
@@ -1826,8 +1804,76 @@ int main(int argc, char **argv_orig, char **envp) {
     printf("DEBUG: rand %06d is %u\n", counter, rand_below(afl, 65536));
   #endif
 
+  if (!getenv("AFL_CUSTOM_INFO_PROGRAM")) {
+
+    setenv("AFL_CUSTOM_INFO_PROGRAM", argv[optind], 1);
+
+  }
+
+  if (!getenv("AFL_CUSTOM_INFO_PROGRAM_INPUT") && afl->fsrv.out_file) {
+
+    setenv("AFL_CUSTOM_INFO_PROGRAM_INPUT", afl->fsrv.out_file, 1);
+
+  }
+
+  {
+
+    u8 envbuf[8096] = "", tmpbuf[8096] = "";
+    for (s32 i = optind + 1; i < argc; ++i) {
+
+      strcpy(tmpbuf, envbuf);
+      if (strchr(argv[i], ' ') && !strchr(argv[i], '"') &&
+          !strchr(argv[i], '\'')) {
+
+        if (!strchr(argv[i], '\'')) {
+
+          snprintf(envbuf, sizeof(tmpbuf), "%s '%s'", tmpbuf, argv[i]);
+
+        } else {
+
+          snprintf(envbuf, sizeof(tmpbuf), "%s \"%s\"", tmpbuf, argv[i]);
+
+        }
+
+      } else {
+
+        snprintf(envbuf, sizeof(tmpbuf), "%s %s", tmpbuf, argv[i]);
+
+      }
+
+    }
+
+    setenv("AFL_CUSTOM_INFO_PROGRAM_ARGV", envbuf + 1, 1);
+
+  }
+
+  setenv("AFL_CUSTOM_INFO_OUT", afl->out_dir, 1);  // same as __AFL_OUT_DIR
+
   setup_custom_mutators(afl);
 
+  if (afl->limit_time_sig > 0 && afl->custom_mutators_count) {
+
+    if (afl->custom_only) {
+
+      FATAL("Custom mutators are incompatible with MOpt (-L)");
+
+    }
+
+    u32 custom_fuzz = 0;
+    LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
+
+      if (el->afl_custom_fuzz) { custom_fuzz = 1; }
+
+    });
+
+    if (custom_fuzz) {
+
+      WARNF("afl_custom_fuzz is incompatible with MOpt (-L)");
+
+    }
+
+  }
+
   write_setup_file(afl, argc, argv);
 
   setup_cmdline_file(afl, argv + optind);
@@ -1979,6 +2025,7 @@ int main(int argc, char **argv_orig, char **envp) {
   if (afl->non_instrumented_mode || afl->fsrv.qemu_mode ||
       afl->fsrv.frida_mode || afl->fsrv.cs_mode || afl->unicorn_mode) {
 
+    u32 old_map_size = map_size;
     map_size = afl->fsrv.real_map_size = afl->fsrv.map_size = MAP_SIZE;
     afl->virgin_bits = ck_realloc(afl->virgin_bits, map_size);
     afl->virgin_tmout = ck_realloc(afl->virgin_tmout, map_size);
@@ -1990,6 +2037,18 @@ int main(int argc, char **argv_orig, char **envp) {
     afl->first_trace = ck_realloc(afl->first_trace, map_size);
     afl->map_tmp_buf = ck_realloc(afl->map_tmp_buf, map_size);
 
+    if (old_map_size < map_size) {
+
+      memset(afl->var_bytes + old_map_size, 0, map_size - old_map_size);
+      memset(afl->top_rated + old_map_size, 0, map_size - old_map_size);
+      memset(afl->clean_trace + old_map_size, 0, map_size - old_map_size);
+      memset(afl->clean_trace_custom + old_map_size, 0,
+             map_size - old_map_size);
+      memset(afl->first_trace + old_map_size, 0, map_size - old_map_size);
+      memset(afl->map_tmp_buf + old_map_size, 0, map_size - old_map_size);
+
+    }
+
   }
 
   afl->argv = use_argv;
@@ -2017,6 +2076,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
       OKF("Re-initializing maps to %u bytes", new_map_size);
 
+      u32 old_map_size = map_size;
       afl->virgin_bits = ck_realloc(afl->virgin_bits, new_map_size);
       afl->virgin_tmout = ck_realloc(afl->virgin_tmout, new_map_size);
       afl->virgin_crash = ck_realloc(afl->virgin_crash, new_map_size);
@@ -2029,6 +2089,18 @@ int main(int argc, char **argv_orig, char **envp) {
       afl->first_trace = ck_realloc(afl->first_trace, new_map_size);
       afl->map_tmp_buf = ck_realloc(afl->map_tmp_buf, new_map_size);
 
+      if (old_map_size < new_map_size) {
+
+        memset(afl->var_bytes + old_map_size, 0, new_map_size - old_map_size);
+        memset(afl->top_rated + old_map_size, 0, new_map_size - old_map_size);
+        memset(afl->clean_trace + old_map_size, 0, new_map_size - old_map_size);
+        memset(afl->clean_trace_custom + old_map_size, 0,
+               new_map_size - old_map_size);
+        memset(afl->first_trace + old_map_size, 0, new_map_size - old_map_size);
+        memset(afl->map_tmp_buf + old_map_size, 0, new_map_size - old_map_size);
+
+      }
+
       afl_fsrv_kill(&afl->fsrv);
       afl_shm_deinit(&afl->shm);
       afl->fsrv.map_size = new_map_size;
@@ -2079,6 +2151,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
       OKF("Re-initializing maps to %u bytes due cmplog", new_map_size);
 
+      u32 old_map_size = map_size;
       afl->virgin_bits = ck_realloc(afl->virgin_bits, new_map_size);
       afl->virgin_tmout = ck_realloc(afl->virgin_tmout, new_map_size);
       afl->virgin_crash = ck_realloc(afl->virgin_crash, new_map_size);
@@ -2091,6 +2164,18 @@ int main(int argc, char **argv_orig, char **envp) {
       afl->first_trace = ck_realloc(afl->first_trace, new_map_size);
       afl->map_tmp_buf = ck_realloc(afl->map_tmp_buf, new_map_size);
 
+      if (old_map_size < new_map_size) {
+
+        memset(afl->var_bytes + old_map_size, 0, new_map_size - old_map_size);
+        memset(afl->top_rated + old_map_size, 0, new_map_size - old_map_size);
+        memset(afl->clean_trace + old_map_size, 0, new_map_size - old_map_size);
+        memset(afl->clean_trace_custom + old_map_size, 0,
+               new_map_size - old_map_size);
+        memset(afl->first_trace + old_map_size, 0, new_map_size - old_map_size);
+        memset(afl->map_tmp_buf + old_map_size, 0, new_map_size - old_map_size);
+
+      }
+
       afl_fsrv_kill(&afl->fsrv);
       afl_fsrv_kill(&afl->cmplog_fsrv);
       afl_shm_deinit(&afl->shm);
diff --git a/src/afl-ld-lto.c b/src/afl-ld-lto.c
index 5438bd9f..420dd817 100644
--- a/src/afl-ld-lto.c
+++ b/src/afl-ld-lto.c
@@ -2,7 +2,7 @@
   american fuzzy lop++ - wrapper for llvm 11+ lld
   -----------------------------------------------
 
-  Written by Marc Heuse <mh@mh-sec.de> for afl++
+  Written by Marc Heuse <mh@mh-sec.de> for AFL++
 
   Maintained by Marc Heuse <mh@mh-sec.de>,
                 Heiko Eißfeldt <heiko.eissfeldt@hexco.de>
@@ -210,7 +210,7 @@ static void edit_params(int argc, char **argv) {
 
     if (strcmp(argv[i], "--afl") == 0) {
 
-      if (!be_quiet) OKF("afl++ test command line flag detected, exiting.");
+      if (!be_quiet) OKF("AFL++ test command line flag detected, exiting.");
       exit(0);
 
     }
diff --git a/src/afl-showmap.c b/src/afl-showmap.c
index d0e01cb1..9c029035 100644
--- a/src/afl-showmap.c
+++ b/src/afl-showmap.c
@@ -1287,7 +1287,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
         break;
 
-      case 'Y':  // fallthough
+      case 'Y':  // fallthrough
 #ifdef __linux__
       case 'X':                                                 /* NYX mode */
 
@@ -1421,6 +1421,14 @@ int main(int argc, char **argv_orig, char **envp) {
     // If @@ are in the target args, replace them and also set use_stdin=false.
     detect_file_args(argv + optind, stdin_file, &fsrv->use_stdin);
 
+    fsrv->dev_null_fd = open("/dev/null", O_RDWR);
+    if (fsrv->dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); }
+
+    fsrv->out_file = stdin_file;
+    fsrv->out_fd =
+        open(stdin_file, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
+    if (fsrv->out_fd < 0) { PFATAL("Unable to create '%s'", stdin_file); }
+
   } else {
 
     // If @@ are in the target args, replace them and also set use_stdin=false.
@@ -1588,6 +1596,14 @@ int main(int argc, char **argv_orig, char **envp) {
 
     fsrv->map_size = map_size;
 
+  } else {
+
+    afl_fsrv_start(fsrv, use_argv, &stop_soon,
+                   (get_afl_env("AFL_DEBUG_CHILD") ||
+                    get_afl_env("AFL_DEBUG_CHILD_OUTPUT"))
+                       ? 1
+                       : 0);
+
   }
 
   if (in_dir || in_filelist) {
@@ -1617,9 +1633,6 @@ int main(int argc, char **argv_orig, char **envp) {
 
     if (getenv("AFL_DEBUG_GDB")) wait_for_gdb = true;
 
-    fsrv->dev_null_fd = open("/dev/null", O_RDWR);
-    if (fsrv->dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); }
-
     if (in_filelist) {
 
       if (!be_quiet) ACTF("Reading from file list '%s'...", in_filelist);
@@ -1666,10 +1679,6 @@ int main(int argc, char **argv_orig, char **envp) {
     }
 
     atexit(at_exit_handler);
-    fsrv->out_file = stdin_file;
-    fsrv->out_fd =
-        open(stdin_file, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
-    if (fsrv->out_fd < 0) { PFATAL("Unable to create '%s'", out_file); }
 
     if (get_afl_env("AFL_DEBUG")) {
 
@@ -1685,12 +1694,6 @@ int main(int argc, char **argv_orig, char **envp) {
 
     }
 
-    afl_fsrv_start(fsrv, use_argv, &stop_soon,
-                   (get_afl_env("AFL_DEBUG_CHILD") ||
-                    get_afl_env("AFL_DEBUG_CHILD_OUTPUT"))
-                       ? 1
-                       : 0);
-
     map_size = fsrv->map_size;
 
     if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)