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.c25
-rw-r--r--src/afl-cc.c16
-rw-r--r--src/afl-common.c60
-rw-r--r--src/afl-forkserver.c32
-rw-r--r--src/afl-fuzz-init.c133
-rw-r--r--src/afl-fuzz-one.c8
-rw-r--r--src/afl-fuzz-queue.c39
-rw-r--r--src/afl-fuzz-redqueen.c140
-rw-r--r--src/afl-fuzz-state.c7
-rw-r--r--src/afl-fuzz-stats.c10
-rw-r--r--src/afl-fuzz.c171
-rw-r--r--src/afl-sharedmem.c14
-rw-r--r--src/afl-showmap.c66
-rw-r--r--src/afl-tmin.c62
14 files changed, 541 insertions, 242 deletions
diff --git a/src/afl-analyze.c b/src/afl-analyze.c
index 0af489fe..20aef2da 100644
--- a/src/afl-analyze.c
+++ b/src/afl-analyze.c
@@ -1078,6 +1078,31 @@ int main(int argc, char **argv_orig, char **envp) {
 
   if (optind == argc || !in_file) { usage(argv[0]); }
 
+  if (qemu_mode && getenv("AFL_USE_QASAN")) {
+
+    u8 *preload = getenv("AFL_PRELOAD");
+    u8 *libqasan = get_libqasan_path(argv_orig[0]);
+
+    if (!preload) {
+
+      setenv("AFL_PRELOAD", libqasan, 0);
+
+    } else {
+
+      u8 *result = ck_alloc(strlen(libqasan) + strlen(preload) + 2);
+      strcpy(result, libqasan);
+      strcat(result, " ");
+      strcat(result, preload);
+
+      setenv("AFL_PRELOAD", result, 1);
+      ck_free(result);
+
+    }
+
+    ck_free(libqasan);
+
+  }
+
   map_size = get_map_size();
 
   use_hex_offsets = !!get_afl_env("AFL_ANALYZE_HEX");
diff --git a/src/afl-cc.c b/src/afl-cc.c
index b5dcb632..f513764a 100644
--- a/src/afl-cc.c
+++ b/src/afl-cc.c
@@ -572,7 +572,8 @@ static void edit_params(u32 argc, char **argv, char **envp) {
 
       cc_params[cc_par_cnt++] = "-Wl,--allow-multiple-definition";
 
-      if (instrument_mode == INSTRUMENT_CFG)
+      if (instrument_mode == INSTRUMENT_CFG ||
+          instrument_mode == INSTRUMENT_PCGUARD)
         cc_params[cc_par_cnt++] = alloc_printf(
             "-Wl,-mllvm=-load=%s/SanitizerCoverageLTO.so", obj_path);
       else
@@ -1670,15 +1671,16 @@ int main(int argc, char **argv, char **envp) {
   if (compiler_mode == LTO) {
 
     if (instrument_mode == 0 || instrument_mode == INSTRUMENT_LTO ||
-        instrument_mode == INSTRUMENT_CFG) {
+        instrument_mode == INSTRUMENT_CFG ||
+        instrument_mode == INSTRUMENT_PCGUARD) {
 
       lto_mode = 1;
-      if (!instrument_mode) {
+      // force CFG
+      // if (!instrument_mode) {
 
-        instrument_mode = INSTRUMENT_CFG;
-        // ptr = instrument_mode_string[instrument_mode];
-
-      }
+      instrument_mode = INSTRUMENT_PCGUARD;
+      // ptr = instrument_mode_string[instrument_mode];
+      // }
 
     } else if (instrument_mode == INSTRUMENT_LTO ||
 
diff --git a/src/afl-common.c b/src/afl-common.c
index cf996548..235c4c05 100644
--- a/src/afl-common.c
+++ b/src/afl-common.c
@@ -334,6 +334,66 @@ char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
 
 }
 
+/* Get libqasan path. */
+
+u8 *get_libqasan_path(u8 *own_loc) {
+
+  if (!unlikely(own_loc)) { FATAL("BUG: param own_loc is NULL"); }
+
+  u8 *tmp, *cp = NULL, *rsl, *own_copy;
+
+  tmp = getenv("AFL_PATH");
+
+  if (tmp) {
+
+    cp = alloc_printf("%s/libqasan.so", tmp);
+
+    if (access(cp, X_OK)) { FATAL("Unable to find '%s'", tmp); }
+
+    return cp;
+
+  }
+
+  own_copy = ck_strdup(own_loc);
+  rsl = strrchr(own_copy, '/');
+
+  if (rsl) {
+
+    *rsl = 0;
+
+    cp = alloc_printf("%s/libqasan.so", own_copy);
+    ck_free(own_copy);
+
+    if (!access(cp, X_OK)) { return cp; }
+
+  } else {
+
+    ck_free(own_copy);
+
+  }
+
+  if (!access(BIN_PATH "/libqasan.so", X_OK)) {
+
+    if (cp) { ck_free(cp); }
+
+    return ck_strdup(BIN_PATH "/libqasan.so");
+
+  }
+
+  SAYF("\n" cLRD "[-] " cRST
+       "Oops, unable to find the 'libqasan.so' binary. The binary must be "
+       "built\n"
+       "    separately by following the instructions in "
+       "qemu_mode/libqasan/README.md. "
+       "If you\n"
+       "    already have the binary installed, you may need to specify "
+       "AFL_PATH in the\n"
+       "    environment.\n");
+
+  FATAL("Failed to locate 'libqasan.so'.");
+
+}
+
 /* Find binary, used by analyze, showmap, tmin
    @returns the path, allocating the string */
 
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index 1f5685b0..9ee59822 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -515,6 +515,10 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
              "handle_sigill=0",
              0);
 
+    /* Envs for QASan */
+    setenv("QASAN_MAX_CALL_STACK", "0", 0);
+    setenv("QASAN_SYMBOLIZE", "0", 0);
+
     /* MSAN is tricky, because it doesn't support abort_on_error=1 at this
        point. So, we do this in a very hacky way. */
 
@@ -678,11 +682,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
 
       if ((status & FS_OPT_AUTODICT) == FS_OPT_AUTODICT) {
 
-        if (ignore_autodict) {
-
-          if (!be_quiet) { WARNF("Ignoring offered AUTODICT feature."); }
-
-        } else {
+        if (!ignore_autodict) {
 
           if (fsrv->add_extra_func == NULL || fsrv->afl_ptr == NULL) {
 
@@ -965,7 +965,9 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
 
 }
 
-static void afl_fsrv_kill(afl_forkserver_t *fsrv) {
+/* Stop the forkserver and child */
+
+void afl_fsrv_kill(afl_forkserver_t *fsrv) {
 
   if (fsrv->child_pid > 0) { kill(fsrv->child_pid, fsrv->kill_signal); }
   if (fsrv->fsrv_pid > 0) {
@@ -975,13 +977,28 @@ static void afl_fsrv_kill(afl_forkserver_t *fsrv) {
 
   }
 
+  close(fsrv->fsrv_ctl_fd);
+  close(fsrv->fsrv_st_fd);
+  fsrv->fsrv_pid = -1;
+  fsrv->child_pid = -1;
+
+}
+
+/* Get the map size from the target forkserver */
+
+u32 afl_fsrv_get_mapsize(afl_forkserver_t *fsrv, char **argv,
+                         volatile u8 *stop_soon_p, u8 debug_child_output) {
+
+  afl_fsrv_start(fsrv, argv, stop_soon_p, debug_child_output);
+  return fsrv->map_size;
+
 }
 
 /* Delete the current testcase and write the buf to the testcase file */
 
 void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) {
 
-  if (fsrv->shmem_fuzz) {
+  if (likely(fsrv->use_shmem_fuzz && fsrv->shmem_fuzz)) {
 
     if (unlikely(len > MAX_FILE)) len = MAX_FILE;
 
@@ -1038,6 +1055,7 @@ void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) {
 
     }
 
+    // fprintf(stderr, "WRITE %d %u\n", fd, len);
     ck_write(fd, buf, len, fsrv->out_file);
 
     if (fsrv->use_stdin) {
diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c
index 84f81112..40ba20c7 100644
--- a/src/afl-fuzz-init.c
+++ b/src/afl-fuzz-init.c
@@ -25,6 +25,7 @@
 
 #include "afl-fuzz.h"
 #include <limits.h>
+#include "cmplog.h"
 
 #ifdef HAVE_AFFINITY
 
@@ -468,7 +469,7 @@ void read_foreign_testcases(afl_state_t *afl, int first) {
         afl->foreign_syncs[iter].dir[0] != 0) {
 
       if (first) ACTF("Scanning '%s'...", afl->foreign_syncs[iter].dir);
-      time_t ctime_max = 0;
+      time_t mtime_max = 0;
       u8 *   name = strrchr(afl->foreign_syncs[iter].dir, '/');
       if (!name) { name = afl->foreign_syncs[iter].dir; }
       if (!strcmp(name, "queue") || !strcmp(name, "out") ||
@@ -482,8 +483,8 @@ void read_foreign_testcases(afl_state_t *afl, int first) {
 
       }
 
-      /* We do not use sorting yet and do a more expensive ctime check instead.
-         a ctimesort() implementation would be better though. */
+      /* We do not use sorting yet and do a more expensive mtime check instead.
+         a mtimesort() implementation would be better though. */
 
       nl_cnt = scandir(afl->foreign_syncs[iter].dir, &nl, NULL, NULL);
 
@@ -537,8 +538,8 @@ void read_foreign_testcases(afl_state_t *afl, int first) {
 
         }
 
-        /* we detect new files by their ctime */
-        if (likely(st.st_ctime <= afl->foreign_syncs[iter].ctime)) {
+        /* we detect new files by their mtime */
+        if (likely(st.st_mtime <= afl->foreign_syncs[iter].mtime)) {
 
           ck_free(fn2);
           continue;
@@ -600,11 +601,11 @@ void read_foreign_testcases(afl_state_t *afl, int first) {
         munmap(mem, st.st_size);
         close(fd);
 
-        if (st.st_ctime > ctime_max) ctime_max = st.st_ctime;
+        if (st.st_mtime > mtime_max) mtime_max = st.st_mtime;
 
       }
 
-      afl->foreign_syncs[iter].ctime = ctime_max;
+      afl->foreign_syncs[iter].mtime = mtime_max;
       free(nl);                                              /* not tracked */
 
     }
@@ -765,13 +766,16 @@ void read_testcases(afl_state_t *afl, u8 *directory) {
 
     }
 
-    if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) {
+    /*
+        if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) {
 
-      u64 cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
-      afl->queue_top->n_fuzz_entry = cksum % N_FUZZ_SIZE;
-      afl->n_fuzz[afl->queue_top->n_fuzz_entry] = 1;
+          u64 cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size,
+       HASH_CONST); afl->queue_top->n_fuzz_entry = cksum % N_FUZZ_SIZE;
+          afl->n_fuzz[afl->queue_top->n_fuzz_entry] = 1;
 
-    }
+        }
+
+    */
 
   }
 
@@ -816,12 +820,15 @@ void read_testcases(afl_state_t *afl, u8 *directory) {
 
 void perform_dry_run(afl_state_t *afl) {
 
-  struct queue_entry *q = afl->queue;
-  u32                 cal_failures = 0;
+  struct queue_entry *q;
+  u32                 cal_failures = 0, idx;
   u8 *                skip_crashes = afl->afl_env.afl_skip_crashes;
   u8 *                use_mem;
 
-  while (q) {
+  for (idx = 0; idx < afl->queued_paths; idx++) {
+
+    q = afl->queue_buf[idx];
+    if (unlikely(q->disabled)) { continue; }
 
     u8  res;
     s32 fd;
@@ -833,6 +840,8 @@ void perform_dry_run(afl_state_t *afl) {
 
     }
 
+    if (afl->afl_env.afl_cmplog_only_new) { q->colorized = CMPLOG_LVL_MAX; }
+
     u8 *fn = strrchr(q->fname, '/') + 1;
 
     ACTF("Attempting dry run with '%s'...", fn);
@@ -1049,20 +1058,22 @@ void perform_dry_run(afl_state_t *afl) {
 
         p->disabled = 1;
         p->perf_score = 0;
-        while (p && p->next != q)
-          p = p->next;
 
-        if (p)
-          p->next = q->next;
-        else
-          afl->queue = q->next;
+        u32 i = 0;
+        while (unlikely(afl->queue_buf[i]->disabled)) {
+
+          ++i;
+
+        }
+
+        afl->queue = afl->queue_buf[i];
 
         afl->max_depth = 0;
-        p = afl->queue;
-        while (p) {
+        for (i = 0; i < afl->queued_paths; i++) {
 
-          if (p->depth > afl->max_depth) afl->max_depth = p->depth;
-          p = p->next;
+          if (!afl->queue_buf[i]->disabled &&
+              afl->queue_buf[i]->depth > afl->max_depth)
+            afl->max_depth = afl->queue_buf[i]->depth;
 
         }
 
@@ -1095,8 +1106,6 @@ void perform_dry_run(afl_state_t *afl) {
 
     }
 
-    q = q->next;
-
   }
 
   if (cal_failures) {
@@ -1122,31 +1131,23 @@ void perform_dry_run(afl_state_t *afl) {
 
   /* Now we remove all entries from the queue that have a duplicate trace map */
 
-  q = afl->queue;
-  struct queue_entry *p, *prev = NULL;
-  int                 duplicates = 0;
-
-restart_outer_cull_loop:
+  u32 duplicates = 0, i;
 
-  while (q) {
+  for (idx = 0; idx < afl->queued_paths; idx++) {
 
-    if (q->cal_failed || !q->exec_cksum) { goto next_entry; }
+    q = afl->queue_buf[idx];
+    if (q->disabled || q->cal_failed || !q->exec_cksum) { continue; }
 
-  restart_inner_cull_loop:
+    u32 done = 0;
+    for (i = idx + 1; i < afl->queued_paths && !done; i++) {
 
-    p = q->next;
+      struct queue_entry *p = afl->queue_buf[i];
+      if (p->disabled || p->cal_failed || !p->exec_cksum) { continue; }
 
-    while (p) {
-
-      if (!p->cal_failed && p->exec_cksum == q->exec_cksum) {
+      if (p->exec_cksum == q->exec_cksum) {
 
         duplicates = 1;
 
-        // We do not remove any of the memory allocated because for
-        // splicing the data might still be interesting.
-        // We only decouple them from the linked list.
-        // This will result in some leaks at exit, but who cares.
-
         // we keep the shorter file
         if (p->len >= q->len) {
 
@@ -1160,8 +1161,6 @@ restart_outer_cull_loop:
 
           p->disabled = 1;
           p->perf_score = 0;
-          q->next = p->next;
-          goto restart_inner_cull_loop;
 
         } else {
 
@@ -1175,35 +1174,26 @@ restart_outer_cull_loop:
 
           q->disabled = 1;
           q->perf_score = 0;
-          if (prev)
-            prev->next = q = p;
-          else
-            afl->queue = q = p;
-          goto restart_outer_cull_loop;
+
+          done = 1;
 
         }
 
       }
 
-      p = p->next;
-
     }
 
-  next_entry:
-
-    prev = q;
-    q = q->next;
-
   }
 
   if (duplicates) {
 
     afl->max_depth = 0;
-    q = afl->queue;
-    while (q) {
 
-      if (q->depth > afl->max_depth) afl->max_depth = q->depth;
-      q = q->next;
+    for (idx = 0; idx < afl->queued_paths; idx++) {
+
+      if (!afl->queue_buf[idx]->disabled &&
+          afl->queue_buf[idx]->depth > afl->max_depth)
+        afl->max_depth = afl->queue_buf[idx]->depth;
 
     }
 
@@ -1253,11 +1243,15 @@ static void link_or_copy(u8 *old_path, u8 *new_path) {
 void pivot_inputs(afl_state_t *afl) {
 
   struct queue_entry *q = afl->queue;
-  u32                 id = 0;
+  u32                 id = 0, i;
 
   ACTF("Creating hard links for all input files...");
 
-  while (q) {
+  for (i = 0; i < afl->queued_paths; i++) {
+
+    q = afl->queue_buf[i];
+
+    if (unlikely(q->disabled)) { continue; }
 
     u8 *nfn, *rsl = strrchr(q->fname, '/');
     u32 orig_id;
@@ -1285,19 +1279,14 @@ void pivot_inputs(afl_state_t *afl) {
       afl->resuming_fuzz = 1;
       nfn = alloc_printf("%s/queue/%s", afl->out_dir, rsl);
 
-      /* Since we're at it, let's also try to find parent and figure out the
+      /* Since we're at it, let's also get the parent and figure out the
          appropriate depth for this entry. */
 
       src_str = strchr(rsl + 3, ':');
 
       if (src_str && sscanf(src_str + 1, "%06u", &src_id) == 1) {
 
-        struct queue_entry *s = afl->queue;
-        while (src_id-- && s) {
-
-          s = s->next;
-
-        }
+        struct queue_entry *s = afl->queue_buf[src_id];
 
         if (s) { q->depth = s->depth + 1; }
 
@@ -1345,7 +1334,6 @@ void pivot_inputs(afl_state_t *afl) {
 
     if (q->passed_det) { mark_as_det_done(afl, q); }
 
-    q = q->next;
     ++id;
 
   }
@@ -2505,6 +2493,7 @@ void setup_testcase_shmem(afl_state_t *afl) {
 
   // we need to set the non-instrumented mode to not overwrite the SHM_ENV_VAR
   u8 *map = afl_shm_init(afl->shm_fuzz, MAX_FILE + sizeof(u32), 1);
+  afl->shm_fuzz->shmemfuzz_mode = 1;
 
   if (!map) { FATAL("BUG: Zero return from afl_shm_init."); }
 
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index ff766158..18291fb7 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -26,6 +26,7 @@
 #include "afl-fuzz.h"
 #include <string.h>
 #include <limits.h>
+#include "cmplog.h"
 
 /* MOpt */
 
@@ -543,7 +544,8 @@ u8 fuzz_one_original(afl_state_t *afl) {
   if (likely(!afl->old_seed_selection))
     orig_perf = perf_score = afl->queue_cur->perf_score;
   else
-    orig_perf = perf_score = calculate_score(afl, afl->queue_cur);
+    afl->queue_cur->perf_score = orig_perf = perf_score =
+        calculate_score(afl, afl->queue_cur);
 
   if (unlikely(perf_score <= 0)) { goto abandon_entry; }
 
@@ -553,7 +555,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
 
     if (unlikely(len < 4)) {
 
-      afl->queue_cur->colorized = 0xff;
+      afl->queue_cur->colorized = CMPLOG_LVL_MAX;
 
     } else {
 
@@ -2981,7 +2983,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
 
     if (unlikely(len < 4)) {
 
-      afl->queue_cur->colorized = 0xff;
+      afl->queue_cur->colorized = CMPLOG_LVL_MAX;
 
     } else {
 
diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c
index 4442b400..ad3e3b8e 100644
--- a/src/afl-fuzz-queue.c
+++ b/src/afl-fuzz-queue.c
@@ -143,7 +143,7 @@ void create_alias_table(afl_state_t *afl) {
 
       struct queue_entry *q = afl->queue_buf[i];
 
-      if (!q->disabled) { q->perf_score = calculate_score(afl, q); }
+      if (likely(!q->disabled)) { q->perf_score = calculate_score(afl, q); }
 
       sum += q->perf_score;
 
@@ -444,7 +444,6 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
 
   if (afl->queue_top) {
 
-    afl->queue_top->next = q;
     afl->queue_top = q;
 
   } else {
@@ -465,6 +464,7 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
       AFL_BUF_PARAM(queue), afl->queued_paths * sizeof(struct queue_entry *));
   if (unlikely(!queue_buf)) { PFATAL("alloc"); }
   queue_buf[afl->queued_paths - 1] = q;
+  q->id = afl->queued_paths - 1;
 
   afl->last_path_time = get_cur_time();
 
@@ -641,10 +641,9 @@ void cull_queue(afl_state_t *afl) {
 
   if (likely(!afl->score_changed || afl->non_instrumented_mode)) { return; }
 
-  struct queue_entry *q;
-  u32                 len = (afl->fsrv.map_size >> 3);
-  u32                 i;
-  u8 *                temp_v = afl->map_tmp_buf;
+  u32 len = (afl->fsrv.map_size >> 3);
+  u32 i;
+  u8 *temp_v = afl->map_tmp_buf;
 
   afl->score_changed = 0;
 
@@ -653,12 +652,9 @@ void cull_queue(afl_state_t *afl) {
   afl->queued_favored = 0;
   afl->pending_favored = 0;
 
-  q = afl->queue;
-
-  while (q) {
+  for (i = 0; i < afl->queued_paths; i++) {
 
-    q->favored = 0;
-    q = q->next;
+    afl->queue_buf[i]->favored = 0;
 
   }
 
@@ -697,12 +693,13 @@ void cull_queue(afl_state_t *afl) {
 
   }
 
-  q = afl->queue;
+  for (i = 0; i < afl->queued_paths; i++) {
+
+    if (likely(!afl->queue_buf[i]->disabled)) {
 
-  while (q) {
+      mark_as_redundant(afl, afl->queue_buf[i], !afl->queue_buf[i]->favored);
 
-    mark_as_redundant(afl, q, !q->favored);
-    q = q->next;
+    }
 
   }
 
@@ -852,13 +849,15 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) {
       // Don't modify perf_score for unfuzzed seeds
       if (q->fuzz_level == 0) break;
 
-      struct queue_entry *queue_it = afl->queue;
-      while (queue_it) {
+      u32 i;
+      for (i = 0; i < afl->queued_paths; i++) {
 
-        fuzz_mu += log2(afl->n_fuzz[q->n_fuzz_entry]);
-        n_paths++;
+        if (likely(!afl->queue_buf[i]->disabled)) {
 
-        queue_it = queue_it->next;
+          fuzz_mu += log2(afl->n_fuzz[afl->queue_buf[i]->n_fuzz_entry]);
+          n_paths++;
+
+        }
 
       }
 
diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c
index 67d505fc..74c9db38 100644
--- a/src/afl-fuzz-redqueen.c
+++ b/src/afl-fuzz-redqueen.c
@@ -1118,7 +1118,11 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
 #ifdef ARITHMETIC_LESSER_GREATER
   if (lvl < LVL3 || attr == IS_TRANSFORM) { return 0; }
 
-  if (!(attr & (IS_GREATER | IS_LESSER)) || SHAPE_BYTES(h->shape) < 4) { return 0; }
+  if (!(attr & (IS_GREATER | IS_LESSER)) || SHAPE_BYTES(h->shape) < 4) {
+
+    return 0;
+
+  }
 
   // transform >= to < and <= to >
   if ((attr & IS_EQUAL) && (attr & (IS_GREATER | IS_LESSER))) {
@@ -1138,110 +1142,110 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
   // lesser/greater FP comparison
   if (attr >= IS_FP && attr < IS_FP_MOD) {
 
-      u64 repl_new;
-
-      if (attr & IS_GREATER) {
+    u64 repl_new;
 
-        if (SHAPE_BYTES(h->shape) == 4 && its_len >= 4) {
+    if (attr & IS_GREATER) {
 
-          float *f = (float *)&repl;
-          float  g = *f;
-          g += 1.0;
-          u32 *r = (u32 *)&g;
-          repl_new = (u32)*r;
+      if (SHAPE_BYTES(h->shape) == 4 && its_len >= 4) {
 
-        } else if (SHAPE_BYTES(h->shape) == 8 && its_len >= 8) {
+        float *f = (float *)&repl;
+        float  g = *f;
+        g += 1.0;
+        u32 *r = (u32 *)&g;
+        repl_new = (u32)*r;
 
-          double *f = (double *)&repl;
-          double  g = *f;
-          g += 1.0;
+      } else if (SHAPE_BYTES(h->shape) == 8 && its_len >= 8) {
 
-          u64 *r = (u64 *)&g;
-          repl_new = *r;
+        double *f = (double *)&repl;
+        double  g = *f;
+        g += 1.0;
 
-        } else {
+        u64 *r = (u64 *)&g;
+        repl_new = *r;
 
-          return 0;
+      } else {
 
-        }
+        return 0;
 
-        changed_val = repl_new;
+      }
 
-        if (unlikely(cmp_extend_encoding(
-                afl, h, pattern, repl_new, o_pattern, changed_val, 16, idx,
-                taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) {
+      changed_val = repl_new;
 
-          return 1;
+      if (unlikely(cmp_extend_encoding(
+              afl, h, pattern, repl_new, o_pattern, changed_val, 16, idx,
+              taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) {
 
-        }
+        return 1;
 
-      } else {
+      }
 
-        if (SHAPE_BYTES(h->shape) == 4) {
+    } else {
 
-          float *f = (float *)&repl;
-          float  g = *f;
-          g -= 1.0;
-          u32 *r = (u32 *)&g;
-          repl_new = (u32)*r;
+      if (SHAPE_BYTES(h->shape) == 4) {
 
-        } else if (SHAPE_BYTES(h->shape) == 8) {
+        float *f = (float *)&repl;
+        float  g = *f;
+        g -= 1.0;
+        u32 *r = (u32 *)&g;
+        repl_new = (u32)*r;
 
-          double *f = (double *)&repl;
-          double  g = *f;
-          g -= 1.0;
-          u64 *r = (u64 *)&g;
-          repl_new = *r;
+      } else if (SHAPE_BYTES(h->shape) == 8) {
 
-        } else {
+        double *f = (double *)&repl;
+        double  g = *f;
+        g -= 1.0;
+        u64 *r = (u64 *)&g;
+        repl_new = *r;
 
-          return 0;
+      } else {
 
-        }
+        return 0;
 
-        changed_val = repl_new;
+      }
 
-        if (unlikely(cmp_extend_encoding(
-                afl, h, pattern, repl_new, o_pattern, changed_val, 16, idx,
-                taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) {
+      changed_val = repl_new;
 
-          return 1;
+      if (unlikely(cmp_extend_encoding(
+              afl, h, pattern, repl_new, o_pattern, changed_val, 16, idx,
+              taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) {
 
-        }
+        return 1;
 
       }
 
-      // transform double to float, llvm likes to do that internally ...
-      if (SHAPE_BYTES(h->shape) == 8 && its_len >= 4) {
+    }
+
+    // transform double to float, llvm likes to do that internally ...
+    if (SHAPE_BYTES(h->shape) == 8 && its_len >= 4) {
 
-        double *f = (double *)&repl;
-        float   g = (float)*f;
-        repl_new = 0;
+      double *f = (double *)&repl;
+      float   g = (float)*f;
+      repl_new = 0;
   #if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
-        memcpy((char *)&repl_new, (char *)&g, 4);
+      memcpy((char *)&repl_new, (char *)&g, 4);
   #else
-        memcpy(((char *)&repl_new) + 4, (char *)&g, 4);
+      memcpy(((char *)&repl_new) + 4, (char *)&g, 4);
   #endif
-        changed_val = repl_new;
-        h->shape = 3;  // modify shape
-
-        // fprintf(stderr, "DOUBLE2FLOAT %llx\n", repl_new);
-
-        if (unlikely(cmp_extend_encoding(
-                afl, h, pattern, repl_new, o_pattern, changed_val, 16, idx,
-                taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) {
+      changed_val = repl_new;
+      h->shape = 3;  // modify shape
 
-          h->shape = 7;  // recover shape
-          return 1;
+      // fprintf(stderr, "DOUBLE2FLOAT %llx\n", repl_new);
 
-        }
+      if (unlikely(cmp_extend_encoding(
+              afl, h, pattern, repl_new, o_pattern, changed_val, 16, idx,
+              taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) {
 
         h->shape = 7;  // recover shape
+        return 1;
 
       }
 
+      h->shape = 7;  // recover shape
+
     }
 
+  }
+
   else if (attr < IS_FP) {
 
     // lesser/greater integer comparison
@@ -1700,12 +1704,16 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
 
       if (afl->pass_stats[key].total == 0) {
 
+#ifdef WORD_SIZE_64
         if (unlikely(is_n)) {
 
           try_to_add_to_dictN(afl, s128_v0, SHAPE_BYTES(h->shape));
           try_to_add_to_dictN(afl, s128_v1, SHAPE_BYTES(h->shape));
 
-        } else {
+        } else
+
+#endif
+        {
 
           try_to_add_to_dict(afl, o->v0, SHAPE_BYTES(h->shape));
           try_to_add_to_dict(afl, o->v1, SHAPE_BYTES(h->shape));
diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c
index 8423a3d1..5040e3ef 100644
--- a/src/afl-fuzz-state.c
+++ b/src/afl-fuzz-state.c
@@ -236,6 +236,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
             afl->afl_env.afl_custom_mutator_only =
                 get_afl_env(afl_environment_variables[i]) ? 1 : 0;
 
+          } else if (!strncmp(env, "AFL_CMPLOG_ONLY_NEW",
+
+                              afl_environment_variable_len)) {
+
+            afl->afl_env.afl_cmplog_only_new =
+                get_afl_env(afl_environment_variables[i]) ? 1 : 0;
+
           } else if (!strncmp(env, "AFL_NO_UI", afl_environment_variable_len)) {
 
             afl->afl_env.afl_no_ui =
diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c
index 82da8176..7e99bf8f 100644
--- a/src/afl-fuzz-stats.c
+++ b/src/afl-fuzz-stats.c
@@ -1014,8 +1014,8 @@ void show_stats(afl_state_t *afl) {
 
 void show_init_stats(afl_state_t *afl) {
 
-  struct queue_entry *q = afl->queue;
-  u32                 min_bits = 0, max_bits = 0, max_len = 0, count = 0;
+  struct queue_entry *q;
+  u32                 min_bits = 0, max_bits = 0, max_len = 0, count = 0, i;
   u64                 min_us = 0, max_us = 0;
   u64                 avg_us = 0;
 
@@ -1028,7 +1028,10 @@ void show_init_stats(afl_state_t *afl) {
 
   }
 
-  while (q) {
+  for (i = 0; i < afl->queued_paths; i++) {
+
+    q = afl->queue_buf[i];
+    if (unlikely(q->disabled)) { continue; }
 
     if (!min_us || q->exec_us < min_us) { min_us = q->exec_us; }
     if (q->exec_us > max_us) { max_us = q->exec_us; }
@@ -1039,7 +1042,6 @@ void show_init_stats(afl_state_t *afl) {
     if (q->len > max_len) { max_len = q->len; }
 
     ++count;
-    q = q->next;
 
   }
 
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index e856730e..49733594 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -145,7 +145,8 @@ static void usage(u8 *argv0, int more_help) {
 
       "Other stuff:\n"
       "  -M/-S id      - distributed mode (see docs/parallel_fuzzing.md)\n"
-      "                  -M auto-sets -D and -Z (use -d to disable -D)\n"
+      "                  -M auto-sets -D, -Z (use -d to disable -D) and no "
+      "trimming\n"
       "  -F path       - sync to a foreign fuzzer queue directory (requires "
       "-M, can\n"
       "                  be specified up to %u times)\n"
@@ -181,6 +182,7 @@ static void usage(u8 *argv0, int more_help) {
       "AFL_AUTORESUME: resume fuzzing if directory specified by -o already exists\n"
       "AFL_BENCH_JUST_ONE: run the target just once\n"
       "AFL_BENCH_UNTIL_CRASH: exit soon when the first crashing input has been found\n"
+      "AFL_CMPLOG_ONLY_NEW: do not run cmplog on initial testcases (good for resumes!)\n"
       "AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n"
       "AFL_CUSTOM_MUTATOR_LIBRARY: lib with afl_custom_fuzz() to mutate inputs\n"
       "AFL_CUSTOM_MUTATOR_ONLY: avoid AFL++'s internal mutators\n"
@@ -340,7 +342,6 @@ int main(int argc, char **argv_orig, char **envp) {
   afl->debug = debug;
   afl_fsrv_init(&afl->fsrv);
   if (debug) { afl->fsrv.debug = true; }
-
   read_afl_environment(afl, envp);
   if (afl->shm.map_size) { afl->fsrv.map_size = afl->shm.map_size; }
   exit_1 = !!afl->afl_env.afl_bench_just_one;
@@ -357,8 +358,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
   while ((opt = getopt(
               argc, argv,
-              "+b:B:c:CdDe:E:hi:I:f:F:l:L:m:M:nNo:p:RQs:S:t:T:UV:Wx:Z")) >
-         0) {
+              "+b:B:c:CdDe:E:hi:I:f:F:l:L:m:M:nNo:p:RQs:S:t:T:UV:Wx:Z")) > 0) {
 
     switch (opt) {
 
@@ -502,6 +502,7 @@ int main(int argc, char **argv_orig, char **envp) {
         afl->sync_id = ck_strdup(optarg);
         afl->skip_deterministic = 0;  // force deterministic fuzzing
         afl->old_seed_selection = 1;  // force old queue walking seed selection
+        afl->disable_trim = 1;        // disable trimming
 
         if ((c = strchr(afl->sync_id, ':'))) {
 
@@ -700,7 +701,6 @@ int main(int argc, char **argv_orig, char **envp) {
         if (afl->in_bitmap) { FATAL("Multiple -B options not supported"); }
 
         afl->in_bitmap = optarg;
-        read_bitmap(afl->in_bitmap, afl->virgin_bits, afl->fsrv.map_size);
         break;
 
       case 'C':                                               /* crash mode */
@@ -986,6 +986,32 @@ int main(int argc, char **argv_orig, char **envp) {
 
   }
 
+  if (afl->fsrv.qemu_mode && getenv("AFL_USE_QASAN")) {
+
+    u8 *preload = getenv("AFL_PRELOAD");
+    u8 *libqasan = get_libqasan_path(argv_orig[0]);
+
+    if (!preload) {
+
+      setenv("AFL_PRELOAD", libqasan, 0);
+
+    } else {
+
+      u8 *result = ck_alloc(strlen(libqasan) + strlen(preload) + 2);
+      strcpy(result, libqasan);
+      strcat(result, " ");
+      strcat(result, preload);
+
+      setenv("AFL_PRELOAD", result, 1);
+      ck_free(result);
+
+    }
+
+    afl->afl_env.afl_preload = (u8 *)getenv("AFL_PRELOAD");
+    ck_free(libqasan);
+
+  }
+
   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\" "
@@ -1341,13 +1367,6 @@ int main(int argc, char **argv_orig, char **envp) {
   set_scheduler_mode(SCHEDULER_MODE_LOW_LATENCY);
   #endif
 
-  afl->fsrv.trace_bits =
-      afl_shm_init(&afl->shm, afl->fsrv.map_size, afl->non_instrumented_mode);
-
-  if (!afl->in_bitmap) { memset(afl->virgin_bits, 255, afl->fsrv.map_size); }
-  memset(afl->virgin_tmout, 255, afl->fsrv.map_size);
-  memset(afl->virgin_crash, 255, afl->fsrv.map_size);
-
   init_count_class16();
 
   if (afl->is_main_node && check_main_node_exists(afl) == 1) {
@@ -1514,62 +1533,87 @@ int main(int argc, char **argv_orig, char **envp) {
   }
 
   afl->argv = use_argv;
+  afl->fsrv.trace_bits =
+      afl_shm_init(&afl->shm, afl->fsrv.map_size, afl->non_instrumented_mode);
 
-  if (afl->cmplog_binary) {
+  if (!afl->non_instrumented_mode) {
 
-    ACTF("Spawning cmplog forkserver");
-    afl_fsrv_init_dup(&afl->cmplog_fsrv, &afl->fsrv);
-    // TODO: this is semi-nice
-    afl->cmplog_fsrv.trace_bits = afl->fsrv.trace_bits;
-    afl->cmplog_fsrv.qemu_mode = afl->fsrv.qemu_mode;
-    afl->cmplog_fsrv.cmplog_binary = afl->cmplog_binary;
-    afl->cmplog_fsrv.init_child_func = cmplog_exec_child;
-    afl_fsrv_start(&afl->cmplog_fsrv, afl->argv, &afl->stop_soon,
-                   afl->afl_env.afl_debug_child);
-    OKF("Cmplog forkserver successfully started");
+    afl->fsrv.map_size = 4194304;  // dummy temporary value
 
-  }
+    u32 new_map_size = afl_fsrv_get_mapsize(
+        &afl->fsrv, afl->argv, &afl->stop_soon, afl->afl_env.afl_debug_child);
 
-  perform_dry_run(afl);
+    if (new_map_size && new_map_size != 4194304) {
 
-  /*
-    if (!user_set_cache && afl->q_testcase_max_cache_size) {
+      // only reinitialize when it makes sense
+      if (map_size != new_map_size) {
 
-      / * The user defined not a fixed number of entries for the cache.
-         Hence we autodetect a good value. After the dry run inputs are
-         trimmed and we know the average and max size of the input seeds.
-         We use this information to set a fitting size to max entries
-         based on the cache size. * /
+        //      if (map_size < new_map_size ||
+        //          (new_map_size > map_size && new_map_size - map_size >
+        //          MAP_SIZE)) {
 
-      struct queue_entry *q = afl->queue;
-      u64                 size = 0, count = 0, avg = 0, max = 0;
+        OKF("Re-initializing maps to %u bytes", new_map_size);
 
-      while (q) {
+        afl->virgin_bits = ck_realloc(afl->virgin_bits, map_size);
+        afl->virgin_tmout = ck_realloc(afl->virgin_tmout, map_size);
+        afl->virgin_crash = ck_realloc(afl->virgin_crash, map_size);
+        afl->var_bytes = ck_realloc(afl->var_bytes, map_size);
+        afl->top_rated = ck_realloc(afl->top_rated, map_size * sizeof(void *));
+        afl->clean_trace = ck_realloc(afl->clean_trace, map_size);
+        afl->clean_trace_custom = ck_realloc(afl->clean_trace_custom, map_size);
+        afl->first_trace = ck_realloc(afl->first_trace, map_size);
+        afl->map_tmp_buf = ck_realloc(afl->map_tmp_buf, map_size);
 
-        ++count;
-        size += q->len;
-        if (max < q->len) { max = q->len; }
-        q = q->next;
+        afl_shm_deinit(&afl->shm);
+        afl_fsrv_kill(&afl->fsrv);
+        afl->fsrv.map_size = new_map_size;
+        afl->fsrv.trace_bits = afl_shm_init(&afl->shm, afl->fsrv.map_size,
+                                            afl->non_instrumented_mode);
+        setenv("AFL_NO_AUTODICT", "1", 1);  // loaded already
+        afl_fsrv_start(&afl->fsrv, afl->argv, &afl->stop_soon,
+                       afl->afl_env.afl_debug_child);
 
       }
 
-      if (count) {
+      map_size = new_map_size;
 
-        avg = size / count;
-        avg = ((avg + max) / 2) + 1;
+    }
 
-      }
+    afl->fsrv.map_size = map_size;
 
-      if (avg < 10240) { avg = 10240; }
+  }
 
-      afl->q_testcase_max_cache_entries = afl->q_testcase_max_cache_size / avg;
+  // after we have the correct bitmap size we can read the bitmap -B option
+  // and set the virgin maps
+  if (!afl->in_bitmap) {
 
-      if (afl->q_testcase_max_cache_entries > 32768)
-        afl->q_testcase_max_cache_entries = 32768;
+    memset(afl->virgin_bits, 255, afl->fsrv.map_size);
 
-    }
+  } else {
+
+    read_bitmap(afl->in_bitmap, afl->virgin_bits, afl->fsrv.map_size);
+
+  }
+
+  memset(afl->virgin_tmout, 255, afl->fsrv.map_size);
+  memset(afl->virgin_crash, 255, afl->fsrv.map_size);
 
-  */
+  if (afl->cmplog_binary) {
+
+    ACTF("Spawning cmplog forkserver");
+    afl_fsrv_init_dup(&afl->cmplog_fsrv, &afl->fsrv);
+    // TODO: this is semi-nice
+    afl->cmplog_fsrv.trace_bits = afl->fsrv.trace_bits;
+    afl->cmplog_fsrv.qemu_mode = afl->fsrv.qemu_mode;
+    afl->cmplog_fsrv.cmplog_binary = afl->cmplog_binary;
+    afl->cmplog_fsrv.init_child_func = cmplog_exec_child;
+    afl_fsrv_start(&afl->cmplog_fsrv, afl->argv, &afl->stop_soon,
+                   afl->afl_env.afl_debug_child);
+    OKF("Cmplog forkserver successfully started");
+
+  }
+
+  perform_dry_run(afl);
 
   if (afl->q_testcase_max_cache_entries) {
 
@@ -1642,7 +1686,13 @@ int main(int argc, char **argv_orig, char **envp) {
       if (unlikely(afl->old_seed_selection)) {
 
         afl->current_entry = 0;
-        afl->queue_cur = afl->queue;
+        while (unlikely(afl->queue_buf[afl->current_entry]->disabled)) {
+
+          ++afl->current_entry;
+
+        }
+
+        afl->queue_cur = afl->queue_buf[afl->current_entry];
 
         if (unlikely(seek_to)) {
 
@@ -1774,12 +1824,14 @@ int main(int argc, char **argv_orig, char **envp) {
 
         }
 
-        struct queue_entry *q = afl->queue;
         // we must recalculate the scores of all queue entries
-        while (q) {
+        for (i = 0; i < (s32)afl->queued_paths; i++) {
+
+          if (likely(!afl->queue_buf[i]->disabled)) {
 
-          update_bitmap_score(afl, q);
-          q = q->next;
+            update_bitmap_score(afl, afl->queue_buf[i]);
+
+          }
 
         }
 
@@ -1821,8 +1873,15 @@ int main(int argc, char **argv_orig, char **envp) {
 
       if (unlikely(afl->old_seed_selection)) {
 
-        afl->queue_cur = afl->queue_cur->next;
-        ++afl->current_entry;
+        while (++afl->current_entry < afl->queued_paths &&
+               afl->queue_buf[afl->current_entry]->disabled)
+          ;
+        if (unlikely(afl->current_entry >= afl->queued_paths ||
+                     afl->queue_buf[afl->current_entry] == NULL ||
+                     afl->queue_buf[afl->current_entry]->disabled))
+          afl->queue_cur = NULL;
+        else
+          afl->queue_cur = afl->queue_buf[afl->current_entry];
 
       }
 
diff --git a/src/afl-sharedmem.c b/src/afl-sharedmem.c
index fe641d0d..3241a130 100644
--- a/src/afl-sharedmem.c
+++ b/src/afl-sharedmem.c
@@ -66,9 +66,17 @@ static list_t shm_list = {.element_prealloc_count = 0};
 
 void afl_shm_deinit(sharedmem_t *shm) {
 
-  if (shm == NULL) return;
-
+  if (shm == NULL) { return; }
   list_remove(&shm_list, shm);
+  if (shm->shmemfuzz_mode) {
+
+    unsetenv(SHM_FUZZ_ENV_VAR);
+
+  } else {
+
+    unsetenv(SHM_ENV_VAR);
+
+  }
 
 #ifdef USEMMAP
   if (shm->map != NULL) {
@@ -94,6 +102,8 @@ void afl_shm_deinit(sharedmem_t *shm) {
 
   if (shm->cmplog_mode) {
 
+    unsetenv(CMPLOG_SHM_ENV_VAR);
+
     if (shm->cmp_map != NULL) {
 
       munmap(shm->cmp_map, shm->map_size);
diff --git a/src/afl-showmap.c b/src/afl-showmap.c
index 5a0b6ecf..56091357 100644
--- a/src/afl-showmap.c
+++ b/src/afl-showmap.c
@@ -86,7 +86,8 @@ static u8 quiet_mode,                  /* Hide non-essential messages?      */
     remove_shm = 1,                    /* remove shmem?                     */
     collect_coverage,                  /* collect coverage                  */
     have_coverage,                     /* have coverage?                    */
-    no_classify;                       /* do not classify counts            */
+    no_classify,                       /* do not classify counts            */
+    debug;                             /* debug mode                        */
 
 static volatile u8 stop_soon,          /* Ctrl-C pressed?                   */
     child_crashed;                     /* Child crashed?                    */
@@ -743,6 +744,7 @@ int main(int argc, char **argv_orig, char **envp) {
   char **argv = argv_cpy_dup(argc, argv_orig);
 
   afl_forkserver_t fsrv_var = {0};
+  if (getenv("AFL_DEBUG")) { debug = 1; }
   fsrv = &fsrv_var;
   afl_fsrv_init(fsrv);
   map_size = get_map_size();
@@ -943,6 +945,31 @@ int main(int argc, char **argv_orig, char **envp) {
 
   if (optind == argc || !out_file) { usage(argv[0]); }
 
+  if (fsrv->qemu_mode && getenv("AFL_USE_QASAN")) {
+
+    u8 *preload = getenv("AFL_PRELOAD");
+    u8 *libqasan = get_libqasan_path(argv_orig[0]);
+
+    if (!preload) {
+
+      setenv("AFL_PRELOAD", libqasan, 0);
+
+    } else {
+
+      u8 *result = ck_alloc(strlen(libqasan) + strlen(preload) + 2);
+      strcpy(result, libqasan);
+      strcat(result, " ");
+      strcat(result, preload);
+
+      setenv("AFL_PRELOAD", result, 1);
+      ck_free(result);
+
+    }
+
+    ck_free(libqasan);
+
+  }
+
   if (in_dir) {
 
     if (!out_file && !collect_coverage)
@@ -966,14 +993,16 @@ int main(int argc, char **argv_orig, char **envp) {
 
   //  if (afl->shmem_testcase_mode) { setup_testcase_shmem(afl); }
 
+  setenv("AFL_NO_AUTODICT", "1", 1);
+
   /* initialize cmplog_mode */
   shm.cmplog_mode = 0;
-  fsrv->trace_bits = afl_shm_init(&shm, map_size, 0);
   setup_signal_handlers();
 
   set_up_environment(fsrv);
 
   fsrv->target_path = find_binary(argv[optind]);
+  fsrv->trace_bits = afl_shm_init(&shm, map_size, 0);
 
   if (!quiet_mode) {
 
@@ -1026,6 +1055,7 @@ int main(int argc, char **argv_orig, char **envp) {
   /* initialize cmplog_mode */
   shm_fuzz->cmplog_mode = 0;
   u8 *map = afl_shm_init(shm_fuzz, MAX_FILE + sizeof(u32), 1);
+  shm_fuzz->shmemfuzz_mode = 1;
   if (!map) { FATAL("BUG: Zero return from afl_shm_init."); }
 #ifdef USEMMAP
   setenv(SHM_FUZZ_ENV_VAR, shm_fuzz->g_shm_file_path, 1);
@@ -1038,6 +1068,38 @@ int main(int argc, char **argv_orig, char **envp) {
   fsrv->shmem_fuzz_len = (u32 *)map;
   fsrv->shmem_fuzz = map + sizeof(u32);
 
+  u32 save_be_quiet = be_quiet;
+  be_quiet = !debug;
+  fsrv->map_size = 4194304;  // dummy temporary value
+  u32 new_map_size = afl_fsrv_get_mapsize(
+      fsrv, use_argv, &stop_soon,
+      (get_afl_env("AFL_DEBUG_CHILD") || get_afl_env("AFL_DEBUG_CHILD_OUTPUT"))
+          ? 1
+          : 0);
+  be_quiet = save_be_quiet;
+
+  if (new_map_size) {
+
+    // only reinitialize when it makes sense
+    if (map_size < new_map_size ||
+        (new_map_size > map_size && new_map_size - map_size > MAP_SIZE)) {
+
+      if (!be_quiet)
+        ACTF("Aquired new map size for target: %u bytes\n", new_map_size);
+
+      afl_shm_deinit(&shm);
+      afl_fsrv_kill(fsrv);
+      fsrv->map_size = new_map_size;
+      fsrv->trace_bits = afl_shm_init(&shm, new_map_size, 0);
+
+    }
+
+    map_size = new_map_size;
+
+  }
+
+  fsrv->map_size = map_size;
+
   if (in_dir) {
 
     DIR *          dir_in, *dir_out = NULL;
diff --git a/src/afl-tmin.c b/src/afl-tmin.c
index 5fd60cd2..799a4b87 100644
--- a/src/afl-tmin.c
+++ b/src/afl-tmin.c
@@ -79,7 +79,8 @@ static u8 crash_mode,                  /* Crash-centric mode?               */
     edges_only,                        /* Ignore hit counts?                */
     exact_mode,                        /* Require path match for crashes?   */
     remove_out_file,                   /* remove out_file on exit?          */
-    remove_shm = 1;                    /* remove shmem on exit?             */
+    remove_shm = 1,                    /* remove shmem on exit?             */
+    debug;                             /* debug mode                        */
 
 static volatile u8 stop_soon;          /* Ctrl-C pressed?                   */
 
@@ -878,6 +879,7 @@ int main(int argc, char **argv_orig, char **envp) {
   char **argv = argv_cpy_dup(argc, argv_orig);
 
   afl_forkserver_t fsrv_var = {0};
+  if (getenv("AFL_DEBUG")) { debug = 1; }
   fsrv = &fsrv_var;
   afl_fsrv_init(fsrv);
   map_size = get_map_size();
@@ -1074,10 +1076,35 @@ int main(int argc, char **argv_orig, char **envp) {
   if (optind == argc || !in_file || !output_file) { usage(argv[0]); }
 
   check_environment_vars(envp);
+  setenv("AFL_NO_AUTODICT", "1", 1);
+
+  if (fsrv->qemu_mode && getenv("AFL_USE_QASAN")) {
+
+    u8 *preload = getenv("AFL_PRELOAD");
+    u8 *libqasan = get_libqasan_path(argv_orig[0]);
+
+    if (!preload) {
+
+      setenv("AFL_PRELOAD", libqasan, 0);
+
+    } else {
+
+      u8 *result = ck_alloc(strlen(libqasan) + strlen(preload) + 2);
+      strcpy(result, libqasan);
+      strcat(result, " ");
+      strcat(result, preload);
+
+      setenv("AFL_PRELOAD", result, 1);
+      ck_free(result);
+
+    }
+
+    ck_free(libqasan);
+
+  }
 
   /* initialize cmplog_mode */
   shm.cmplog_mode = 0;
-  fsrv->trace_bits = afl_shm_init(&shm, map_size, 0);
 
   atexit(at_exit_handler);
   setup_signal_handlers();
@@ -1085,6 +1112,7 @@ int main(int argc, char **argv_orig, char **envp) {
   set_up_environment(fsrv);
 
   fsrv->target_path = find_binary(argv[optind]);
+  fsrv->trace_bits = afl_shm_init(&shm, map_size, 0);
   detect_file_args(argv + optind, out_file, &fsrv->use_stdin);
 
   if (fsrv->qemu_mode) {
@@ -1156,6 +1184,7 @@ int main(int argc, char **argv_orig, char **envp) {
   /* initialize cmplog_mode */
   shm_fuzz->cmplog_mode = 0;
   u8 *map = afl_shm_init(shm_fuzz, MAX_FILE + sizeof(u32), 1);
+  shm_fuzz->shmemfuzz_mode = 1;
   if (!map) { FATAL("BUG: Zero return from afl_shm_init."); }
 #ifdef USEMMAP
   setenv(SHM_FUZZ_ENV_VAR, shm_fuzz->g_shm_file_path, 1);
@@ -1170,12 +1199,39 @@ int main(int argc, char **argv_orig, char **envp) {
 
   read_initial_file();
 
-  afl_fsrv_start(
+  fsrv->map_size = 4194304;  // dummy temporary value
+  u32 new_map_size = afl_fsrv_get_mapsize(
       fsrv, use_argv, &stop_soon,
       (get_afl_env("AFL_DEBUG_CHILD") || get_afl_env("AFL_DEBUG_CHILD_OUTPUT"))
           ? 1
           : 0);
 
+  if (new_map_size) {
+
+    if (map_size < new_map_size ||
+        (new_map_size > map_size && new_map_size - map_size > MAP_SIZE)) {
+
+      if (!be_quiet)
+        ACTF("Aquired new map size for target: %u bytes\n", new_map_size);
+
+      afl_shm_deinit(&shm);
+      afl_fsrv_kill(fsrv);
+      fsrv->map_size = new_map_size;
+      fsrv->trace_bits = afl_shm_init(&shm, new_map_size, 0);
+      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 = new_map_size;
+
+  }
+
+  fsrv->map_size = map_size;
+
   if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)
     shm_fuzz = deinit_shmem(fsrv, shm_fuzz);