about summary refs log tree commit diff
diff options
context:
space:
mode:
authorvan Hauser <vh@thc.org>2023-06-12 10:16:45 +0300
committerGitHub <noreply@github.com>2023-06-12 10:16:45 +0300
commitf1a616406eff94458ad300efa1b46ff301b24ae8 (patch)
tree4d3957e452ce12ef81f949a945c85f38fff216a3
parent61b6f4ed9e4dce15c39e4350278a95a41ea2522c (diff)
parented97dbacef98c379d7028514a43c799c86050584 (diff)
downloadafl++-f1a616406eff94458ad300efa1b46ff301b24ae8.tar.gz
Merge pull request #1767 from AFLplusplus/mutationnew
Mutationnew
-rw-r--r--custom_mutators/aflpp/Makefile10
-rw-r--r--custom_mutators/aflpp/README.md8
-rw-r--r--custom_mutators/aflpp/aflpp.c89
-rw-r--r--custom_mutators/aflpp/standalone/Makefile10
-rw-r--r--custom_mutators/aflpp/standalone/README.md10
-rw-r--r--custom_mutators/aflpp/standalone/aflpp-standalone.c165
-rw-r--r--include/afl-fuzz.h72
-rw-r--r--include/afl-mutations.h2202
-rw-r--r--include/config.h6
-rw-r--r--src/afl-fuzz-bitmap.c12
-rw-r--r--src/afl-fuzz-one.c921
-rw-r--r--src/afl-fuzz-queue.c2
-rw-r--r--src/afl-fuzz-state.c1
-rw-r--r--src/afl-fuzz-stats.c45
-rw-r--r--src/afl-fuzz.c77
15 files changed, 3289 insertions, 341 deletions
diff --git a/custom_mutators/aflpp/Makefile b/custom_mutators/aflpp/Makefile
new file mode 100644
index 00000000..8efdf3e4
--- /dev/null
+++ b/custom_mutators/aflpp/Makefile
@@ -0,0 +1,10 @@
+
+CFLAGS = -O3 -funroll-loops -fPIC -Wl,-Bsymbolic
+
+all: aflpp-mutator.so
+
+aflpp-mutator.so:	aflpp.c
+	$(CC) $(CFLAGS) -I../../include -I. -shared -o aflpp-mutator.so aflpp.c ../../src/afl-performance.c
+
+clean:
+	rm -f *.o *~ *.so core
diff --git a/custom_mutators/aflpp/README.md b/custom_mutators/aflpp/README.md
new file mode 100644
index 00000000..04d605c1
--- /dev/null
+++ b/custom_mutators/aflpp/README.md
@@ -0,0 +1,8 @@
+# custum mutator: AFL++
+
+this is the AFL++ havoc mutator as a custom mutator module for AFL++.
+
+just type `make` to build
+
+```AFL_CUSTOM_MUTATOR_LIBRARY=custom_mutators/aflpp/aflpp-mutator.so afl-fuzz ...```
+
diff --git a/custom_mutators/aflpp/aflpp.c b/custom_mutators/aflpp/aflpp.c
new file mode 100644
index 00000000..e15d0391
--- /dev/null
+++ b/custom_mutators/aflpp/aflpp.c
@@ -0,0 +1,89 @@
+#include "afl-mutations.h"
+
+typedef struct my_mutator {
+
+  afl_state_t *afl;
+  u8          *buf;
+  u32          buf_size;
+
+} my_mutator_t;
+
+my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
+
+  (void)seed;
+
+  my_mutator_t *data = calloc(1, sizeof(my_mutator_t));
+  if (!data) {
+
+    perror("afl_custom_init alloc");
+    return NULL;
+
+  }
+
+  if ((data->buf = malloc(MAX_FILE)) == NULL) {
+
+    perror("afl_custom_init alloc");
+    return NULL;
+
+  } else {
+
+    data->buf_size = MAX_FILE;
+
+  }
+
+  data->afl = afl;
+
+  return data;
+
+}
+
+/* here we run the AFL++ mutator, which is the best! */
+
+size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
+                       u8 **out_buf, uint8_t *add_buf, size_t add_buf_size,
+                       size_t max_size) {
+
+  if (max_size > data->buf_size) {
+
+    u8 *ptr = realloc(data->buf, max_size);
+
+    if (ptr) {
+
+      return 0;
+
+    } else {
+
+      data->buf = ptr;
+      data->buf_size = max_size;
+
+    }
+
+  }
+
+  u32 havoc_steps = 1 + rand_below(data->afl, 16);
+
+  /* set everything up, costly ... :( */
+  memcpy(data->buf, buf, buf_size);
+
+  /* the mutation */
+  u32 out_buf_len = afl_mutate(data->afl, data->buf, buf_size, havoc_steps,
+                               false, true, add_buf, add_buf_size, max_size);
+
+  /* return size of mutated data */
+  *out_buf = data->buf;
+  return out_buf_len;
+
+}
+
+/**
+ * Deinitialize everything
+ *
+ * @param data The data ptr from afl_custom_init
+ */
+void afl_custom_deinit(my_mutator_t *data) {
+
+  free(data->buf);
+  free(data);
+
+}
+
diff --git a/custom_mutators/aflpp/standalone/Makefile b/custom_mutators/aflpp/standalone/Makefile
new file mode 100644
index 00000000..f1e99445
--- /dev/null
+++ b/custom_mutators/aflpp/standalone/Makefile
@@ -0,0 +1,10 @@
+
+CFLAGS = -O3 -funroll-loops -fPIC
+
+all: aflpp-standalone
+
+aflpp-standalone:	aflpp-standalone.c
+	$(CC) $(CFLAGS) -I../../../include -I. -o aflpp-standalone aflpp-standalone.c ../../../src/afl-performance.c
+
+clean:
+	rm -f *.o *~ aflpp-standalone core
diff --git a/custom_mutators/aflpp/standalone/README.md b/custom_mutators/aflpp/standalone/README.md
new file mode 100644
index 00000000..a1ffb5f9
--- /dev/null
+++ b/custom_mutators/aflpp/standalone/README.md
@@ -0,0 +1,10 @@
+# AFL++ standalone mutator
+
+this is the AFL++ havoc mutator as a standalone mutator
+
+just type `make` to build.
+
+```
+aflpp-standalone inputfile outputfile [splicefile]
+```
+
diff --git a/custom_mutators/aflpp/standalone/aflpp-standalone.c b/custom_mutators/aflpp/standalone/aflpp-standalone.c
new file mode 100644
index 00000000..91bac4a8
--- /dev/null
+++ b/custom_mutators/aflpp/standalone/aflpp-standalone.c
@@ -0,0 +1,165 @@
+#include "afl-mutations.h"
+
+s8  interesting_8[] = {INTERESTING_8};
+s16 interesting_16[] = {INTERESTING_8, INTERESTING_16};
+s32 interesting_32[] = {INTERESTING_8, INTERESTING_16, INTERESTING_32};
+
+typedef struct my_mutator {
+
+  afl_state_t *afl;
+  u8          *buf;
+  u32          buf_size;
+
+} my_mutator_t;
+
+my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
+
+  (void)seed;
+
+  my_mutator_t *data = calloc(1, sizeof(my_mutator_t));
+  if (!data) {
+
+    perror("afl_custom_init alloc");
+    return NULL;
+
+  }
+
+  if ((data->buf = malloc(1024*1024)) == NULL) {
+
+    perror("afl_custom_init alloc");
+    return NULL;
+
+  } else {
+
+    data->buf_size = 1024*1024;
+
+  }
+
+  /* fake AFL++ state */
+  data->afl = calloc(1, sizeof(afl_state_t));
+  data->afl->queue_cycle = 1;
+  data->afl->fsrv.dev_urandom_fd = open("/dev/urandom", O_RDONLY);
+  rand_set_seed(data->afl, getpid());
+
+  return data;
+
+}
+
+/* here we run the AFL++ mutator, which is the best! */
+
+size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
+                       u8 **out_buf, uint8_t *add_buf, size_t add_buf_size,
+                       size_t max_size) {
+
+  if (max_size > data->buf_size) {
+
+    u8 *ptr = realloc(data->buf, max_size);
+
+    if (ptr) {
+
+      return 0;
+
+    } else {
+
+      data->buf = ptr;
+      data->buf_size = max_size;
+
+    }
+
+  }
+
+  u32 havoc_steps = 1 + rand_below(data->afl, 16);
+
+  /* set everything up, costly ... :( */
+  memcpy(data->buf, buf, buf_size);
+
+  /* the mutation */
+  u32 out_buf_len = afl_mutate(data->afl, data->buf, buf_size, havoc_steps,
+                               false, true, add_buf, add_buf_size, max_size);
+
+  /* return size of mutated data */
+  *out_buf = data->buf;
+  return out_buf_len;
+
+}
+
+int main(int argc, char *argv[]) {
+
+  if (argc > 1 && strncmp(argv[1], "-h", 2) == 0) {
+    printf("Syntax: %s [-v] [inputfile [outputfile [splicefile]]]\n\n", argv[0]);
+    printf("Reads a testcase from stdin when no input file (or '-') is specified,\n");
+    printf("mutates according to AFL++'s mutation engine, and write to stdout when '-' or\n");
+    printf("no output filename is given. As an optional third parameter you can give a file\n");
+    printf("for splicing. Maximum input and output length is 1MB.\n");
+    printf("The -v verbose option prints debug output to stderr.\n");
+    return 0;
+  }
+
+  FILE *in = stdin, *out = stdout, *splice = NULL;
+  unsigned char *inbuf = malloc(1024 * 1024), *outbuf, *splicebuf = NULL;
+  int verbose = 0, splicelen = 0;
+
+  if (argc > 1 && strcmp(argv[1], "-v") == 0) {
+    verbose = 1;
+    argc--;
+    argv++;
+    fprintf(stderr, "Verbose active\n");
+  }
+
+  my_mutator_t *data = afl_custom_init(NULL, 0);
+
+  if (argc > 1 && strcmp(argv[1], "-") != 0) {
+    if ((in = fopen(argv[1], "r")) == NULL) {
+      perror(argv[1]);
+      return -1;
+    }
+    if (verbose) fprintf(stderr, "Input: %s\n", argv[1]);
+  }
+
+  size_t inlen = fread(inbuf, 1, 1024*1024, in);
+  
+  if (!inlen) {
+    fprintf(stderr, "Error: empty file %s\n", argv[1] ? argv[1] : "stdin");
+    return -1;
+  }
+
+  if (argc > 2 && strcmp(argv[2], "-") != 0) {
+    if ((out = fopen(argv[2], "w")) == NULL) {
+      perror(argv[2]);
+      return -1;
+    }
+    if (verbose) fprintf(stderr, "Output: %s\n", argv[2]);
+  }
+
+  if (argc > 3) {
+    if ((splice = fopen(argv[3], "r")) == NULL) {
+      perror(argv[3]);
+      return -1;
+    }
+    if (verbose) fprintf(stderr, "Splice: %s\n", argv[3]);
+    splicebuf = malloc(1024*1024);
+    size_t splicelen = fread(splicebuf, 1, 1024*1024, splice);
+    if (!splicelen) {
+      fprintf(stderr, "Error: empty file %s\n", argv[3]);
+      return -1;
+    }
+    if (verbose) fprintf(stderr, "Mutation splice length: %zu\n", splicelen);
+  }
+
+  if (verbose) fprintf(stderr, "Mutation input length: %zu\n", inlen);
+  unsigned int outlen = afl_custom_fuzz(data, inbuf, inlen, &outbuf, splicebuf, splicelen, 1024*1024);
+
+  if (outlen == 0 || !outbuf) {
+    fprintf(stderr, "Error: no mutation data returned.\n");
+    return -1;
+  }
+
+  if (verbose) fprintf(stderr, "Mutation output length: %zu\n", outlen);
+
+  if (fwrite(outbuf, 1, outlen, out) != outlen) {
+    fprintf(stderr, "Warning: incomplete write.\n");
+    return -1;
+  }
+  
+  return 0;
+}
diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h
index beb2de2a..c6c45fbd 100644
--- a/include/afl-fuzz.h
+++ b/include/afl-fuzz.h
@@ -494,7 +494,8 @@ typedef struct afl_state {
       *orig_cmdline,                    /* Original command line            */
       *infoexec;                       /* Command to execute on a new crash */
 
-  u32 hang_tmout;                       /* Timeout used for hang det (ms)   */
+  u32 hang_tmout,                       /* Timeout used for hang det (ms)   */
+      stats_update_freq;                /* Stats update frequency (execs)   */
 
   u8 havoc_stack_pow2,                  /* HAVOC_STACK_POW2                 */
       no_unlink,                        /* do not unlink cur_input          */
@@ -503,40 +504,37 @@ typedef struct afl_state {
       custom_splice_optout,             /* Custom mutator no splice buffer  */
       is_main_node,                     /* if this is the main node         */
       is_secondary_node,                /* if this is a secondary instance  */
-      pizza_is_served;                  /* pizza mode                       */
-
-  u32 stats_update_freq;                /* Stats update frequency (execs)   */
-
-  u8 schedule;                          /* Power schedule (default: EXPLORE)*/
-  u8 havoc_max_mult;
-
-  u8 skip_deterministic,                /* Skip deterministic stages?       */
-      use_splicing,                     /* Recombine input files?           */
-      non_instrumented_mode,            /* Run in non-instrumented mode?    */
-      score_changed,                    /* Scoring for favorites changed?   */
-      resuming_fuzz,                    /* Resuming an older fuzzing job?   */
-      timeout_given,                    /* Specific timeout given?          */
-      not_on_tty,                       /* stdout is not a tty              */
-      term_too_small,                   /* terminal dimensions too small    */
-      no_forkserver,                    /* Disable forkserver?              */
-      crash_mode,                       /* Crash mode! Yeah!                */
-      in_place_resume,                  /* Attempt in-place resume?         */
-      autoresume,                       /* Resume if afl->out_dir exists?   */
-      auto_changed,                     /* Auto-generated tokens changed?   */
-      no_cpu_meter_red,                 /* Feng shui on the status screen   */
-      no_arith,                         /* Skip most arithmetic ops         */
-      shuffle_queue,                    /* Shuffle input queue?             */
-      bitmap_changed,                   /* Time to update bitmap?           */
-      unicorn_mode,                     /* Running in Unicorn mode?         */
-      use_wine,                         /* Use WINE with QEMU mode          */
-      skip_requested,                   /* Skip request, via SIGUSR1        */
-      run_over10m,                      /* Run time over 10 minutes?        */
-      persistent_mode,                  /* Running in persistent mode?      */
-      deferred_mode,                    /* Deferred forkserver mode?        */
-      fixed_seed,                       /* do not reseed                    */
-      fast_cal,                         /* Try to calibrate faster?         */
-      disable_trim,                     /* Never trim in fuzz_one           */
-      shmem_testcase_mode,              /* If sharedmem testcases are used  */
+      pizza_is_served,                  /* pizza mode                       */
+      text_input,                       /* target wants text inputs         */
+      fuzz_mode, /* current mode: coverage/exploration or crash/exploitation */
+      schedule,                         /* Power schedule (default: EXPLORE)*/
+      havoc_max_mult, skip_deterministic, /* Skip deterministic stages?       */
+      use_splicing,                       /* Recombine input files?           */
+      non_instrumented_mode,              /* Run in non-instrumented mode?    */
+      score_changed,                      /* Scoring for favorites changed?   */
+      resuming_fuzz,                      /* Resuming an older fuzzing job?   */
+      timeout_given,                      /* Specific timeout given?          */
+      not_on_tty,                         /* stdout is not a tty              */
+      term_too_small,                     /* terminal dimensions too small    */
+      no_forkserver,                      /* Disable forkserver?              */
+      crash_mode,                         /* Crash mode! Yeah!                */
+      in_place_resume,                    /* Attempt in-place resume?         */
+      autoresume,                         /* Resume if afl->out_dir exists?   */
+      auto_changed,                       /* Auto-generated tokens changed?   */
+      no_cpu_meter_red,                   /* Feng shui on the status screen   */
+      no_arith,                           /* Skip most arithmetic ops         */
+      shuffle_queue,                      /* Shuffle input queue?             */
+      bitmap_changed,                     /* Time to update bitmap?           */
+      unicorn_mode,                       /* Running in Unicorn mode?         */
+      use_wine,                           /* Use WINE with QEMU mode          */
+      skip_requested,                     /* Skip request, via SIGUSR1        */
+      run_over10m,                        /* Run time over 10 minutes?        */
+      persistent_mode,                    /* Running in persistent mode?      */
+      deferred_mode,                      /* Deferred forkserver mode?        */
+      fixed_seed,                         /* do not reseed                    */
+      fast_cal,                           /* Try to calibrate faster?         */
+      disable_trim,                       /* Never trim in fuzz_one           */
+      shmem_testcase_mode,                /* If sharedmem testcases are used  */
       expand_havoc,                /* perform expensive havoc after no find */
       cycle_schedules,                  /* cycle power schedules?           */
       old_seed_selection,               /* use vanilla afl seed selection   */
@@ -597,7 +595,8 @@ typedef struct afl_state {
       last_hang_time,                   /* Time for most recent hang (ms)   */
       longest_find_time,                /* Longest time taken for a find    */
       exit_on_time,                     /* Delay to exit if no new paths    */
-      sync_time;                        /* Sync time (ms)                   */
+      sync_time,                        /* Sync time (ms)                   */
+      switch_fuzz_mode;                 /* auto or fixed fuzz mode          */
 
   u32 slowest_exec_ms,                  /* Slowest testcase non hang in ms  */
       subseq_tmouts;                    /* Number of timeouts in a row      */
@@ -1203,6 +1202,7 @@ u8     check_if_text_buf(u8 *buf, u32 len);
 #ifndef AFL_SHOWMAP
 void setup_signal_handlers(void);
 #endif
+char *get_fuzzing_state(afl_state_t *afl);
 
 /* CmpLog */
 
diff --git a/include/afl-mutations.h b/include/afl-mutations.h
new file mode 100644
index 00000000..a3c9fd59
--- /dev/null
+++ b/include/afl-mutations.h
@@ -0,0 +1,2202 @@
+/* Implementation of afl havoc mutation to be used in AFL++ custom mutators and
+   partially in afl-fuzz itself.
+
+   How to use:
+
+   #include "afl-mutations.h"  // needs afl-fuzz.h
+
+   u32 afl_mutate(afl_state_t *afl, u8 *buf, u32 len, u32t steps, bool is_text,
+                  bool is_exploration, u8 *splice_buf, u32 splice_len,
+                  u32 max_len);
+
+   Returns:
+     u32 - the length of the mutated data return in *buf. 0 = error
+   Parameters:
+     afl_state_t *afl - the *afl state pointer
+     u8 *buf - the input buffer to mutate which will be mutated into.
+           NOTE: must be able to contain a size of at least max_len (see below)!
+     u32 len - the length of the input
+     u32 steps - how many mutations to perform on the input
+     bool is_text - is the target expecting text inputs
+     bool is_exploration - mutate for exploration mode (instead of exploitation)
+     splice_buf - a buffer from another corpus item to splice with.
+                  If NULL then no splicing
+     splice_len - the length of the splice buffer. If 0 then no splicing
+     u32 max_len - the maximum size the mutated buffer may grow to
+*/
+
+#ifndef _ANDROID_ASHMEM_H
+  #define AFL_MUTATIONS_H
+
+  #include <stdbool.h>
+  #include "afl-fuzz.h"
+
+  #define MUT_STRATEGY_ARRAY_SIZE 256
+
+enum {
+
+  /* 00 */ MUT_FLIPBIT,
+  /* 01 */ MUT_INTERESTING8,
+  /* 02 */ MUT_INTERESTING16,
+  /* 03 */ MUT_INTERESTING16BE,
+  /* 04 */ MUT_INTERESTING32,
+  /* 05 */ MUT_INTERESTING32BE,
+  /* 06 */ MUT_ARITH8_,
+  /* 07 */ MUT_ARITH8,
+  /* 08 */ MUT_ARITH16_,
+  /* 09 */ MUT_ARITH16BE_,
+  /* 10 */ MUT_ARITH16,
+  /* 11 */ MUT_ARITH16BE,
+  /* 12 */ MUT_ARITH32_,
+  /* 13 */ MUT_ARITH32BE_,
+  /* 14 */ MUT_ARITH32,
+  /* 15 */ MUT_ARITH32BE,
+  /* 16 */ MUT_RAND8,
+  /* 17 */ MUT_CLONE_COPY,
+  /* 18 */ MUT_CLONE_FIXED,
+  /* 19 */ MUT_OVERWRITE_COPY,
+  /* 20 */ MUT_OVERWRITE_FIXED,
+  /* 21 */ MUT_BYTEADD,
+  /* 22 */ MUT_BYTESUB,
+  /* 23 */ MUT_FLIP8,
+  /* 24 */ MUT_SWITCH,
+  /* 25 */ MUT_DEL,
+  /* 26 */ MUT_SHUFFLE,
+  /* 27 */ MUT_DELONE,
+  /* 28 */ MUT_INSERTONE,
+  /* 29 */ MUT_ASCIINUM,
+  /* 30 */ MUT_INSERTASCIINUM,
+  /* 31 */ MUT_EXTRA_OVERWRITE,
+  /* 32 */ MUT_EXTRA_INSERT,
+  /* 33 */ MUT_AUTO_EXTRA_OVERWRITE,
+  /* 34 */ MUT_AUTO_EXTRA_INSERT,
+  /* 35 */ MUT_SPLICE_OVERWRITE,
+  /* 36 */ MUT_SPLICE_INSERT,
+
+  MUT_MAX
+
+};
+
+  #define MUT_NORMAL_ARRAY_SIZE 77
+u32 normal_splice_array[MUT_NORMAL_ARRAY_SIZE] = {MUT_FLIPBIT,
+                                                  MUT_FLIPBIT,
+                                                  MUT_FLIPBIT,
+                                                  MUT_FLIPBIT,
+                                                  MUT_INTERESTING8,
+                                                  MUT_INTERESTING8,
+                                                  MUT_INTERESTING8,
+                                                  MUT_INTERESTING8,
+                                                  MUT_INTERESTING16,
+                                                  MUT_INTERESTING16,
+                                                  MUT_INTERESTING16BE,
+                                                  MUT_INTERESTING16BE,
+                                                  MUT_INTERESTING32,
+                                                  MUT_INTERESTING32,
+                                                  MUT_INTERESTING32BE,
+                                                  MUT_INTERESTING32BE,
+                                                  MUT_ARITH8_,
+                                                  MUT_ARITH8_,
+                                                  MUT_ARITH8_,
+                                                  MUT_ARITH8_,
+                                                  MUT_ARITH8,
+                                                  MUT_ARITH8,
+                                                  MUT_ARITH8,
+                                                  MUT_ARITH8,
+                                                  MUT_ARITH16_,
+                                                  MUT_ARITH16_,
+                                                  MUT_ARITH16BE_,
+                                                  MUT_ARITH16BE_,
+                                                  MUT_ARITH16,
+                                                  MUT_ARITH16,
+                                                  MUT_ARITH16BE,
+                                                  MUT_ARITH16BE,
+                                                  MUT_ARITH32_,
+                                                  MUT_ARITH32_,
+                                                  MUT_ARITH32BE_,
+                                                  MUT_ARITH32BE_,
+                                                  MUT_ARITH32,
+                                                  MUT_ARITH32,
+                                                  MUT_ARITH32BE,
+                                                  MUT_ARITH32BE,
+                                                  MUT_RAND8,
+                                                  MUT_RAND8,
+                                                  MUT_RAND8,
+                                                  MUT_RAND8,
+                                                  MUT_CLONE_COPY,
+                                                  MUT_CLONE_COPY,
+                                                  MUT_CLONE_COPY,
+                                                  MUT_CLONE_FIXED,
+                                                  MUT_OVERWRITE_COPY,
+                                                  MUT_OVERWRITE_COPY,
+                                                  MUT_OVERWRITE_COPY,
+                                                  MUT_OVERWRITE_FIXED,
+                                                  MUT_BYTEADD,
+                                                  MUT_BYTESUB,
+                                                  MUT_FLIP8,
+                                                  MUT_SWITCH,
+                                                  MUT_SWITCH,
+                                                  MUT_DEL,
+                                                  MUT_DEL,
+                                                  MUT_DEL,
+                                                  MUT_DEL,
+                                                  MUT_DEL,
+                                                  MUT_DEL,
+                                                  MUT_DEL,
+                                                  MUT_DEL,
+                                                  MUT_EXTRA_OVERWRITE,
+                                                  MUT_EXTRA_OVERWRITE,
+                                                  MUT_EXTRA_INSERT,
+                                                  MUT_EXTRA_INSERT,
+                                                  MUT_AUTO_EXTRA_OVERWRITE,
+                                                  MUT_AUTO_EXTRA_OVERWRITE,
+                                                  MUT_AUTO_EXTRA_INSERT,
+                                                  MUT_AUTO_EXTRA_INSERT,
+                                                  MUT_SPLICE_OVERWRITE,
+                                                  MUT_SPLICE_OVERWRITE,
+                                                  MUT_SPLICE_INSERT,
+                                                  MUT_SPLICE_INSERT};
+
+  #define MUT_SPLICE_ARRAY_SIZE 81
+u32 full_splice_array[MUT_SPLICE_ARRAY_SIZE] = {MUT_FLIPBIT,
+                                                MUT_FLIPBIT,
+                                                MUT_FLIPBIT,
+                                                MUT_FLIPBIT,
+                                                MUT_INTERESTING8,
+                                                MUT_INTERESTING8,
+                                                MUT_INTERESTING8,
+                                                MUT_INTERESTING8,
+                                                MUT_INTERESTING16,
+                                                MUT_INTERESTING16,
+                                                MUT_INTERESTING16BE,
+                                                MUT_INTERESTING16BE,
+                                                MUT_INTERESTING32,
+                                                MUT_INTERESTING32,
+                                                MUT_INTERESTING32BE,
+                                                MUT_INTERESTING32BE,
+                                                MUT_ARITH8_,
+                                                MUT_ARITH8_,
+                                                MUT_ARITH8_,
+                                                MUT_ARITH8_,
+                                                MUT_ARITH8,
+                                                MUT_ARITH8,
+                                                MUT_ARITH8,
+                                                MUT_ARITH8,
+                                                MUT_ARITH16_,
+                                                MUT_ARITH16_,
+                                                MUT_ARITH16BE_,
+                                                MUT_ARITH16BE_,
+                                                MUT_ARITH16,
+                                                MUT_ARITH16,
+                                                MUT_ARITH16BE,
+                                                MUT_ARITH16BE,
+                                                MUT_ARITH32_,
+                                                MUT_ARITH32_,
+                                                MUT_ARITH32BE_,
+                                                MUT_ARITH32BE_,
+                                                MUT_ARITH32,
+                                                MUT_ARITH32,
+                                                MUT_ARITH32BE,
+                                                MUT_ARITH32BE,
+                                                MUT_RAND8,
+                                                MUT_RAND8,
+                                                MUT_RAND8,
+                                                MUT_RAND8,
+                                                MUT_CLONE_COPY,
+                                                MUT_CLONE_COPY,
+                                                MUT_CLONE_COPY,
+                                                MUT_CLONE_FIXED,
+                                                MUT_OVERWRITE_COPY,
+                                                MUT_OVERWRITE_COPY,
+                                                MUT_OVERWRITE_COPY,
+                                                MUT_OVERWRITE_FIXED,
+                                                MUT_BYTEADD,
+                                                MUT_BYTESUB,
+                                                MUT_FLIP8,
+                                                MUT_SWITCH,
+                                                MUT_SWITCH,
+                                                MUT_DEL,
+                                                MUT_DEL,
+                                                MUT_DEL,
+                                                MUT_DEL,
+                                                MUT_DEL,
+                                                MUT_DEL,
+                                                MUT_DEL,
+                                                MUT_DEL,
+                                                MUT_EXTRA_OVERWRITE,
+                                                MUT_EXTRA_OVERWRITE,
+                                                MUT_EXTRA_INSERT,
+                                                MUT_EXTRA_INSERT,
+                                                MUT_AUTO_EXTRA_OVERWRITE,
+                                                MUT_AUTO_EXTRA_OVERWRITE,
+                                                MUT_AUTO_EXTRA_INSERT,
+                                                MUT_AUTO_EXTRA_INSERT,
+                                                MUT_SPLICE_OVERWRITE,
+                                                MUT_SPLICE_OVERWRITE,
+                                                MUT_SPLICE_OVERWRITE,
+                                                MUT_SPLICE_OVERWRITE,
+                                                MUT_SPLICE_INSERT,
+                                                MUT_SPLICE_INSERT,
+                                                MUT_SPLICE_INSERT,
+                                                MUT_SPLICE_INSERT};
+
+u32 mutation_strategy_exploration_text[MUT_STRATEGY_ARRAY_SIZE] = {
+
+    MUT_FLIPBIT,
+    MUT_FLIPBIT,
+    MUT_FLIPBIT,
+    MUT_FLIPBIT,
+    MUT_FLIPBIT,
+    MUT_FLIPBIT,
+    MUT_INTERESTING8,
+    MUT_INTERESTING8,
+    MUT_INTERESTING8,
+    MUT_INTERESTING8,
+    MUT_INTERESTING8,
+    MUT_INTERESTING16,
+    MUT_INTERESTING16,
+    MUT_INTERESTING16,
+    MUT_INTERESTING16,
+    MUT_INTERESTING16,
+    MUT_INTERESTING16BE,
+    MUT_INTERESTING16BE,
+    MUT_INTERESTING16BE,
+    MUT_INTERESTING16BE,
+    MUT_INTERESTING16BE,
+    MUT_INTERESTING32,
+    MUT_INTERESTING32,
+    MUT_INTERESTING32,
+    MUT_INTERESTING32,
+    MUT_INTERESTING32,
+    MUT_INTERESTING32BE,
+    MUT_INTERESTING32BE,
+    MUT_INTERESTING32BE,
+    MUT_INTERESTING32BE,
+    MUT_INTERESTING32BE,
+    MUT_ARITH8_,
+    MUT_ARITH8_,
+    MUT_ARITH8_,
+    MUT_ARITH8_,
+    MUT_ARITH8_,
+    MUT_ARITH8_,
+    MUT_ARITH8,
+    MUT_ARITH8,
+    MUT_ARITH8,
+    MUT_ARITH8,
+    MUT_ARITH8,
+    MUT_ARITH8,
+    MUT_ARITH16_,
+    MUT_ARITH16_,
+    MUT_ARITH16_,
+    MUT_ARITH16_,
+    MUT_ARITH16_,
+    MUT_ARITH16_,
+    MUT_ARITH16BE_,
+    MUT_ARITH16BE_,
+    MUT_ARITH16BE_,
+    MUT_ARITH16BE_,
+    MUT_ARITH16BE_,
+    MUT_ARITH16BE_,
+    MUT_ARITH16,
+    MUT_ARITH16,
+    MUT_ARITH16,
+    MUT_ARITH16,
+    MUT_ARITH16,
+    MUT_ARITH16,
+    MUT_ARITH16BE,
+    MUT_ARITH16BE,
+    MUT_ARITH16BE,
+    MUT_ARITH16BE,
+    MUT_ARITH16BE,
+    MUT_ARITH16BE,
+    MUT_ARITH32_,
+    MUT_ARITH32_,
+    MUT_ARITH32_,
+    MUT_ARITH32_,
+    MUT_ARITH32_,
+    MUT_ARITH32_,
+    MUT_ARITH32BE_,
+    MUT_ARITH32BE_,
+    MUT_ARITH32BE_,
+    MUT_ARITH32BE_,
+    MUT_ARITH32BE_,
+    MUT_ARITH32BE_,
+    MUT_ARITH32,
+    MUT_ARITH32,
+    MUT_ARITH32,
+    MUT_ARITH32,
+    MUT_ARITH32,
+    MUT_ARITH32,
+    MUT_ARITH32BE,
+    MUT_ARITH32BE,
+    MUT_ARITH32BE,
+    MUT_ARITH32BE,
+    MUT_ARITH32BE,
+    MUT_ARITH32BE,
+    MUT_RAND8,
+    MUT_RAND8,
+    MUT_RAND8,
+    MUT_RAND8,
+    MUT_RAND8,
+    MUT_RAND8,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_FIXED,
+    MUT_CLONE_FIXED,
+    MUT_CLONE_FIXED,
+    MUT_CLONE_FIXED,
+    MUT_CLONE_FIXED,
+    MUT_CLONE_FIXED,
+    MUT_CLONE_FIXED,
+    MUT_CLONE_FIXED,
+    MUT_CLONE_FIXED,
+    MUT_CLONE_FIXED,
+    MUT_OVERWRITE_COPY,
+    MUT_OVERWRITE_COPY,
+    MUT_OVERWRITE_COPY,
+    MUT_OVERWRITE_COPY,
+    MUT_OVERWRITE_COPY,
+    MUT_OVERWRITE_COPY,
+    MUT_OVERWRITE_COPY,
+    MUT_OVERWRITE_COPY,
+    MUT_OVERWRITE_COPY,
+    MUT_OVERWRITE_FIXED,
+    MUT_OVERWRITE_FIXED,
+    MUT_OVERWRITE_FIXED,
+    MUT_OVERWRITE_FIXED,
+    MUT_OVERWRITE_FIXED,
+    MUT_OVERWRITE_FIXED,
+    MUT_OVERWRITE_FIXED,
+    MUT_OVERWRITE_FIXED,
+    MUT_BYTEADD,
+    MUT_BYTEADD,
+    MUT_BYTEADD,
+    MUT_BYTEADD,
+    MUT_BYTEADD,
+    MUT_BYTEADD,
+    MUT_BYTESUB,
+    MUT_BYTESUB,
+    MUT_BYTESUB,
+    MUT_BYTESUB,
+    MUT_BYTESUB,
+    MUT_BYTESUB,
+    MUT_FLIP8,
+    MUT_FLIP8,
+    MUT_FLIP8,
+    MUT_FLIP8,
+    MUT_FLIP8,
+    MUT_FLIP8,
+    MUT_FLIP8,
+    MUT_FLIP8,
+    MUT_SWITCH,
+    MUT_SWITCH,
+    MUT_SWITCH,
+    MUT_SWITCH,
+    MUT_SWITCH,
+    MUT_SWITCH,
+    MUT_SWITCH,
+    MUT_SWITCH,
+    MUT_DEL,
+    MUT_DEL,
+    MUT_DEL,
+    MUT_DEL,
+    MUT_DEL,
+    MUT_DEL,
+    MUT_DEL,
+    MUT_SHUFFLE,
+    MUT_SHUFFLE,
+    MUT_SHUFFLE,
+    MUT_SHUFFLE,
+    MUT_SHUFFLE,
+    MUT_SHUFFLE,
+    MUT_SHUFFLE,
+    MUT_SHUFFLE,
+    MUT_DELONE,
+    MUT_DELONE,
+    MUT_DELONE,
+    MUT_DELONE,
+    MUT_DELONE,
+    MUT_DELONE,
+    MUT_DELONE,
+    MUT_INSERTONE,
+    MUT_INSERTONE,
+    MUT_INSERTONE,
+    MUT_INSERTONE,
+    MUT_INSERTONE,
+    MUT_INSERTONE,
+    MUT_ASCIINUM,
+    MUT_ASCIINUM,
+    MUT_ASCIINUM,
+    MUT_ASCIINUM,
+    MUT_ASCIINUM,
+    MUT_ASCIINUM,
+    MUT_ASCIINUM,
+    MUT_ASCIINUM,
+    MUT_INSERTASCIINUM,
+    MUT_INSERTASCIINUM,
+    MUT_INSERTASCIINUM,
+    MUT_INSERTASCIINUM,
+    MUT_INSERTASCIINUM,
+    MUT_INSERTASCIINUM,
+    MUT_INSERTASCIINUM,
+    MUT_INSERTASCIINUM,
+    MUT_EXTRA_OVERWRITE,
+    MUT_EXTRA_OVERWRITE,
+    MUT_EXTRA_OVERWRITE,
+    MUT_EXTRA_OVERWRITE,
+    MUT_EXTRA_OVERWRITE,
+    MUT_EXTRA_OVERWRITE,
+    MUT_EXTRA_OVERWRITE,
+    MUT_EXTRA_OVERWRITE,
+    MUT_EXTRA_INSERT,
+    MUT_EXTRA_INSERT,
+    MUT_EXTRA_INSERT,
+    MUT_EXTRA_INSERT,
+    MUT_EXTRA_INSERT,
+    MUT_EXTRA_INSERT,
+    MUT_EXTRA_INSERT,
+    MUT_EXTRA_INSERT,
+    MUT_AUTO_EXTRA_OVERWRITE,
+    MUT_AUTO_EXTRA_OVERWRITE,
+    MUT_AUTO_EXTRA_OVERWRITE,
+    MUT_AUTO_EXTRA_OVERWRITE,
+    MUT_AUTO_EXTRA_OVERWRITE,
+    MUT_AUTO_EXTRA_OVERWRITE,
+    MUT_AUTO_EXTRA_INSERT,
+    MUT_AUTO_EXTRA_INSERT,
+    MUT_AUTO_EXTRA_INSERT,
+    MUT_AUTO_EXTRA_INSERT,
+    MUT_AUTO_EXTRA_INSERT,
+    MUT_AUTO_EXTRA_INSERT,
+    MUT_SPLICE_OVERWRITE,
+    MUT_SPLICE_OVERWRITE,
+    MUT_SPLICE_OVERWRITE,
+    MUT_SPLICE_OVERWRITE,
+    MUT_SPLICE_OVERWRITE,
+    MUT_SPLICE_OVERWRITE,
+    MUT_SPLICE_OVERWRITE,
+    MUT_SPLICE_OVERWRITE,
+    MUT_SPLICE_OVERWRITE,
+    MUT_SPLICE_INSERT,
+    MUT_SPLICE_INSERT,
+    MUT_SPLICE_INSERT,
+    MUT_SPLICE_INSERT,
+    MUT_SPLICE_INSERT,
+    MUT_SPLICE_INSERT,
+    MUT_SPLICE_INSERT,
+    MUT_SPLICE_INSERT,
+    MUT_SPLICE_INSERT,
+    MUT_SPLICE_INSERT
+
+};
+
+u32 mutation_strategy_exploration_binary[MUT_STRATEGY_ARRAY_SIZE] = {
+
+    MUT_FLIPBIT,
+    MUT_FLIPBIT,
+    MUT_FLIPBIT,
+    MUT_FLIPBIT,
+    MUT_FLIPBIT,
+    MUT_FLIPBIT,
+    MUT_FLIPBIT,
+    MUT_INTERESTING8,
+    MUT_INTERESTING8,
+    MUT_INTERESTING8,
+    MUT_INTERESTING8,
+    MUT_INTERESTING8,
+    MUT_INTERESTING8,
+    MUT_INTERESTING16,
+    MUT_INTERESTING16,
+    MUT_INTERESTING16,
+    MUT_INTERESTING16,
+    MUT_INTERESTING16,
+    MUT_INTERESTING16,
+    MUT_INTERESTING16BE,
+    MUT_INTERESTING16BE,
+    MUT_INTERESTING16BE,
+    MUT_INTERESTING16BE,
+    MUT_INTERESTING16BE,
+    MUT_INTERESTING16BE,
+    MUT_INTERESTING32,
+    MUT_INTERESTING32,
+    MUT_INTERESTING32,
+    MUT_INTERESTING32,
+    MUT_INTERESTING32,
+    MUT_INTERESTING32,
+    MUT_INTERESTING32BE,
+    MUT_INTERESTING32BE,
+    MUT_INTERESTING32BE,
+    MUT_INTERESTING32BE,
+    MUT_INTERESTING32BE,
+    MUT_INTERESTING32BE,
+    MUT_ARITH8_,
+    MUT_ARITH8_,
+    MUT_ARITH8_,
+    MUT_ARITH8_,
+    MUT_ARITH8_,
+    MUT_ARITH8_,
+    MUT_ARITH8_,
+    MUT_ARITH8,
+    MUT_ARITH8,
+    MUT_ARITH8,
+    MUT_ARITH8,
+    MUT_ARITH8,
+    MUT_ARITH8,
+    MUT_ARITH8,
+    MUT_ARITH16_,
+    MUT_ARITH16_,
+    MUT_ARITH16_,
+    MUT_ARITH16_,
+    MUT_ARITH16_,
+    MUT_ARITH16_,
+    MUT_ARITH16BE_,
+    MUT_ARITH16BE_,
+    MUT_ARITH16BE_,
+    MUT_ARITH16BE_,
+    MUT_ARITH16BE_,
+    MUT_ARITH16BE_,
+    MUT_ARITH16,
+    MUT_ARITH16,
+    MUT_ARITH16,
+    MUT_ARITH16,
+    MUT_ARITH16,
+    MUT_ARITH16,
+    MUT_ARITH16BE,
+    MUT_ARITH16BE,
+    MUT_ARITH16BE,
+    MUT_ARITH16BE,
+    MUT_ARITH16BE,
+    MUT_ARITH16BE,
+    MUT_ARITH32_,
+    MUT_ARITH32_,
+    MUT_ARITH32_,
+    MUT_ARITH32_,
+    MUT_ARITH32_,
+    MUT_ARITH32_,
+    MUT_ARITH32BE_,
+    MUT_ARITH32BE_,
+    MUT_ARITH32BE_,
+    MUT_ARITH32BE_,
+    MUT_ARITH32BE_,
+    MUT_ARITH32BE_,
+    MUT_ARITH32,
+    MUT_ARITH32,
+    MUT_ARITH32,
+    MUT_ARITH32,
+    MUT_ARITH32,
+    MUT_ARITH32,
+    MUT_ARITH32,
+    MUT_ARITH32BE,
+    MUT_ARITH32BE,
+    MUT_ARITH32BE,
+    MUT_ARITH32BE,
+    MUT_ARITH32BE,
+    MUT_ARITH32BE,
+    MUT_RAND8,
+    MUT_RAND8,
+    MUT_RAND8,
+    MUT_RAND8,
+    MUT_RAND8,
+    MUT_RAND8,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_FIXED,
+    MUT_CLONE_FIXED,
+    MUT_CLONE_FIXED,
+    MUT_CLONE_FIXED,
+    MUT_CLONE_FIXED,
+    MUT_CLONE_FIXED,
+    MUT_CLONE_FIXED,
+    MUT_CLONE_FIXED,
+    MUT_CLONE_FIXED,
+    MUT_OVERWRITE_COPY,
+    MUT_OVERWRITE_COPY,
+    MUT_OVERWRITE_COPY,
+    MUT_OVERWRITE_COPY,
+    MUT_OVERWRITE_COPY,
+    MUT_OVERWRITE_COPY,
+    MUT_OVERWRITE_COPY,
+    MUT_OVERWRITE_COPY,
+    MUT_OVERWRITE_COPY,
+    MUT_OVERWRITE_FIXED,
+    MUT_OVERWRITE_FIXED,
+    MUT_OVERWRITE_FIXED,
+    MUT_OVERWRITE_FIXED,
+    MUT_OVERWRITE_FIXED,
+    MUT_OVERWRITE_FIXED,
+    MUT_OVERWRITE_FIXED,
+    MUT_BYTEADD,
+    MUT_BYTEADD,
+    MUT_BYTEADD,
+    MUT_BYTEADD,
+    MUT_BYTEADD,
+    MUT_BYTEADD,
+    MUT_BYTEADD,
+    MUT_BYTESUB,
+    MUT_BYTESUB,
+    MUT_BYTESUB,
+    MUT_BYTESUB,
+    MUT_BYTESUB,
+    MUT_BYTESUB,
+    MUT_BYTESUB,
+    MUT_FLIP8,
+    MUT_FLIP8,
+    MUT_FLIP8,
+    MUT_FLIP8,
+    MUT_FLIP8,
+    MUT_FLIP8,
+    MUT_FLIP8,
+    MUT_FLIP8,
+    MUT_FLIP8,
+    MUT_FLIP8,
+    MUT_SWITCH,
+    MUT_SWITCH,
+    MUT_SWITCH,
+    MUT_SWITCH,
+    MUT_SWITCH,
+    MUT_SWITCH,
+    MUT_SWITCH,
+    MUT_DEL,
+    MUT_DEL,
+    MUT_DEL,
+    MUT_DEL,
+    MUT_DEL,
+    MUT_DEL,
+    MUT_SHUFFLE,
+    MUT_SHUFFLE,
+    MUT_SHUFFLE,
+    MUT_SHUFFLE,
+    MUT_SHUFFLE,
+    MUT_SHUFFLE,
+    MUT_DELONE,
+    MUT_DELONE,
+    MUT_DELONE,
+    MUT_DELONE,
+    MUT_DELONE,
+    MUT_DELONE,
+    MUT_INSERTONE,
+    MUT_INSERTONE,
+    MUT_INSERTONE,
+    MUT_INSERTONE,
+    MUT_INSERTONE,
+    MUT_INSERTONE,
+    MUT_ASCIINUM,
+    MUT_ASCIINUM,
+    MUT_ASCIINUM,
+    MUT_ASCIINUM,
+    MUT_ASCIINUM,
+    MUT_ASCIINUM,
+    MUT_INSERTASCIINUM,
+    MUT_INSERTASCIINUM,
+    MUT_INSERTASCIINUM,
+    MUT_INSERTASCIINUM,
+    MUT_INSERTASCIINUM,
+    MUT_INSERTASCIINUM,
+    MUT_EXTRA_OVERWRITE,
+    MUT_EXTRA_OVERWRITE,
+    MUT_EXTRA_OVERWRITE,
+    MUT_EXTRA_OVERWRITE,
+    MUT_EXTRA_OVERWRITE,
+    MUT_EXTRA_OVERWRITE,
+    MUT_EXTRA_OVERWRITE,
+    MUT_EXTRA_INSERT,
+    MUT_EXTRA_INSERT,
+    MUT_EXTRA_INSERT,
+    MUT_EXTRA_INSERT,
+    MUT_EXTRA_INSERT,
+    MUT_EXTRA_INSERT,
+    MUT_EXTRA_INSERT,
+    MUT_AUTO_EXTRA_OVERWRITE,
+    MUT_AUTO_EXTRA_OVERWRITE,
+    MUT_AUTO_EXTRA_OVERWRITE,
+    MUT_AUTO_EXTRA_OVERWRITE,
+    MUT_AUTO_EXTRA_OVERWRITE,
+    MUT_AUTO_EXTRA_OVERWRITE,
+    MUT_AUTO_EXTRA_INSERT,
+    MUT_AUTO_EXTRA_INSERT,
+    MUT_AUTO_EXTRA_INSERT,
+    MUT_AUTO_EXTRA_INSERT,
+    MUT_AUTO_EXTRA_INSERT,
+    MUT_AUTO_EXTRA_INSERT,
+    MUT_SPLICE_OVERWRITE,
+    MUT_SPLICE_OVERWRITE,
+    MUT_SPLICE_OVERWRITE,
+    MUT_SPLICE_OVERWRITE,
+    MUT_SPLICE_OVERWRITE,
+    MUT_SPLICE_OVERWRITE,
+    MUT_SPLICE_OVERWRITE,
+    MUT_SPLICE_OVERWRITE,
+    MUT_SPLICE_INSERT,
+    MUT_SPLICE_INSERT,
+    MUT_SPLICE_INSERT,
+    MUT_SPLICE_INSERT,
+    MUT_SPLICE_INSERT,
+    MUT_SPLICE_INSERT,
+    MUT_SPLICE_INSERT,
+    MUT_SPLICE_INSERT,
+    MUT_SPLICE_INSERT,
+    MUT_SPLICE_INSERT
+
+};
+
+u32 mutation_strategy_exploitation_text[MUT_STRATEGY_ARRAY_SIZE] = {
+
+    MUT_FLIPBIT,
+    MUT_FLIPBIT,
+    MUT_FLIPBIT,
+    MUT_FLIPBIT,
+    MUT_FLIPBIT,
+    MUT_FLIPBIT,
+    MUT_FLIPBIT,
+    MUT_INTERESTING8,
+    MUT_INTERESTING8,
+    MUT_INTERESTING8,
+    MUT_INTERESTING8,
+    MUT_INTERESTING8,
+    MUT_INTERESTING8,
+    MUT_INTERESTING8,
+    MUT_INTERESTING16,
+    MUT_INTERESTING16,
+    MUT_INTERESTING16,
+    MUT_INTERESTING16,
+    MUT_INTERESTING16,
+    MUT_INTERESTING16,
+    MUT_INTERESTING16,
+    MUT_INTERESTING16BE,
+    MUT_INTERESTING16BE,
+    MUT_INTERESTING16BE,
+    MUT_INTERESTING16BE,
+    MUT_INTERESTING16BE,
+    MUT_INTERESTING16BE,
+    MUT_INTERESTING16BE,
+    MUT_INTERESTING32,
+    MUT_INTERESTING32,
+    MUT_INTERESTING32,
+    MUT_INTERESTING32,
+    MUT_INTERESTING32,
+    MUT_INTERESTING32,
+    MUT_INTERESTING32,
+    MUT_INTERESTING32,
+    MUT_INTERESTING32BE,
+    MUT_INTERESTING32BE,
+    MUT_INTERESTING32BE,
+    MUT_INTERESTING32BE,
+    MUT_INTERESTING32BE,
+    MUT_INTERESTING32BE,
+    MUT_INTERESTING32BE,
+    MUT_INTERESTING32BE,
+    MUT_ARITH8_,
+    MUT_ARITH8_,
+    MUT_ARITH8_,
+    MUT_ARITH8_,
+    MUT_ARITH8_,
+    MUT_ARITH8_,
+    MUT_ARITH8,
+    MUT_ARITH8,
+    MUT_ARITH8,
+    MUT_ARITH8,
+    MUT_ARITH8,
+    MUT_ARITH8,
+    MUT_ARITH8,
+    MUT_ARITH16_,
+    MUT_ARITH16_,
+    MUT_ARITH16_,
+    MUT_ARITH16_,
+    MUT_ARITH16_,
+    MUT_ARITH16_,
+    MUT_ARITH16BE_,
+    MUT_ARITH16BE_,
+    MUT_ARITH16BE_,
+    MUT_ARITH16BE_,
+    MUT_ARITH16BE_,
+    MUT_ARITH16BE_,
+    MUT_ARITH16BE_,
+    MUT_ARITH16,
+    MUT_ARITH16,
+    MUT_ARITH16,
+    MUT_ARITH16,
+    MUT_ARITH16,
+    MUT_ARITH16,
+    MUT_ARITH16,
+    MUT_ARITH16BE,
+    MUT_ARITH16BE,
+    MUT_ARITH16BE,
+    MUT_ARITH16BE,
+    MUT_ARITH16BE,
+    MUT_ARITH16BE,
+    MUT_ARITH16BE,
+    MUT_ARITH32_,
+    MUT_ARITH32_,
+    MUT_ARITH32_,
+    MUT_ARITH32_,
+    MUT_ARITH32_,
+    MUT_ARITH32_,
+    MUT_ARITH32BE_,
+    MUT_ARITH32BE_,
+    MUT_ARITH32BE_,
+    MUT_ARITH32BE_,
+    MUT_ARITH32BE_,
+    MUT_ARITH32BE_,
+    MUT_ARITH32,
+    MUT_ARITH32,
+    MUT_ARITH32,
+    MUT_ARITH32,
+    MUT_ARITH32,
+    MUT_ARITH32,
+    MUT_ARITH32BE,
+    MUT_ARITH32BE,
+    MUT_ARITH32BE,
+    MUT_ARITH32BE,
+    MUT_ARITH32BE,
+    MUT_ARITH32BE,
+    MUT_ARITH32BE,
+    MUT_RAND8,
+    MUT_RAND8,
+    MUT_RAND8,
+    MUT_RAND8,
+    MUT_RAND8,
+    MUT_RAND8,
+    MUT_RAND8,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_FIXED,
+    MUT_CLONE_FIXED,
+    MUT_CLONE_FIXED,
+    MUT_CLONE_FIXED,
+    MUT_CLONE_FIXED,
+    MUT_CLONE_FIXED,
+    MUT_CLONE_FIXED,
+    MUT_CLONE_FIXED,
+    MUT_OVERWRITE_COPY,
+    MUT_OVERWRITE_COPY,
+    MUT_OVERWRITE_COPY,
+    MUT_OVERWRITE_COPY,
+    MUT_OVERWRITE_COPY,
+    MUT_OVERWRITE_COPY,
+    MUT_OVERWRITE_FIXED,
+    MUT_OVERWRITE_FIXED,
+    MUT_OVERWRITE_FIXED,
+    MUT_OVERWRITE_FIXED,
+    MUT_OVERWRITE_FIXED,
+    MUT_OVERWRITE_FIXED,
+    MUT_BYTEADD,
+    MUT_BYTEADD,
+    MUT_BYTEADD,
+    MUT_BYTEADD,
+    MUT_BYTEADD,
+    MUT_BYTEADD,
+    MUT_BYTEADD,
+    MUT_BYTESUB,
+    MUT_BYTESUB,
+    MUT_BYTESUB,
+    MUT_BYTESUB,
+    MUT_BYTESUB,
+    MUT_BYTESUB,
+    MUT_FLIP8,
+    MUT_FLIP8,
+    MUT_FLIP8,
+    MUT_FLIP8,
+    MUT_FLIP8,
+    MUT_FLIP8,
+    MUT_FLIP8,
+    MUT_FLIP8,
+    MUT_FLIP8,
+    MUT_SWITCH,
+    MUT_SWITCH,
+    MUT_SWITCH,
+    MUT_SWITCH,
+    MUT_SWITCH,
+    MUT_SWITCH,
+    MUT_SWITCH,
+    MUT_DEL,
+    MUT_DEL,
+    MUT_DEL,
+    MUT_DEL,
+    MUT_DEL,
+    MUT_DEL,
+    MUT_SHUFFLE,
+    MUT_SHUFFLE,
+    MUT_SHUFFLE,
+    MUT_SHUFFLE,
+    MUT_SHUFFLE,
+    MUT_SHUFFLE,
+    MUT_SHUFFLE,
+    MUT_DELONE,
+    MUT_DELONE,
+    MUT_DELONE,
+    MUT_DELONE,
+    MUT_DELONE,
+    MUT_INSERTONE,
+    MUT_INSERTONE,
+    MUT_INSERTONE,
+    MUT_INSERTONE,
+    MUT_INSERTONE,
+    MUT_INSERTONE,
+    MUT_ASCIINUM,
+    MUT_ASCIINUM,
+    MUT_ASCIINUM,
+    MUT_ASCIINUM,
+    MUT_ASCIINUM,
+    MUT_ASCIINUM,
+    MUT_INSERTASCIINUM,
+    MUT_INSERTASCIINUM,
+    MUT_INSERTASCIINUM,
+    MUT_INSERTASCIINUM,
+    MUT_INSERTASCIINUM,
+    MUT_INSERTASCIINUM,
+    MUT_INSERTASCIINUM,
+    MUT_INSERTASCIINUM,
+    MUT_EXTRA_OVERWRITE,
+    MUT_EXTRA_OVERWRITE,
+    MUT_EXTRA_OVERWRITE,
+    MUT_EXTRA_OVERWRITE,
+    MUT_EXTRA_OVERWRITE,
+    MUT_EXTRA_OVERWRITE,
+    MUT_EXTRA_OVERWRITE,
+    MUT_EXTRA_INSERT,
+    MUT_EXTRA_INSERT,
+    MUT_EXTRA_INSERT,
+    MUT_EXTRA_INSERT,
+    MUT_EXTRA_INSERT,
+    MUT_EXTRA_INSERT,
+    MUT_EXTRA_INSERT,
+    MUT_AUTO_EXTRA_OVERWRITE,
+    MUT_AUTO_EXTRA_OVERWRITE,
+    MUT_AUTO_EXTRA_OVERWRITE,
+    MUT_AUTO_EXTRA_OVERWRITE,
+    MUT_AUTO_EXTRA_OVERWRITE,
+    MUT_AUTO_EXTRA_OVERWRITE,
+    MUT_AUTO_EXTRA_OVERWRITE,
+    MUT_AUTO_EXTRA_INSERT,
+    MUT_AUTO_EXTRA_INSERT,
+    MUT_AUTO_EXTRA_INSERT,
+    MUT_AUTO_EXTRA_INSERT,
+    MUT_AUTO_EXTRA_INSERT,
+    MUT_AUTO_EXTRA_INSERT,
+    MUT_AUTO_EXTRA_INSERT,
+    MUT_SPLICE_OVERWRITE,
+    MUT_SPLICE_OVERWRITE,
+    MUT_SPLICE_OVERWRITE,
+    MUT_SPLICE_OVERWRITE,
+    MUT_SPLICE_OVERWRITE,
+    MUT_SPLICE_OVERWRITE,
+    MUT_SPLICE_OVERWRITE,
+    MUT_SPLICE_INSERT,
+    MUT_SPLICE_INSERT,
+    MUT_SPLICE_INSERT,
+    MUT_SPLICE_INSERT,
+    MUT_SPLICE_INSERT,
+    MUT_SPLICE_INSERT,
+    MUT_SPLICE_INSERT,
+    MUT_SPLICE_INSERT,
+    MUT_SPLICE_INSERT
+
+};
+
+u32 mutation_strategy_exploitation_binary[MUT_STRATEGY_ARRAY_SIZE] = {
+
+    MUT_FLIPBIT,
+    MUT_FLIPBIT,
+    MUT_FLIPBIT,
+    MUT_FLIPBIT,
+    MUT_FLIPBIT,
+    MUT_FLIPBIT,
+    MUT_FLIPBIT,
+    MUT_INTERESTING8,
+    MUT_INTERESTING8,
+    MUT_INTERESTING8,
+    MUT_INTERESTING8,
+    MUT_INTERESTING8,
+    MUT_INTERESTING8,
+    MUT_INTERESTING8,
+    MUT_INTERESTING16,
+    MUT_INTERESTING16,
+    MUT_INTERESTING16,
+    MUT_INTERESTING16,
+    MUT_INTERESTING16,
+    MUT_INTERESTING16,
+    MUT_INTERESTING16,
+    MUT_INTERESTING16BE,
+    MUT_INTERESTING16BE,
+    MUT_INTERESTING16BE,
+    MUT_INTERESTING16BE,
+    MUT_INTERESTING16BE,
+    MUT_INTERESTING16BE,
+    MUT_INTERESTING16BE,
+    MUT_INTERESTING32,
+    MUT_INTERESTING32,
+    MUT_INTERESTING32,
+    MUT_INTERESTING32,
+    MUT_INTERESTING32,
+    MUT_INTERESTING32,
+    MUT_INTERESTING32,
+    MUT_INTERESTING32,
+    MUT_INTERESTING32BE,
+    MUT_INTERESTING32BE,
+    MUT_INTERESTING32BE,
+    MUT_INTERESTING32BE,
+    MUT_INTERESTING32BE,
+    MUT_INTERESTING32BE,
+    MUT_INTERESTING32BE,
+    MUT_INTERESTING32BE,
+    MUT_ARITH8_,
+    MUT_ARITH8_,
+    MUT_ARITH8_,
+    MUT_ARITH8_,
+    MUT_ARITH8_,
+    MUT_ARITH8_,
+    MUT_ARITH8,
+    MUT_ARITH8,
+    MUT_ARITH8,
+    MUT_ARITH8,
+    MUT_ARITH8,
+    MUT_ARITH8,
+    MUT_ARITH8,
+    MUT_ARITH16_,
+    MUT_ARITH16_,
+    MUT_ARITH16_,
+    MUT_ARITH16_,
+    MUT_ARITH16_,
+    MUT_ARITH16_,
+    MUT_ARITH16BE_,
+    MUT_ARITH16BE_,
+    MUT_ARITH16BE_,
+    MUT_ARITH16BE_,
+    MUT_ARITH16BE_,
+    MUT_ARITH16BE_,
+    MUT_ARITH16BE_,
+    MUT_ARITH16,
+    MUT_ARITH16,
+    MUT_ARITH16,
+    MUT_ARITH16,
+    MUT_ARITH16,
+    MUT_ARITH16,
+    MUT_ARITH16,
+    MUT_ARITH16BE,
+    MUT_ARITH16BE,
+    MUT_ARITH16BE,
+    MUT_ARITH16BE,
+    MUT_ARITH16BE,
+    MUT_ARITH16BE,
+    MUT_ARITH16BE,
+    MUT_ARITH32_,
+    MUT_ARITH32_,
+    MUT_ARITH32_,
+    MUT_ARITH32_,
+    MUT_ARITH32_,
+    MUT_ARITH32_,
+    MUT_ARITH32BE_,
+    MUT_ARITH32BE_,
+    MUT_ARITH32BE_,
+    MUT_ARITH32BE_,
+    MUT_ARITH32BE_,
+    MUT_ARITH32BE_,
+    MUT_ARITH32BE_,
+    MUT_ARITH32,
+    MUT_ARITH32,
+    MUT_ARITH32,
+    MUT_ARITH32,
+    MUT_ARITH32,
+    MUT_ARITH32,
+    MUT_ARITH32,
+    MUT_ARITH32BE,
+    MUT_ARITH32BE,
+    MUT_ARITH32BE,
+    MUT_ARITH32BE,
+    MUT_ARITH32BE,
+    MUT_ARITH32BE,
+    MUT_ARITH32BE,
+    MUT_RAND8,
+    MUT_RAND8,
+    MUT_RAND8,
+    MUT_RAND8,
+    MUT_RAND8,
+    MUT_RAND8,
+    MUT_RAND8,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
+    MUT_CLONE_FIXED,
+    MUT_CLONE_FIXED,
+    MUT_CLONE_FIXED,
+    MUT_CLONE_FIXED,
+    MUT_CLONE_FIXED,
+    MUT_CLONE_FIXED,
+    MUT_CLONE_FIXED,
+    MUT_CLONE_FIXED,
+    MUT_OVERWRITE_COPY,
+    MUT_OVERWRITE_COPY,
+    MUT_OVERWRITE_COPY,
+    MUT_OVERWRITE_COPY,
+    MUT_OVERWRITE_COPY,
+    MUT_OVERWRITE_COPY,
+    MUT_OVERWRITE_FIXED,
+    MUT_OVERWRITE_FIXED,
+    MUT_OVERWRITE_FIXED,
+    MUT_OVERWRITE_FIXED,
+    MUT_OVERWRITE_FIXED,
+    MUT_OVERWRITE_FIXED,
+    MUT_BYTEADD,
+    MUT_BYTEADD,
+    MUT_BYTEADD,
+    MUT_BYTEADD,
+    MUT_BYTEADD,
+    MUT_BYTEADD,
+    MUT_BYTEADD,
+    MUT_BYTESUB,
+    MUT_BYTESUB,
+    MUT_BYTESUB,
+    MUT_BYTESUB,
+    MUT_BYTESUB,
+    MUT_BYTESUB,
+    MUT_FLIP8,
+    MUT_FLIP8,
+    MUT_FLIP8,
+    MUT_FLIP8,
+    MUT_FLIP8,
+    MUT_FLIP8,
+    MUT_FLIP8,
+    MUT_FLIP8,
+    MUT_FLIP8,
+    MUT_FLIP8,
+    MUT_SWITCH,
+    MUT_SWITCH,
+    MUT_SWITCH,
+    MUT_SWITCH,
+    MUT_SWITCH,
+    MUT_SWITCH,
+    MUT_SWITCH,
+    MUT_DEL,
+    MUT_DEL,
+    MUT_DEL,
+    MUT_DEL,
+    MUT_DEL,
+    MUT_DEL,
+    MUT_SHUFFLE,
+    MUT_SHUFFLE,
+    MUT_SHUFFLE,
+    MUT_SHUFFLE,
+    MUT_SHUFFLE,
+    MUT_SHUFFLE,
+    MUT_DELONE,
+    MUT_DELONE,
+    MUT_DELONE,
+    MUT_DELONE,
+    MUT_DELONE,
+    MUT_INSERTONE,
+    MUT_INSERTONE,
+    MUT_INSERTONE,
+    MUT_INSERTONE,
+    MUT_INSERTONE,
+    MUT_INSERTONE,
+    MUT_ASCIINUM,
+    MUT_ASCIINUM,
+    MUT_ASCIINUM,
+    MUT_ASCIINUM,
+    MUT_ASCIINUM,
+    MUT_INSERTASCIINUM,
+    MUT_INSERTASCIINUM,
+    MUT_INSERTASCIINUM,
+    MUT_INSERTASCIINUM,
+    MUT_INSERTASCIINUM,
+    MUT_INSERTASCIINUM,
+    MUT_INSERTASCIINUM,
+    MUT_EXTRA_OVERWRITE,
+    MUT_EXTRA_OVERWRITE,
+    MUT_EXTRA_OVERWRITE,
+    MUT_EXTRA_OVERWRITE,
+    MUT_EXTRA_OVERWRITE,
+    MUT_EXTRA_OVERWRITE,
+    MUT_EXTRA_OVERWRITE,
+    MUT_EXTRA_INSERT,
+    MUT_EXTRA_INSERT,
+    MUT_EXTRA_INSERT,
+    MUT_EXTRA_INSERT,
+    MUT_EXTRA_INSERT,
+    MUT_EXTRA_INSERT,
+    MUT_EXTRA_INSERT,
+    MUT_AUTO_EXTRA_OVERWRITE,
+    MUT_AUTO_EXTRA_OVERWRITE,
+    MUT_AUTO_EXTRA_OVERWRITE,
+    MUT_AUTO_EXTRA_OVERWRITE,
+    MUT_AUTO_EXTRA_OVERWRITE,
+    MUT_AUTO_EXTRA_OVERWRITE,
+    MUT_AUTO_EXTRA_OVERWRITE,
+    MUT_AUTO_EXTRA_INSERT,
+    MUT_AUTO_EXTRA_INSERT,
+    MUT_AUTO_EXTRA_INSERT,
+    MUT_AUTO_EXTRA_INSERT,
+    MUT_AUTO_EXTRA_INSERT,
+    MUT_AUTO_EXTRA_INSERT,
+    MUT_AUTO_EXTRA_INSERT,
+    MUT_SPLICE_OVERWRITE,
+    MUT_SPLICE_OVERWRITE,
+    MUT_SPLICE_OVERWRITE,
+    MUT_SPLICE_OVERWRITE,
+    MUT_SPLICE_OVERWRITE,
+    MUT_SPLICE_OVERWRITE,
+    MUT_SPLICE_OVERWRITE,
+    MUT_SPLICE_INSERT,
+    MUT_SPLICE_INSERT,
+    MUT_SPLICE_INSERT,
+    MUT_SPLICE_INSERT,
+    MUT_SPLICE_INSERT,
+    MUT_SPLICE_INSERT,
+    MUT_SPLICE_INSERT,
+    MUT_SPLICE_INSERT,
+    MUT_SPLICE_INSERT
+
+};
+
+u32 afl_mutate(afl_state_t *, u8 *, u32, u32, bool, bool, u8 *, u32, u32);
+u32 choose_block_len(afl_state_t *, u32);
+
+/* Helper to choose random block len for block operations in fuzz_one().
+   Doesn't return zero, provided that max_len is > 0. */
+
+inline u32 choose_block_len(afl_state_t *afl, u32 limit) {
+
+  u32 min_value, max_value;
+  u32 rlim = MIN(afl->queue_cycle, (u32)3);
+
+  if (unlikely(!afl->run_over10m)) { rlim = 1; }
+
+  switch (rand_below(afl, rlim)) {
+
+    case 0:
+      min_value = 1;
+      max_value = HAVOC_BLK_SMALL;
+      break;
+
+    case 1:
+      min_value = HAVOC_BLK_SMALL;
+      max_value = HAVOC_BLK_MEDIUM;
+      break;
+
+    default:
+
+      if (likely(rand_below(afl, 10))) {
+
+        min_value = HAVOC_BLK_MEDIUM;
+        max_value = HAVOC_BLK_LARGE;
+
+      } else {
+
+        min_value = HAVOC_BLK_LARGE;
+        max_value = HAVOC_BLK_XL;
+
+      }
+
+  }
+
+  if (min_value >= limit) { min_value = 1; }
+
+  return min_value + rand_below(afl, MIN(max_value, limit) - min_value + 1);
+
+}
+
+inline u32 afl_mutate(afl_state_t *afl, u8 *buf, u32 len, u32 steps,
+                      bool is_text, bool is_exploration, u8 *splice_buf,
+                      u32 splice_len, u32 max_len) {
+
+  if (!buf || !len) { return 0; }
+
+  u32       *mutation_array;
+  static u8 *tmp_buf = NULL;
+  static u32 tmp_buf_size = 0;
+
+  if (max_len > tmp_buf_size) {
+
+    if (tmp_buf) {
+
+      u8 *ptr = realloc(tmp_buf, max_len);
+
+      if (!ptr) {
+
+        return 0;
+
+      } else {
+
+        tmp_buf = ptr;
+
+      }
+
+    } else {
+
+      if ((tmp_buf = malloc(max_len)) == NULL) { return 0; }
+
+    }
+
+    tmp_buf_size = max_len;
+
+  }
+
+  if (is_text) {
+
+    if (is_exploration) {
+
+      mutation_array = (u32 *)&mutation_strategy_exploration_text;
+
+    } else {
+
+      mutation_array = (u32 *)&mutation_strategy_exploitation_text;
+
+    }
+
+  } else {
+
+    if (is_exploration) {
+
+      mutation_array = (u32 *)&mutation_strategy_exploration_binary;
+
+    } else {
+
+      mutation_array = (u32 *)&mutation_strategy_exploitation_binary;
+
+    }
+
+  }
+
+  for (u32 step = 0; step < steps; ++step) {
+
+  retry_havoc_step : {
+
+    u32 r = rand_below(afl, MUT_STRATEGY_ARRAY_SIZE), item;
+
+    switch (mutation_array[r]) {
+
+      case MUT_FLIPBIT: {
+
+        /* Flip a single bit somewhere. Spooky! */
+        u8  bit = rand_below(afl, 8);
+        u32 off = rand_below(afl, len);
+        buf[off] ^= 1 << bit;
+
+        break;
+
+      }
+
+      case MUT_INTERESTING8: {
+
+        /* Set byte to interesting value. */
+
+        item = rand_below(afl, sizeof(interesting_8));
+        buf[rand_below(afl, len)] = interesting_8[item];
+        break;
+
+      }
+
+      case MUT_INTERESTING16: {
+
+        /* Set word to interesting value, little endian. */
+
+        if (unlikely(len < 2)) { break; }  // no retry
+
+        item = rand_below(afl, sizeof(interesting_16) >> 1);
+        *(u16 *)(buf + rand_below(afl, len - 1)) = interesting_16[item];
+
+        break;
+
+      }
+
+      case MUT_INTERESTING16BE: {
+
+        /* Set word to interesting value, big endian. */
+
+        if (unlikely(len < 2)) { break; }  // no retry
+
+        item = rand_below(afl, sizeof(interesting_16) >> 1);
+        *(u16 *)(buf + rand_below(afl, len - 1)) = SWAP16(interesting_16[item]);
+
+        break;
+
+      }
+
+      case MUT_INTERESTING32: {
+
+        /* Set dword to interesting value, little endian. */
+
+        if (unlikely(len < 4)) { break; }  // no retry
+
+        item = rand_below(afl, sizeof(interesting_32) >> 2);
+        *(u32 *)(buf + rand_below(afl, len - 3)) = interesting_32[item];
+
+        break;
+
+      }
+
+      case MUT_INTERESTING32BE: {
+
+        /* Set dword to interesting value, big endian. */
+
+        if (unlikely(len < 4)) { break; }  // no retry
+
+        item = rand_below(afl, sizeof(interesting_32) >> 2);
+        *(u32 *)(buf + rand_below(afl, len - 3)) = SWAP32(interesting_32[item]);
+
+        break;
+
+      }
+
+      case MUT_ARITH8_: {
+
+        /* Randomly subtract from byte. */
+
+        item = 1 + rand_below(afl, ARITH_MAX);
+        buf[rand_below(afl, len)] -= item;
+        break;
+
+      }
+
+      case MUT_ARITH8: {
+
+        /* Randomly add to byte. */
+
+        item = 1 + rand_below(afl, ARITH_MAX);
+        buf[rand_below(afl, len)] += item;
+        break;
+
+      }
+
+      case MUT_ARITH16_: {
+
+        /* Randomly subtract from word, little endian. */
+
+        if (unlikely(len < 2)) { break; }  // no retry
+
+        u32 pos = rand_below(afl, len - 1);
+        item = 1 + rand_below(afl, ARITH_MAX);
+        *(u16 *)(buf + pos) -= item;
+
+        break;
+
+      }
+
+      case MUT_ARITH16BE_: {
+
+        /* Randomly subtract from word, big endian. */
+
+        if (unlikely(len < 2)) { break; }  // no retry
+
+        u32 pos = rand_below(afl, len - 1);
+        u16 num = 1 + rand_below(afl, ARITH_MAX);
+        *(u16 *)(buf + pos) = SWAP16(SWAP16(*(u16 *)(buf + pos)) - num);
+
+        break;
+
+      }
+
+      case MUT_ARITH16: {
+
+        /* Randomly add to word, little endian. */
+
+        if (unlikely(len < 2)) { break; }  // no retry
+
+        u32 pos = rand_below(afl, len - 1);
+        item = 1 + rand_below(afl, ARITH_MAX);
+        *(u16 *)(buf + pos) += item;
+
+        break;
+
+      }
+
+      case MUT_ARITH16BE: {
+
+        /* Randomly add to word, big endian. */
+
+        if (unlikely(len < 2)) { break; }  // no retry
+
+        u32 pos = rand_below(afl, len - 1);
+        u16 num = 1 + rand_below(afl, ARITH_MAX);
+        *(u16 *)(buf + pos) = SWAP16(SWAP16(*(u16 *)(buf + pos)) + num);
+
+        break;
+
+      }
+
+      case MUT_ARITH32_: {
+
+        /* Randomly subtract from dword, little endian. */
+
+        if (unlikely(len < 4)) { break; }  // no retry
+
+        u32 pos = rand_below(afl, len - 3);
+        item = 1 + rand_below(afl, ARITH_MAX);
+        *(u32 *)(buf + pos) -= item;
+
+        break;
+
+      }
+
+      case MUT_ARITH32BE_: {
+
+        /* Randomly subtract from dword, big endian. */
+
+        if (unlikely(len < 4)) { break; }  // no retry
+
+        u32 pos = rand_below(afl, len - 3);
+        u32 num = 1 + rand_below(afl, ARITH_MAX);
+        *(u32 *)(buf + pos) = SWAP32(SWAP32(*(u32 *)(buf + pos)) - num);
+
+        break;
+
+      }
+
+      case MUT_ARITH32: {
+
+        /* Randomly add to dword, little endian. */
+
+        if (unlikely(len < 4)) { break; }  // no retry
+
+        u32 pos = rand_below(afl, len - 3);
+        item = 1 + rand_below(afl, ARITH_MAX);
+        *(u32 *)(buf + pos) += item;
+
+        break;
+
+      }
+
+      case MUT_ARITH32BE: {
+
+        /* Randomly add to dword, big endian. */
+
+        if (unlikely(len < 4)) { break; }  // no retry
+
+        u32 pos = rand_below(afl, len - 3);
+        u32 num = 1 + rand_below(afl, ARITH_MAX);
+        *(u32 *)(buf + pos) = SWAP32(SWAP32(*(u32 *)(buf + pos)) + num);
+
+        break;
+
+      }
+
+      case MUT_RAND8: {
+
+        /* Just set a random byte to a random value. Because,
+           why not. We use XOR with 1-255 to eliminate the
+           possibility of a no-op. */
+
+        u32 pos = rand_below(afl, len);
+        item = 1 + rand_below(afl, 255);
+        buf[pos] ^= item;
+        break;
+
+      }
+
+      case MUT_CLONE_COPY: {
+
+        if (likely(len + HAVOC_BLK_XL < max_len)) {
+
+          /* Clone bytes. */
+
+          u32 clone_len = choose_block_len(afl, len);
+          u32 clone_from = rand_below(afl, len - clone_len + 1);
+          u32 clone_to = rand_below(afl, len);
+
+          /* Head */
+
+          memcpy(tmp_buf, buf, clone_to);
+
+          /* Inserted part */
+
+          memcpy(tmp_buf + clone_to, buf + clone_from, clone_len);
+
+          /* Tail */
+          memcpy(tmp_buf + clone_to + clone_len, buf + clone_to,
+                 len - clone_to);
+
+          len += clone_len;
+          memcpy(buf, tmp_buf, len);
+
+        } else if (unlikely(len < 8)) {
+
+          break;
+
+        } else {
+
+          goto retry_havoc_step;
+
+        }
+
+        break;
+
+      }
+
+      case MUT_CLONE_FIXED: {
+
+        if (likely(len + HAVOC_BLK_XL < max_len)) {
+
+          /* Insert a block of constant bytes (25%). */
+
+          u32 clone_len = choose_block_len(afl, HAVOC_BLK_XL);
+          u32 clone_to = rand_below(afl, len);
+          u32 strat = rand_below(afl, 2);
+          u32 clone_from = clone_to ? clone_to - 1 : 0;
+          item = strat ? rand_below(afl, 256) : buf[clone_from];
+
+          /* Head */
+
+          memcpy(tmp_buf, buf, clone_to);
+
+          /* Inserted part */
+
+          memset(tmp_buf + clone_to, item, clone_len);
+
+          /* Tail */
+          memcpy(tmp_buf + clone_to + clone_len, buf + clone_to,
+                 len - clone_to);
+
+          len += clone_len;
+          memcpy(buf, tmp_buf, len);
+
+        } else if (unlikely(len < 8)) {
+
+          break;
+
+        } else {
+
+          goto retry_havoc_step;
+
+        }
+
+        break;
+
+      }
+
+      case MUT_OVERWRITE_COPY: {
+
+        /* Overwrite bytes with a randomly selected chunk bytes. */
+
+        if (unlikely(len < 2)) { break; }  // no retry
+
+        u32 copy_len = choose_block_len(afl, len - 1);
+        u32 copy_from = rand_below(afl, len - copy_len + 1);
+        u32 copy_to = rand_below(afl, len - copy_len + 1);
+
+        if (likely(copy_from != copy_to)) {
+
+          memmove(buf + copy_to, buf + copy_from, copy_len);
+
+        }
+
+        break;
+
+      }
+
+      case MUT_OVERWRITE_FIXED: {
+
+        /* Overwrite bytes with fixed bytes. */
+
+        if (unlikely(len < 2)) { break; }  // no retry
+
+        u32 copy_len = choose_block_len(afl, len - 1);
+        u32 copy_to = rand_below(afl, len - copy_len + 1);
+        u32 strat = rand_below(afl, 2);
+        u32 copy_from = copy_to ? copy_to - 1 : 0;
+        item = strat ? rand_below(afl, 256) : buf[copy_from];
+        memset(buf + copy_to, item, copy_len);
+
+        break;
+
+      }
+
+      case MUT_BYTEADD: {
+
+        /* Increase byte by 1. */
+
+        buf[rand_below(afl, len)]++;
+        break;
+
+      }
+
+      case MUT_BYTESUB: {
+
+        /* Decrease byte by 1. */
+
+        buf[rand_below(afl, len)]--;
+        break;
+
+      }
+
+      case MUT_FLIP8: {
+
+        /* Flip byte. */
+
+        buf[rand_below(afl, len)] ^= 0xff;
+        break;
+
+      }
+
+      case MUT_SWITCH: {
+
+        if (unlikely(len < 4)) { break; }  // no retry
+
+        /* Switch bytes. */
+
+        u32 to_end, switch_to, switch_len, switch_from;
+        switch_from = rand_below(afl, len);
+        do {
+
+          switch_to = rand_below(afl, len);
+
+        } while (unlikely(switch_from == switch_to));
+
+        if (switch_from < switch_to) {
+
+          switch_len = switch_to - switch_from;
+          to_end = len - switch_to;
+
+        } else {
+
+          switch_len = switch_from - switch_to;
+          to_end = len - switch_from;
+
+        }
+
+        switch_len = choose_block_len(afl, MIN(switch_len, to_end));
+
+        /* Backup */
+
+        memcpy(tmp_buf, buf + switch_from, switch_len);
+
+        /* Switch 1 */
+
+        memcpy(buf + switch_from, buf + switch_to, switch_len);
+
+        /* Switch 2 */
+
+        memcpy(buf + switch_to, tmp_buf, switch_len);
+
+        break;
+
+      }
+
+      case MUT_DEL: {
+
+        /* Delete bytes. */
+
+        if (unlikely(len < 2)) { break; }  // no retry
+
+        /* Don't delete too much. */
+
+        u32 del_len = choose_block_len(afl, len - 1);
+        u32 del_from = rand_below(afl, len - del_len + 1);
+        memmove(buf + del_from, buf + del_from + del_len,
+                len - del_from - del_len);
+        len -= del_len;
+
+        break;
+
+      }
+
+      case MUT_SHUFFLE: {
+
+        /* Shuffle bytes. */
+
+        if (unlikely(len < 4)) { break; }  // no retry
+
+        u32 blen = choose_block_len(afl, len - 1);
+        u32 off = rand_below(afl, len - blen + 1);
+
+        for (u32 i = blen - 1; i > 0; i--) {
+
+          u32 j;
+          do {
+
+            j = rand_below(afl, i + 1);
+
+          } while (unlikely(i == j));
+
+          u8 temp = buf[off + i];
+          buf[off + i] = buf[off + j];
+          buf[off + j] = temp;
+
+        }
+
+        break;
+
+      }
+
+      case MUT_DELONE: {
+
+        /* Delete bytes. */
+
+        if (unlikely(len < 2)) { break; }  // no retry
+
+        /* Don't delete too much. */
+
+        u32 del_len = 1;
+        u32 del_from = rand_below(afl, len - del_len + 1);
+        memmove(buf + del_from, buf + del_from + del_len,
+                len - del_from - del_len);
+
+        len -= del_len;
+
+        break;
+
+      }
+
+      case MUT_INSERTONE: {
+
+        if (unlikely(len < 2)) { break; }  // no retry
+
+        u32 clone_len = 1;
+        u32 clone_to = rand_below(afl, len);
+        u32 strat = rand_below(afl, 2);
+        u32 clone_from = clone_to ? clone_to - 1 : 0;
+        item = strat ? rand_below(afl, 256) : buf[clone_from];
+
+        /* Head */
+
+        memcpy(tmp_buf, buf, clone_to);
+
+        /* Inserted part */
+
+        memset(tmp_buf + clone_to, item, clone_len);
+
+        /* Tail */
+        memcpy(tmp_buf + clone_to + clone_len, buf + clone_to, len - clone_to);
+
+        len += clone_len;
+        memcpy(buf, tmp_buf, len);
+
+        break;
+
+      }
+
+      case MUT_ASCIINUM: {
+
+        if (unlikely(len < 4)) { break; }  // no retry
+
+        u32 off = rand_below(afl, len), off2 = off, cnt = 0;
+
+        while (off2 + cnt < len && !isdigit(buf[off2 + cnt])) {
+
+          ++cnt;
+
+        }
+
+        // none found, wrap
+        if (off2 + cnt == len) {
+
+          off2 = 0;
+          cnt = 0;
+
+          while (cnt < off && !isdigit(buf[off2 + cnt])) {
+
+            ++cnt;
+
+          }
+
+          if (cnt == off) {
+
+            if (len < 8) {
+
+              break;
+
+            } else {
+
+              goto retry_havoc_step;
+
+            }
+
+          }
+
+        }
+
+        off = off2 + cnt;
+        off2 = off + 1;
+
+        while (off2 < len && isdigit(buf[off2])) {
+
+          ++off2;
+
+        }
+
+        s64 val = buf[off] - '0';
+        for (u32 i = off + 1; i < off2; ++i) {
+
+          val = (val * 10) + buf[i] - '0';
+
+        }
+
+        if (off && buf[off - 1] == '-') { val = -val; }
+
+        u32 strat = rand_below(afl, 8);
+        switch (strat) {
+
+          case 0:
+            val++;
+            break;
+          case 1:
+            val--;
+            break;
+          case 2:
+            val *= 2;
+            break;
+          case 3:
+            val /= 2;
+            break;
+          case 4:
+            if (likely(val && (u64)val < 0x19999999)) {
+
+              val = (u64)rand_next(afl) % (u64)((u64)val * 10);
+
+            } else {
+
+              val = rand_below(afl, 256);
+
+            }
+
+            break;
+          case 5:
+            val += rand_below(afl, 256);
+            break;
+          case 6:
+            val -= rand_below(afl, 256);
+            break;
+          case 7:
+            val = ~(val);
+            break;
+
+        }
+
+        char buf[20];
+        snprintf(buf, sizeof(buf), "%ld", val);
+        u32 old_len = off2 - off;
+        u32 new_len = strlen(buf);
+
+        if (old_len == new_len) {
+
+          memcpy(buf + off, buf, new_len);
+
+        } else {
+
+          /* Head */
+
+          memcpy(tmp_buf, buf, off);
+
+          /* Inserted part */
+
+          memcpy(tmp_buf + off, buf, new_len);
+
+          /* Tail */
+          memcpy(tmp_buf + off + new_len, buf + off2, len - off2);
+
+          len += (new_len - old_len);
+          memcpy(buf, tmp_buf, len);
+
+        }
+
+        // fprintf(stderr, "AFTER : %s\n", buf);
+        break;
+
+      }
+
+      case MUT_INSERTASCIINUM: {
+
+        u32 len = 1 + rand_below(afl, 8);
+        u32 pos = rand_below(afl, len);
+
+        /* Insert ascii number. */
+        if (unlikely(len < pos + len)) {
+
+          if (unlikely(len < 8)) {
+
+            break;
+
+          } else {
+
+            goto retry_havoc_step;
+
+          }
+
+        }
+
+        u64  val = rand_next(afl);
+        char buf[20];
+        snprintf(buf, sizeof(buf), "%llu", val);
+        memcpy(buf + pos, buf, len);
+
+        break;
+
+      }
+
+      case MUT_EXTRA_OVERWRITE: {
+
+        if (unlikely(!afl->extras_cnt)) { goto retry_havoc_step; }
+
+        /* Use the dictionary. */
+
+        u32 use_extra = rand_below(afl, afl->extras_cnt);
+        u32 extra_len = afl->extras[use_extra].len;
+
+        if (unlikely(extra_len > len)) { goto retry_havoc_step; }
+
+        u32 insert_at = rand_below(afl, len - extra_len + 1);
+        memcpy(buf + insert_at, afl->extras[use_extra].data, extra_len);
+
+        break;
+
+      }
+
+      case MUT_EXTRA_INSERT: {
+
+        if (unlikely(!afl->extras_cnt)) { goto retry_havoc_step; }
+
+        u32 use_extra = rand_below(afl, afl->extras_cnt);
+        u32 extra_len = afl->extras[use_extra].len;
+        if (unlikely(len + extra_len >= max_len)) { goto retry_havoc_step; }
+
+        u8 *ptr = afl->extras[use_extra].data;
+        u32 insert_at = rand_below(afl, len + 1);
+
+        /* Tail */
+        memmove(buf + insert_at + extra_len, buf + insert_at, len - insert_at);
+
+        /* Inserted part */
+        memcpy(buf + insert_at, ptr, extra_len);
+        len += extra_len;
+
+        break;
+
+      }
+
+      case MUT_AUTO_EXTRA_OVERWRITE: {
+
+        if (unlikely(!afl->a_extras_cnt)) { goto retry_havoc_step; }
+
+        /* Use the dictionary. */
+
+        u32 use_extra = rand_below(afl, afl->a_extras_cnt);
+        u32 extra_len = afl->a_extras[use_extra].len;
+
+        if (unlikely(extra_len > len)) { goto retry_havoc_step; }
+
+        u32 insert_at = rand_below(afl, len - extra_len + 1);
+        memcpy(buf + insert_at, afl->a_extras[use_extra].data, extra_len);
+
+        break;
+
+      }
+
+      case MUT_AUTO_EXTRA_INSERT: {
+
+        if (unlikely(!afl->a_extras_cnt)) { goto retry_havoc_step; }
+
+        u32 use_extra = rand_below(afl, afl->a_extras_cnt);
+        u32 extra_len = afl->a_extras[use_extra].len;
+        if (unlikely(len + extra_len >= max_len)) { goto retry_havoc_step; }
+
+        u8 *ptr = afl->a_extras[use_extra].data;
+        u32 insert_at = rand_below(afl, len + 1);
+
+        /* Tail */
+        memmove(buf + insert_at + extra_len, buf + insert_at, len - insert_at);
+
+        /* Inserted part */
+        memcpy(buf + insert_at, ptr, extra_len);
+        len += extra_len;
+
+        break;
+
+      }
+
+      case MUT_SPLICE_OVERWRITE: {
+
+        if (unlikely(!splice_buf || !splice_len)) { goto retry_havoc_step; }
+
+        /* overwrite mode */
+
+        u32 copy_from, copy_to, copy_len;
+
+        copy_len = choose_block_len(afl, splice_len - 1);
+
+        if (copy_len > len) copy_len = len;
+
+        copy_from = rand_below(afl, splice_len - copy_len + 1);
+        copy_to = rand_below(afl, len - copy_len + 1);
+        memmove(buf + copy_to, splice_buf + copy_from, copy_len);
+
+        break;
+
+      }
+
+      case MUT_SPLICE_INSERT: {
+
+        if (unlikely(!splice_buf || !splice_len)) { goto retry_havoc_step; }
+
+        if (unlikely(len + HAVOC_BLK_XL >= max_len)) { goto retry_havoc_step; }
+
+        /* insert mode */
+
+        u32 clone_from, clone_to, clone_len;
+
+        clone_len = choose_block_len(afl, splice_len);
+        clone_from = rand_below(afl, splice_len - clone_len + 1);
+        clone_to = rand_below(afl, len + 1);
+
+        /* Head */
+
+        memcpy(tmp_buf, buf, clone_to);
+
+        /* Inserted part */
+
+        memcpy(tmp_buf + clone_to, splice_buf + clone_from, clone_len);
+
+        /* Tail */
+        memcpy(tmp_buf + clone_to + clone_len, buf + clone_to, len - clone_to);
+
+        len += clone_len;
+        memcpy(buf, tmp_buf, len);
+
+        break;
+
+      }
+
+    }
+
+  }
+
+  }
+
+  return len;
+
+}
+
+#endif                                                  /* !AFL_MUTATIONS_H */
+
diff --git a/include/config.h b/include/config.h
index d8153a2c..5100d88f 100644
--- a/include/config.h
+++ b/include/config.h
@@ -43,6 +43,12 @@
    Default: 8MB (defined in bytes) */
 #define DEFAULT_SHMEM_SIZE (8 * 1024 * 1024)
 
+/* Default time until when no more coverage finds are happening afl-fuzz
+   switches to exploitation mode. It automatically switches back when new
+   coverage is found.
+   Default: 300 (seconds) */
+#define STRATEGY_SWITCH_TIME 600
+
 /* Default file permission umode when creating files (default: 0600) */
 #define DEFAULT_PERMISSION 0600
 
diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c
index 556bb5d1..fb8a1d4b 100644
--- a/src/afl-fuzz-bitmap.c
+++ b/src/afl-fuzz-bitmap.c
@@ -533,6 +533,18 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
     close(fd);
     add_to_queue(afl, queue_fn, len, 0);
 
+    if (unlikely(afl->fuzz_mode) && likely(afl->switch_fuzz_mode)) {
+
+      if (afl->afl_env.afl_no_ui) {
+
+        ACTF("New coverage found, switching back to exploration mode.");
+
+      }
+
+      afl->fuzz_mode = 0;
+
+    }
+
 #ifdef INTROSPECTION
     if (afl->custom_mutators_count && afl->current_custom_fuzz) {
 
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index 5c71fc59..4efc661e 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -27,6 +27,7 @@
 #include <string.h>
 #include <limits.h>
 #include "cmplog.h"
+#include "afl-mutations.h"
 
 /* MOpt */
 
@@ -70,50 +71,6 @@ static int select_algorithm(afl_state_t *afl, u32 max_algorithm) {
 
 }
 
-/* Helper to choose random block len for block operations in fuzz_one().
-   Doesn't return zero, provided that max_len is > 0. */
-
-static inline u32 choose_block_len(afl_state_t *afl, u32 limit) {
-
-  u32 min_value, max_value;
-  u32 rlim = MIN(afl->queue_cycle, (u32)3);
-
-  if (unlikely(!afl->run_over10m)) { rlim = 1; }
-
-  switch (rand_below(afl, rlim)) {
-
-    case 0:
-      min_value = 1;
-      max_value = HAVOC_BLK_SMALL;
-      break;
-
-    case 1:
-      min_value = HAVOC_BLK_SMALL;
-      max_value = HAVOC_BLK_MEDIUM;
-      break;
-
-    default:
-
-      if (likely(rand_below(afl, 10))) {
-
-        min_value = HAVOC_BLK_MEDIUM;
-        max_value = HAVOC_BLK_LARGE;
-
-      } else {
-
-        min_value = HAVOC_BLK_LARGE;
-        max_value = HAVOC_BLK_XL;
-
-      }
-
-  }
-
-  if (min_value >= limit) { min_value = 1; }
-
-  return min_value + rand_below(afl, MIN(max_value, limit) - min_value + 1);
-
-}
-
 /* Helper function to see if a particular change (xor_val = old ^ new) could
    be a product of deterministic bit flips with the lengths and stepovers
    attempted by afl-fuzz. This is used to avoid dupes in some of the
@@ -445,10 +402,12 @@ u8 fuzz_one_original(afl_state_t *afl) {
   if (unlikely(afl->not_on_tty)) {
 
     ACTF(
-        "Fuzzing test case #%u (%u total, %llu crashes saved, "
+        "Fuzzing test case #%u (%u total, %llu crashes saved, state: %s, "
+        "mode=%s, "
         "perf_score=%0.0f, weight=%0.0f, favorite=%u, was_fuzzed=%u, "
         "exec_us=%llu, hits=%u, map=%u, ascii=%u)...",
         afl->current_entry, afl->queued_items, afl->saved_crashes,
+        get_fuzzing_state(afl), afl->fuzz_mode ? "exploit" : "explore",
         afl->queue_cur->perf_score, afl->queue_cur->weight,
         afl->queue_cur->favored, afl->queue_cur->was_fuzzed,
         afl->queue_cur->exec_us,
@@ -2123,45 +2082,83 @@ havoc_stage:
   /* We essentially just do several thousand runs (depending on perf_score)
      where we take the input file and make random stacked tweaks. */
 
-#define MAX_HAVOC_ENTRY 64
-#define MUTATE_ASCII_DICT 64
-
-  u32 r_max, r;
+  u32 *mutation_array;
+  u32  stack_max, rand_max;  // stack_max_pow = afl->havoc_stack_pow2;
 
-  r_max = (MAX_HAVOC_ENTRY + 1) + (afl->extras_cnt ? 4 : 0) +
-          (afl->a_extras_cnt
-               ? (unlikely(afl->cmplog_binary && afl->queue_cur->is_ascii)
-                      ? MUTATE_ASCII_DICT
-                      : 4)
-               : 0);
+  /*
 
   if (unlikely(afl->expand_havoc && afl->ready_for_splicing_count > 1)) {
 
-    /* add expensive havoc cases here, they are activated after a full
-       cycle without finds happened */
+    mutation_array = full_splice_array;
+    rand_max = MUT_SPLICE_ARRAY_SIZE;
+
+  } else {
+
+    mutation_array = normal_splice_array;
+    rand_max = MUT_NORMAL_ARRAY_SIZE;
+
+  }
+
+  */
+
+  rand_max = MUT_STRATEGY_ARRAY_SIZE;
+
+  if (unlikely(afl->text_input /*|| afl->queue_cur->is_ascii*/)) {  // is text?
+
+    if (likely(afl->fuzz_mode == 0)) {  // is exploration?
+
+      mutation_array = (unsigned int *)&mutation_strategy_exploration_text;
+
+    } else {  // is exploitation!
+
+      mutation_array = (unsigned int *)&mutation_strategy_exploitation_text;
+
+    }
+
+  } else {  // is binary!
+
+    if (likely(afl->fuzz_mode == 0)) {  // is exploration?
 
-    r_max += 4;
+      mutation_array = (unsigned int *)&mutation_strategy_exploration_binary;
+
+    } else {  // is exploitation!
+
+      mutation_array = (unsigned int *)&mutation_strategy_exploitation_binary;
+
+    }
 
   }
 
-  if (unlikely(get_cur_time() - afl->last_find_time > 5000 /* 5 seconds */ &&
-               afl->ready_for_splicing_count > 1)) {
+  /*
+  if (temp_len < 64) {
+
+    --stack_max_pow;
+
+  } else if (temp_len <= 8096) {
 
-    /* add expensive havoc cases here if there is no findings in the last 5s */
+    ++stack_max_pow;
 
-    r_max += 4;
+  } else {
+
+    ++stack_max_pow;
 
   }
 
+  */
+
+  stack_max = 1 << (1 + rand_below(afl, afl->havoc_stack_pow2));
+
+  // + (afl->extras_cnt ? 2 : 0) + (afl->a_extras_cnt ? 2 : 0);
+
   for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) {
 
-    u32 use_stacking = 1 << (1 + rand_below(afl, afl->havoc_stack_pow2));
+    u32 use_stacking = 1 + rand_below(afl, stack_max);
 
     afl->stage_cur_val = use_stacking;
 
 #ifdef INTROSPECTION
-    snprintf(afl->mutation, sizeof(afl->mutation), "%s HAVOC-%u",
-             afl->queue_cur->fname, use_stacking);
+    snprintf(afl->mutation, sizeof(afl->mutation), "%s HAVOC-%u-%u",
+             afl->queue_cur->fname, afl->queue_cur->is_ascii, use_stacking);
 #endif
 
     for (i = 0; i < use_stacking; ++i) {
@@ -2170,8 +2167,8 @@ havoc_stage:
 
         LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
 
-          if (el->stacked_custom &&
-              rand_below(afl, 100) < el->stacked_custom_prob) {
+          if (unlikely(el->stacked_custom &&
+                       rand_below(afl, 100) < el->stacked_custom_prob)) {
 
             u8    *custom_havoc_buf = NULL;
             size_t new_len = el->afl_custom_havoc_mutation(
@@ -2201,159 +2198,173 @@ havoc_stage:
 
       }
 
-      switch ((r = rand_below(afl, r_max))) {
+    retry_havoc_step : {
+
+      u32 r = rand_below(afl, rand_max), item;
+
+      switch (mutation_array[r]) {
 
-        case 0 ... 3: {
+        case MUT_FLIPBIT: {
 
           /* Flip a single bit somewhere. Spooky! */
+          u8  bit = rand_below(afl, 8);
+          u32 off = rand_below(afl, temp_len);
+          out_buf[off] ^= 1 << bit;
 
 #ifdef INTROSPECTION
-          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " FLIP_BIT1");
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " FLIP-BIT_%u", bit);
           strcat(afl->mutation, afl->m_tmp);
 #endif
-          FLIP_BIT(out_buf, rand_below(afl, temp_len << 3));
           break;
 
         }
 
-        case 4 ... 7: {
+        case MUT_INTERESTING8: {
 
           /* Set byte to interesting value. */
 
+          item = rand_below(afl, sizeof(interesting_8));
 #ifdef INTROSPECTION
-          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING8");
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING8_%u", item);
           strcat(afl->mutation, afl->m_tmp);
 #endif
-          out_buf[rand_below(afl, temp_len)] =
-              interesting_8[rand_below(afl, sizeof(interesting_8))];
+          out_buf[rand_below(afl, temp_len)] = interesting_8[item];
           break;
 
         }
 
-        case 8 ... 9: {
+        case MUT_INTERESTING16: {
 
           /* Set word to interesting value, little endian. */
 
-          if (temp_len < 2) { break; }
+          if (unlikely(temp_len < 2)) { break; }  // no retry
 
+          item = rand_below(afl, sizeof(interesting_16) >> 1);
 #ifdef INTROSPECTION
-          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING16");
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING16_%u", item);
           strcat(afl->mutation, afl->m_tmp);
 #endif
+
           *(u16 *)(out_buf + rand_below(afl, temp_len - 1)) =
-              interesting_16[rand_below(afl, sizeof(interesting_16) >> 1)];
+              interesting_16[item];
 
           break;
 
         }
 
-        case 10 ... 11: {
+        case MUT_INTERESTING16BE: {
 
           /* Set word to interesting value, big endian. */
 
-          if (temp_len < 2) { break; }
+          if (unlikely(temp_len < 2)) { break; }  // no retry
 
+          item = rand_below(afl, sizeof(interesting_16) >> 1);
 #ifdef INTROSPECTION
-          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING16BE");
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING16BE_%u", item);
           strcat(afl->mutation, afl->m_tmp);
 #endif
-          *(u16 *)(out_buf + rand_below(afl, temp_len - 1)) = SWAP16(
-              interesting_16[rand_below(afl, sizeof(interesting_16) >> 1)]);
+          *(u16 *)(out_buf + rand_below(afl, temp_len - 1)) =
+              SWAP16(interesting_16[item]);
 
           break;
 
         }
 
-        case 12 ... 13: {
+        case MUT_INTERESTING32: {
 
           /* Set dword to interesting value, little endian. */
 
-          if (temp_len < 4) { break; }
+          if (unlikely(temp_len < 4)) { break; }  // no retry
 
+          item = rand_below(afl, sizeof(interesting_32) >> 2);
 #ifdef INTROSPECTION
-          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING32");
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING32_%u", item);
           strcat(afl->mutation, afl->m_tmp);
 #endif
+
           *(u32 *)(out_buf + rand_below(afl, temp_len - 3)) =
-              interesting_32[rand_below(afl, sizeof(interesting_32) >> 2)];
+              interesting_32[item];
 
           break;
 
         }
 
-        case 14 ... 15: {
+        case MUT_INTERESTING32BE: {
 
           /* Set dword to interesting value, big endian. */
 
-          if (temp_len < 4) { break; }
+          if (unlikely(temp_len < 4)) { break; }  // no retry
 
+          item = rand_below(afl, sizeof(interesting_32) >> 2);
 #ifdef INTROSPECTION
-          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING32BE");
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING32BE_%u", item);
           strcat(afl->mutation, afl->m_tmp);
 #endif
-          *(u32 *)(out_buf + rand_below(afl, temp_len - 3)) = SWAP32(
-              interesting_32[rand_below(afl, sizeof(interesting_32) >> 2)]);
+          *(u32 *)(out_buf + rand_below(afl, temp_len - 3)) =
+              SWAP32(interesting_32[item]);
 
           break;
 
         }
 
-        case 16 ... 19: {
+        case MUT_ARITH8_: {
 
           /* Randomly subtract from byte. */
 
+          item = 1 + rand_below(afl, ARITH_MAX);
 #ifdef INTROSPECTION
-          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH8_");
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH8-_%u", item);
           strcat(afl->mutation, afl->m_tmp);
 #endif
-          out_buf[rand_below(afl, temp_len)] -= 1 + rand_below(afl, ARITH_MAX);
+          out_buf[rand_below(afl, temp_len)] -= item;
           break;
 
         }
 
-        case 20 ... 23: {
+        case MUT_ARITH8: {
 
           /* Randomly add to byte. */
 
+          item = 1 + rand_below(afl, ARITH_MAX);
 #ifdef INTROSPECTION
-          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH8+");
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH8+_%u", item);
           strcat(afl->mutation, afl->m_tmp);
 #endif
-          out_buf[rand_below(afl, temp_len)] += 1 + rand_below(afl, ARITH_MAX);
+          out_buf[rand_below(afl, temp_len)] += item;
           break;
 
         }
 
-        case 24 ... 25: {
+        case MUT_ARITH16_: {
 
           /* Randomly subtract from word, little endian. */
 
-          if (temp_len < 2) { break; }
+          if (unlikely(temp_len < 2)) { break; }  // no retry
 
           u32 pos = rand_below(afl, temp_len - 1);
+          item = 1 + rand_below(afl, ARITH_MAX);
 
 #ifdef INTROSPECTION
-          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16_-%u", pos);
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16-_%u", item);
           strcat(afl->mutation, afl->m_tmp);
 #endif
-          *(u16 *)(out_buf + pos) -= 1 + rand_below(afl, ARITH_MAX);
+          *(u16 *)(out_buf + pos) -= item;
 
           break;
 
         }
 
-        case 26 ... 27: {
+        case MUT_ARITH16BE_: {
 
           /* Randomly subtract from word, big endian. */
 
-          if (temp_len < 2) { break; }
+          if (unlikely(temp_len < 2)) { break; }  // no retry
 
           u32 pos = rand_below(afl, temp_len - 1);
           u16 num = 1 + rand_below(afl, ARITH_MAX);
 
 #ifdef INTROSPECTION
-          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16_BE-%u_%u", pos,
-                   num);
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16BE-_%u", num);
           strcat(afl->mutation, afl->m_tmp);
 #endif
           *(u16 *)(out_buf + pos) =
@@ -2363,36 +2374,36 @@ havoc_stage:
 
         }
 
-        case 28 ... 29: {
+        case MUT_ARITH16: {
 
           /* Randomly add to word, little endian. */
 
-          if (temp_len < 2) { break; }
+          if (unlikely(temp_len < 2)) { break; }  // no retry
 
           u32 pos = rand_below(afl, temp_len - 1);
+          item = 1 + rand_below(afl, ARITH_MAX);
 
 #ifdef INTROSPECTION
-          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16+-%u", pos);
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16+_%u", item);
           strcat(afl->mutation, afl->m_tmp);
 #endif
-          *(u16 *)(out_buf + pos) += 1 + rand_below(afl, ARITH_MAX);
+          *(u16 *)(out_buf + pos) += item;
 
           break;
 
         }
 
-        case 30 ... 31: {
+        case MUT_ARITH16BE: {
 
           /* Randomly add to word, big endian. */
 
-          if (temp_len < 2) { break; }
+          if (unlikely(temp_len < 2)) { break; }  // no retry
 
           u32 pos = rand_below(afl, temp_len - 1);
           u16 num = 1 + rand_below(afl, ARITH_MAX);
 
 #ifdef INTROSPECTION
-          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16+BE-%u_%u", pos,
-                   num);
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16BE+__%u", num);
           strcat(afl->mutation, afl->m_tmp);
 #endif
           *(u16 *)(out_buf + pos) =
@@ -2402,36 +2413,36 @@ havoc_stage:
 
         }
 
-        case 32 ... 33: {
+        case MUT_ARITH32_: {
 
           /* Randomly subtract from dword, little endian. */
 
-          if (temp_len < 4) { break; }
+          if (unlikely(temp_len < 4)) { break; }  // no retry
 
           u32 pos = rand_below(afl, temp_len - 3);
+          item = 1 + rand_below(afl, ARITH_MAX);
 
 #ifdef INTROSPECTION
-          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32_-%u", pos);
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32-_%u", item);
           strcat(afl->mutation, afl->m_tmp);
 #endif
-          *(u32 *)(out_buf + pos) -= 1 + rand_below(afl, ARITH_MAX);
+          *(u32 *)(out_buf + pos) -= item;
 
           break;
 
         }
 
-        case 34 ... 35: {
+        case MUT_ARITH32BE_: {
 
           /* Randomly subtract from dword, big endian. */
 
-          if (temp_len < 4) { break; }
+          if (unlikely(temp_len < 4)) { break; }  // no retry
 
           u32 pos = rand_below(afl, temp_len - 3);
           u32 num = 1 + rand_below(afl, ARITH_MAX);
 
 #ifdef INTROSPECTION
-          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32_BE-%u-%u", pos,
-                   num);
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32BE-_%u", num);
           strcat(afl->mutation, afl->m_tmp);
 #endif
           *(u32 *)(out_buf + pos) =
@@ -2441,36 +2452,36 @@ havoc_stage:
 
         }
 
-        case 36 ... 37: {
+        case MUT_ARITH32: {
 
           /* Randomly add to dword, little endian. */
 
-          if (temp_len < 4) { break; }
+          if (unlikely(temp_len < 4)) { break; }  // no retry
 
           u32 pos = rand_below(afl, temp_len - 3);
+          item = 1 + rand_below(afl, ARITH_MAX);
 
 #ifdef INTROSPECTION
-          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32+-%u", pos);
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32+_%u", item);
           strcat(afl->mutation, afl->m_tmp);
 #endif
-          *(u32 *)(out_buf + pos) += 1 + rand_below(afl, ARITH_MAX);
+          *(u32 *)(out_buf + pos) += item;
 
           break;
 
         }
 
-        case 38 ... 39: {
+        case MUT_ARITH32BE: {
 
           /* Randomly add to dword, big endian. */
 
-          if (temp_len < 4) { break; }
+          if (unlikely(temp_len < 4)) { break; }  // no retry
 
           u32 pos = rand_below(afl, temp_len - 3);
           u32 num = 1 + rand_below(afl, ARITH_MAX);
 
 #ifdef INTROSPECTION
-          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32+BE-%u-%u", pos,
-                   num);
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32BE+_%u", num);
           strcat(afl->mutation, afl->m_tmp);
 #endif
           *(u32 *)(out_buf + pos) =
@@ -2480,24 +2491,27 @@ havoc_stage:
 
         }
 
-        case 40 ... 43: {
+        case MUT_RAND8: {
 
           /* Just set a random byte to a random value. Because,
              why not. We use XOR with 1-255 to eliminate the
              possibility of a no-op. */
 
+          u32 pos = rand_below(afl, temp_len);
+          item = 1 + rand_below(afl, 255);
 #ifdef INTROSPECTION
-          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " RAND8");
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " RAND8_%u",
+                   out_buf[pos] ^ item);
           strcat(afl->mutation, afl->m_tmp);
 #endif
-          out_buf[rand_below(afl, temp_len)] ^= 1 + rand_below(afl, 255);
+          out_buf[pos] ^= item;
           break;
 
         }
 
-        case 44 ... 46: {
+        case MUT_CLONE_COPY: {
 
-          if (temp_len + HAVOC_BLK_XL < MAX_FILE) {
+          if (likely(temp_len + HAVOC_BLK_XL < MAX_FILE)) {
 
             /* Clone bytes. */
 
@@ -2506,8 +2520,8 @@ havoc_stage:
             u32 clone_to = rand_below(afl, temp_len);
 
 #ifdef INTROSPECTION
-            snprintf(afl->m_tmp, sizeof(afl->m_tmp), " CLONE-%s-%u-%u-%u",
-                     "clone", clone_from, clone_to, clone_len);
+            snprintf(afl->m_tmp, sizeof(afl->m_tmp), " CLONE-%s_%u_%u_%u",
+                     "COPY", clone_from, clone_to, clone_len);
             strcat(afl->mutation, afl->m_tmp);
 #endif
             u8 *new_buf =
@@ -2530,24 +2544,35 @@ havoc_stage:
             afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch));
             temp_len += clone_len;
 
+          } else if (unlikely(temp_len < 8)) {
+
+            break;
+
+          } else {
+
+            goto retry_havoc_step;
+
           }
 
           break;
 
         }
 
-        case 47: {
+        case MUT_CLONE_FIXED: {
 
-          if (temp_len + HAVOC_BLK_XL < MAX_FILE) {
+          if (likely(temp_len + HAVOC_BLK_XL < MAX_FILE)) {
 
             /* Insert a block of constant bytes (25%). */
 
             u32 clone_len = choose_block_len(afl, HAVOC_BLK_XL);
             u32 clone_to = rand_below(afl, temp_len);
+            u32 strat = rand_below(afl, 2);
+            u32 clone_from = clone_to ? clone_to - 1 : 0;
+            item = strat ? rand_below(afl, 256) : out_buf[clone_from];
 
 #ifdef INTROSPECTION
-            snprintf(afl->m_tmp, sizeof(afl->m_tmp), " CLONE-%s-%u-%u",
-                     "insert", clone_to, clone_len);
+            snprintf(afl->m_tmp, sizeof(afl->m_tmp), " CLONE-%s_%u_%u_%u",
+                     "FIXED", strat, clone_to, clone_len);
             strcat(afl->mutation, afl->m_tmp);
 #endif
             u8 *new_buf =
@@ -2560,10 +2585,7 @@ havoc_stage:
 
             /* Inserted part */
 
-            memset(new_buf + clone_to,
-                   rand_below(afl, 2) ? rand_below(afl, 256)
-                                      : out_buf[rand_below(afl, temp_len)],
-                   clone_len);
+            memset(new_buf + clone_to, item, clone_len);
 
             /* Tail */
             memcpy(new_buf + clone_to + clone_len, out_buf + clone_to,
@@ -2573,66 +2595,77 @@ havoc_stage:
             afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch));
             temp_len += clone_len;
 
+          } else if (unlikely(temp_len < 8)) {
+
+            break;
+
+          } else {
+
+            goto retry_havoc_step;
+
           }
 
           break;
 
         }
 
-        case 48 ... 50: {
+        case MUT_OVERWRITE_COPY: {
 
           /* Overwrite bytes with a randomly selected chunk bytes. */
 
-          if (temp_len < 2) { break; }
+          if (unlikely(temp_len < 2)) { break; }  // no retry
 
-          u32 copy_len = choose_block_len(afl, temp_len - 1);
-          u32 copy_from = rand_below(afl, temp_len - copy_len + 1);
-          u32 copy_to = rand_below(afl, temp_len - copy_len + 1);
+          u32 copy_from, copy_to,
+              copy_len = choose_block_len(afl, temp_len - 1);
+
+          do {
+
+            copy_from = rand_below(afl, temp_len - copy_len + 1);
+            copy_to = rand_below(afl, temp_len - copy_len + 1);
 
-          if (likely(copy_from != copy_to)) {
+          } while (unlikely(copy_from == copy_to));
 
 #ifdef INTROSPECTION
-            snprintf(afl->m_tmp, sizeof(afl->m_tmp), " OVERWRITE_COPY-%u-%u-%u",
-                     copy_from, copy_to, copy_len);
-            strcat(afl->mutation, afl->m_tmp);
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " OVERWRITE-COPY_%u_%u_%u",
+                   copy_from, copy_to, copy_len);
+          strcat(afl->mutation, afl->m_tmp);
 #endif
-            memmove(out_buf + copy_to, out_buf + copy_from, copy_len);
-
-          }
+          memmove(out_buf + copy_to, out_buf + copy_from, copy_len);
 
           break;
 
         }
 
-        case 51: {
+        case MUT_OVERWRITE_FIXED: {
 
           /* Overwrite bytes with fixed bytes. */
 
-          if (temp_len < 2) { break; }
+          if (unlikely(temp_len < 2)) { break; }  // no retry
 
           u32 copy_len = choose_block_len(afl, temp_len - 1);
           u32 copy_to = rand_below(afl, temp_len - copy_len + 1);
+          u32 strat = rand_below(afl, 2);
+          u32 copy_from = copy_to ? copy_to - 1 : 0;
+          item = strat ? rand_below(afl, 256) : out_buf[copy_from];
 
 #ifdef INTROSPECTION
-          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " OVERWRITE_FIXED-%u-%u",
-                   copy_to, copy_len);
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp),
+                   " OVERWRITE-FIXED_%u_%u_%u-%u", strat, item, copy_to,
+                   copy_len);
           strcat(afl->mutation, afl->m_tmp);
 #endif
-          memset(out_buf + copy_to,
-                 rand_below(afl, 2) ? rand_below(afl, 256)
-                                    : out_buf[rand_below(afl, temp_len)],
-                 copy_len);
+          memset(out_buf + copy_to, item, copy_len);
 
           break;
 
         }
 
-        case 52: {
+        case MUT_BYTEADD: {
 
           /* Increase byte by 1. */
 
 #ifdef INTROSPECTION
-          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ADDBYTE_");
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " BYTEADD_");
           strcat(afl->mutation, afl->m_tmp);
 #endif
           out_buf[rand_below(afl, temp_len)]++;
@@ -2640,12 +2673,12 @@ havoc_stage:
 
         }
 
-        case 53: {
+        case MUT_BYTESUB: {
 
           /* Decrease byte by 1. */
 
 #ifdef INTROSPECTION
-          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " SUBBYTE_");
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " BYTESUB_");
           strcat(afl->mutation, afl->m_tmp);
 #endif
           out_buf[rand_below(afl, temp_len)]--;
@@ -2653,9 +2686,9 @@ havoc_stage:
 
         }
 
-        case 54: {
+        case MUT_FLIP8: {
 
-          /* Flip byte. */
+          /* Flip byte with a XOR 0xff. This is the same as NEG. */
 
 #ifdef INTROSPECTION
           snprintf(afl->m_tmp, sizeof(afl->m_tmp), " FLIP8_");
@@ -2666,9 +2699,9 @@ havoc_stage:
 
         }
 
-        case 55 ... 56: {
+        case MUT_SWITCH: {
 
-          if (temp_len < 4) { break; }
+          if (unlikely(temp_len < 4)) { break; }  // no retry
 
           /* Switch bytes. */
 
@@ -2678,7 +2711,7 @@ havoc_stage:
 
             switch_to = rand_below(afl, temp_len);
 
-          } while (switch_from == switch_to);
+          } while (unlikely(switch_from == switch_to));
 
           if (switch_from < switch_to) {
 
@@ -2695,7 +2728,7 @@ havoc_stage:
           switch_len = choose_block_len(afl, MIN(switch_len, to_end));
 
 #ifdef INTROSPECTION
-          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " SWITCH-%s-%u-%u-%u",
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " SWITCH-%s_%u_%u_%u",
                    "switch", switch_from, switch_to, switch_len);
           strcat(afl->mutation, afl->m_tmp);
 #endif
@@ -2718,12 +2751,11 @@ havoc_stage:
 
         }
 
-        // MAX_HAVOC_ENTRY = 64
-        case 57 ... MAX_HAVOC_ENTRY: {
+        case MUT_DEL: {
 
           /* Delete bytes. */
 
-          if (temp_len < 2) { break; }
+          if (unlikely(temp_len < 2)) { break; }  // no retry
 
           /* Don't delete too much. */
 
@@ -2731,7 +2763,7 @@ havoc_stage:
           u32 del_from = rand_below(afl, temp_len - del_len + 1);
 
 #ifdef INTROSPECTION
-          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " DEL-%u-%u", del_from,
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " DEL_%u_%u", del_from,
                    del_len);
           strcat(afl->mutation, afl->m_tmp);
 #endif
@@ -2744,135 +2776,401 @@ havoc_stage:
 
         }
 
-        default:
+        case MUT_SHUFFLE: {
+
+          /* Shuffle bytes. */
+
+          if (unlikely(temp_len < 4)) { break; }  // no retry
+
+          u32 len = choose_block_len(afl, temp_len - 1);
+          u32 off = rand_below(afl, temp_len - len + 1);
+
+#ifdef INTROSPECTION
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " SHUFFLE_%u", len);
+          strcat(afl->mutation, afl->m_tmp);
+#endif
+
+          for (u32 i = len - 1; i > 0; i--) {
 
-          r -= (MAX_HAVOC_ENTRY + 1);
+            u32 j;
+            do {
+
+              j = rand_below(afl, i + 1);
+
+            } while (unlikely(i == j));
+
+            unsigned char temp = out_buf[off + i];
+            out_buf[off + i] = out_buf[off + j];
+            out_buf[off + j] = temp;
+
+          }
+
+          break;
+
+        }
 
-          if (afl->extras_cnt) {
+        case MUT_DELONE: {
 
-            if (r < 2) {
+          /* Delete bytes. */
 
-              /* Use the dictionary. */
+          if (unlikely(temp_len < 2)) { break; }  // no retry
 
-              u32 use_extra = rand_below(afl, afl->extras_cnt);
-              u32 extra_len = afl->extras[use_extra].len;
+          /* Don't delete too much. */
 
-              if (extra_len > temp_len) { break; }
+          u32 del_len = 1;
+          u32 del_from = rand_below(afl, temp_len - del_len + 1);
 
-              u32 insert_at = rand_below(afl, temp_len - extra_len + 1);
 #ifdef INTROSPECTION
-              snprintf(afl->m_tmp, sizeof(afl->m_tmp), " EXTRA_OVERWRITE-%u-%u",
-                       insert_at, extra_len);
-              strcat(afl->mutation, afl->m_tmp);
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " DELONE_%u", del_from);
+          strcat(afl->mutation, afl->m_tmp);
 #endif
-              memcpy(out_buf + insert_at, afl->extras[use_extra].data,
-                     extra_len);
+          memmove(out_buf + del_from, out_buf + del_from + del_len,
+                  temp_len - del_from - del_len);
 
-              break;
+          temp_len -= del_len;
+
+          break;
+
+        }
 
-            } else if (r < 4) {
+        case MUT_INSERTONE: {
 
-              u32 use_extra = rand_below(afl, afl->extras_cnt);
-              u32 extra_len = afl->extras[use_extra].len;
-              if (temp_len + extra_len >= MAX_FILE) { break; }
+          if (unlikely(temp_len < 2)) { break; }  // no retry
+
+          u32 clone_len = 1;
+          u32 clone_to = rand_below(afl, temp_len);
+          u32 strat = rand_below(afl, 2);
+          u32 clone_from = clone_to ? clone_to - 1 : 0;
+          item = strat ? rand_below(afl, 256) : out_buf[clone_from];
 
-              u8 *ptr = afl->extras[use_extra].data;
-              u32 insert_at = rand_below(afl, temp_len + 1);
 #ifdef INTROSPECTION
-              snprintf(afl->m_tmp, sizeof(afl->m_tmp), " EXTRA_INSERT-%u-%u",
-                       insert_at, extra_len);
-              strcat(afl->mutation, afl->m_tmp);
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INSERTONE_%u_%u", strat,
+                   clone_to);
+          strcat(afl->mutation, afl->m_tmp);
 #endif
+          u8 *new_buf =
+              afl_realloc(AFL_BUF_PARAM(out_scratch), temp_len + clone_len);
+          if (unlikely(!new_buf)) { PFATAL("alloc"); }
 
-              out_buf = afl_realloc(AFL_BUF_PARAM(out), temp_len + extra_len);
-              if (unlikely(!out_buf)) { PFATAL("alloc"); }
+          /* Head */
 
-              /* Tail */
-              memmove(out_buf + insert_at + extra_len, out_buf + insert_at,
-                      temp_len - insert_at);
+          memcpy(new_buf, out_buf, clone_to);
 
-              /* Inserted part */
-              memcpy(out_buf + insert_at, ptr, extra_len);
-              temp_len += extra_len;
+          /* Inserted part */
 
-              break;
+          memset(new_buf + clone_to, item, clone_len);
 
-            } else {
+          /* Tail */
+          memcpy(new_buf + clone_to + clone_len, out_buf + clone_to,
+                 temp_len - clone_to);
 
-              r -= 4;
+          out_buf = new_buf;
+          afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch));
+          temp_len += clone_len;
 
-            }
+          break;
+
+        }
+
+        case MUT_ASCIINUM: {
+
+          if (unlikely(temp_len < 4)) { break; }  // no retry
+
+          u32 off = rand_below(afl, temp_len), off2 = off, cnt = 0;
+
+          while (off2 + cnt < temp_len && !isdigit(out_buf[off2 + cnt])) {
+
+            ++cnt;
 
           }
 
-          if (afl->a_extras_cnt) {
+          // none found, wrap
+          if (off2 + cnt == temp_len) {
 
-            u32 r_cmp = 2;
+            off2 = 0;
+            cnt = 0;
 
-            if (unlikely(afl->cmplog_binary && afl->queue_cur->is_ascii)) {
+            while (cnt < off && !isdigit(out_buf[off2 + cnt])) {
 
-              r_cmp = MUTATE_ASCII_DICT >> 1;
+              ++cnt;
 
             }
 
-            if (r < r_cmp) {
+            if (cnt == off) {
+
+              if (temp_len < 8) {
+
+                break;
 
-              /* Use the dictionary. */
+              } else {
 
-              u32 use_extra = rand_below(afl, afl->a_extras_cnt);
-              u32 extra_len = afl->a_extras[use_extra].len;
+                goto retry_havoc_step;
 
-              if (extra_len > temp_len) { break; }
+              }
 
-              u32 insert_at = rand_below(afl, temp_len - extra_len + 1);
-#ifdef INTROSPECTION
-              snprintf(afl->m_tmp, sizeof(afl->m_tmp),
-                       " AUTO_EXTRA_OVERWRITE-%u-%u", insert_at, extra_len);
-              strcat(afl->mutation, afl->m_tmp);
-#endif
-              memcpy(out_buf + insert_at, afl->a_extras[use_extra].data,
-                     extra_len);
+            }
+
+          }
+
+          off = off2 + cnt;
+          off2 = off + 1;
 
+          while (off2 < temp_len && isdigit(out_buf[off2])) {
+
+            ++off2;
+
+          }
+
+          s64 val = out_buf[off] - '0';
+          for (u32 i = off + 1; i < off2; ++i) {
+
+            val = (val * 10) + out_buf[i] - '0';
+
+          }
+
+          if (off && out_buf[off - 1] == '-') { val = -val; }
+
+          u32 strat = rand_below(afl, 8);
+          switch (strat) {
+
+            case 0:
+              val++;
+              break;
+            case 1:
+              val--;
+              break;
+            case 2:
+              val *= 2;
               break;
+            case 3:
+              val /= 2;
+              break;
+            case 4:
+              if (likely(val && (u64)val < 0x19999999)) {
+
+                val = (u64)rand_next(afl) % (u64)((u64)val * 10);
 
-            } else if (r < (r_cmp << 1)) {
+              } else {
+
+                val = rand_below(afl, 256);
+
+              }
+
+              break;
+            case 5:
+              val += rand_below(afl, 256);
+              break;
+            case 6:
+              val -= rand_below(afl, 256);
+              break;
+            case 7:
+              val = ~(val);
+              break;
 
-              u32 use_extra = rand_below(afl, afl->a_extras_cnt);
-              u32 extra_len = afl->a_extras[use_extra].len;
-              if (temp_len + extra_len >= MAX_FILE) { break; }
+          }
 
-              u8 *ptr = afl->a_extras[use_extra].data;
-              u32 insert_at = rand_below(afl, temp_len + 1);
 #ifdef INTROSPECTION
-              snprintf(afl->m_tmp, sizeof(afl->m_tmp),
-                       " AUTO_EXTRA_INSERT-%u-%u", insert_at, extra_len);
-              strcat(afl->mutation, afl->m_tmp);
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ASCIINUM_%u_%u_%u",
+                   afl->queue_cur->is_ascii, strat, off);
+          strcat(afl->mutation, afl->m_tmp);
 #endif
+          // fprintf(stderr, "val: %u-%u = %ld\n", off, off2, val);
+
+          char buf[20];
+          snprintf(buf, sizeof(buf), "%ld", val);
+
+          // fprintf(stderr, "BEFORE: %s\n", out_buf);
+
+          u32 old_len = off2 - off;
+          u32 new_len = strlen(buf);
+
+          if (old_len == new_len) {
+
+            memcpy(out_buf + off, buf, new_len);
+
+          } else {
+
+            u8 *new_buf = afl_realloc(AFL_BUF_PARAM(out_scratch),
+                                      temp_len + new_len - old_len);
+            if (unlikely(!new_buf)) { PFATAL("alloc"); }
+
+            /* Head */
+
+            memcpy(new_buf, out_buf, off);
+
+            /* Inserted part */
+
+            memcpy(new_buf + off, buf, new_len);
+
+            /* Tail */
+            memcpy(new_buf + off + new_len, out_buf + off2, temp_len - off2);
+
+            out_buf = new_buf;
+            afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch));
+            temp_len += (new_len - old_len);
+
+          }
+
+          // fprintf(stderr, "AFTER : %s\n", out_buf);
+          break;
+
+        }
 
-              out_buf = afl_realloc(AFL_BUF_PARAM(out), temp_len + extra_len);
-              if (unlikely(!out_buf)) { PFATAL("alloc"); }
+        case MUT_INSERTASCIINUM: {
 
-              /* Tail */
-              memmove(out_buf + insert_at + extra_len, out_buf + insert_at,
-                      temp_len - insert_at);
+          u32 len = 1 + rand_below(afl, 8);
+          u32 pos = rand_below(afl, temp_len);
+          /* Insert ascii number. */
+          if (unlikely(temp_len < pos + len)) {
 
-              /* Inserted part */
-              memcpy(out_buf + insert_at, ptr, extra_len);
-              temp_len += extra_len;
+            if (unlikely(temp_len < 8)) {
 
               break;
 
             } else {
 
-              r -= (r_cmp << 1);
+              goto retry_havoc_step;
 
             }
 
           }
 
-          /* Splicing otherwise if we are still here.
-             Overwrite bytes with a randomly selected chunk from another
-             testcase or insert that chunk. */
+#ifdef INTROSPECTION
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INSERTASCIINUM_");
+          strcat(afl->mutation, afl->m_tmp);
+#endif
+          u64  val = rand_next(afl);
+          char buf[20];
+          snprintf(buf, sizeof(buf), "%llu", val);
+          memcpy(out_buf + pos, buf, len);
+
+          break;
+
+        }
+
+        case MUT_EXTRA_OVERWRITE: {
+
+          if (unlikely(!afl->extras_cnt)) { goto retry_havoc_step; }
+
+          /* Use the dictionary. */
+
+          u32 use_extra = rand_below(afl, afl->extras_cnt);
+          u32 extra_len = afl->extras[use_extra].len;
+
+          if (unlikely(extra_len > temp_len)) { goto retry_havoc_step; }
+
+          u32 insert_at = rand_below(afl, temp_len - extra_len + 1);
+#ifdef INTROSPECTION
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " EXTRA-OVERWRITE_%u_%u",
+                   insert_at, extra_len);
+          strcat(afl->mutation, afl->m_tmp);
+#endif
+          memcpy(out_buf + insert_at, afl->extras[use_extra].data, extra_len);
+
+          break;
+
+        }
+
+        case MUT_EXTRA_INSERT: {
+
+          if (unlikely(!afl->extras_cnt)) { goto retry_havoc_step; }
+
+          u32 use_extra = rand_below(afl, afl->extras_cnt);
+          u32 extra_len = afl->extras[use_extra].len;
+          if (unlikely(temp_len + extra_len >= MAX_FILE)) {
+
+            goto retry_havoc_step;
+
+          }
+
+          u8 *ptr = afl->extras[use_extra].data;
+          u32 insert_at = rand_below(afl, temp_len + 1);
+#ifdef INTROSPECTION
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " EXTRA-INSERT_%u_%u",
+                   insert_at, extra_len);
+          strcat(afl->mutation, afl->m_tmp);
+#endif
+
+          out_buf = afl_realloc(AFL_BUF_PARAM(out), temp_len + extra_len);
+          if (unlikely(!out_buf)) { PFATAL("alloc"); }
+
+          /* Tail */
+          memmove(out_buf + insert_at + extra_len, out_buf + insert_at,
+                  temp_len - insert_at);
+
+          /* Inserted part */
+          memcpy(out_buf + insert_at, ptr, extra_len);
+          temp_len += extra_len;
+
+          break;
+
+        }
+
+        case MUT_AUTO_EXTRA_OVERWRITE: {
+
+          if (unlikely(!afl->a_extras_cnt)) { goto retry_havoc_step; }
+
+          /* Use the dictionary. */
+
+          u32 use_extra = rand_below(afl, afl->a_extras_cnt);
+          u32 extra_len = afl->a_extras[use_extra].len;
+
+          if (unlikely(extra_len > temp_len)) { goto retry_havoc_step; }
+
+          u32 insert_at = rand_below(afl, temp_len - extra_len + 1);
+#ifdef INTROSPECTION
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp),
+                   " AUTO-EXTRA-OVERWRITE_%u_%u", insert_at, extra_len);
+          strcat(afl->mutation, afl->m_tmp);
+#endif
+          memcpy(out_buf + insert_at, afl->a_extras[use_extra].data, extra_len);
+
+          break;
+
+        }
+
+        case MUT_AUTO_EXTRA_INSERT: {
+
+          if (unlikely(!afl->a_extras_cnt)) { goto retry_havoc_step; }
+
+          u32 use_extra = rand_below(afl, afl->a_extras_cnt);
+          u32 extra_len = afl->a_extras[use_extra].len;
+          if (unlikely(temp_len + extra_len >= MAX_FILE)) {
+
+            goto retry_havoc_step;
+
+          }
+
+          u8 *ptr = afl->a_extras[use_extra].data;
+          u32 insert_at = rand_below(afl, temp_len + 1);
+#ifdef INTROSPECTION
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " AUTO-EXTRA-INSERT_%u_%u",
+                   insert_at, extra_len);
+          strcat(afl->mutation, afl->m_tmp);
+#endif
+
+          out_buf = afl_realloc(AFL_BUF_PARAM(out), temp_len + extra_len);
+          if (unlikely(!out_buf)) { PFATAL("alloc"); }
+
+          /* Tail */
+          memmove(out_buf + insert_at + extra_len, out_buf + insert_at,
+                  temp_len - insert_at);
+
+          /* Inserted part */
+          memcpy(out_buf + insert_at, ptr, extra_len);
+          temp_len += extra_len;
+
+          break;
+
+        }
+
+        case MUT_SPLICE_OVERWRITE: {
+
+          if (unlikely(afl->ready_for_splicing_count <= 1)) {
+
+            goto retry_havoc_step;
+
+          }
 
           /* Pick a random queue entry and seek to it. */
 
@@ -2881,79 +3179,110 @@ havoc_stage:
 
             tid = rand_below(afl, afl->queued_items);
 
-          } while (tid == afl->current_entry || afl->queue_buf[tid]->len < 4);
+          } while (unlikely(tid == afl->current_entry ||
+
+                            afl->queue_buf[tid]->len < 4));
 
           /* Get the testcase for splicing. */
           struct queue_entry *target = afl->queue_buf[tid];
           u32                 new_len = target->len;
           u8                 *new_buf = queue_testcase_get(afl, target);
 
-          if ((temp_len >= 2 && r % 2) || temp_len + HAVOC_BLK_XL >= MAX_FILE) {
-
-            /* overwrite mode */
+          /* overwrite mode */
 
-            u32 copy_from, copy_to, copy_len;
+          u32 copy_from, copy_to, copy_len;
 
-            copy_len = choose_block_len(afl, new_len - 1);
-            if (copy_len > temp_len) copy_len = temp_len;
+          copy_len = choose_block_len(afl, new_len - 1);
+          if (copy_len > temp_len) copy_len = temp_len;
 
-            copy_from = rand_below(afl, new_len - copy_len + 1);
-            copy_to = rand_below(afl, temp_len - copy_len + 1);
+          copy_from = rand_below(afl, new_len - copy_len + 1);
+          copy_to = rand_below(afl, temp_len - copy_len + 1);
 
 #ifdef INTROSPECTION
-            snprintf(afl->m_tmp, sizeof(afl->m_tmp),
-                     " SPLICE_OVERWRITE-%u-%u-%u-%s", copy_from, copy_to,
-                     copy_len, target->fname);
-            strcat(afl->mutation, afl->m_tmp);
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp),
+                   " SPLICE-OVERWRITE_%u_%u_%u_%s", copy_from, copy_to,
+                   copy_len, target->fname);
+          strcat(afl->mutation, afl->m_tmp);
 #endif
-            memmove(out_buf + copy_to, new_buf + copy_from, copy_len);
+          memmove(out_buf + copy_to, new_buf + copy_from, copy_len);
 
-          } else {
+          break;
 
-            /* insert mode */
+        }
+
+        case MUT_SPLICE_INSERT: {
+
+          if (unlikely(afl->ready_for_splicing_count <= 1)) {
+
+            goto retry_havoc_step;
+
+          }
+
+          if (unlikely(temp_len + HAVOC_BLK_XL >= MAX_FILE)) {
+
+            goto retry_havoc_step;
+
+          }
 
-            u32 clone_from, clone_to, clone_len;
+          /* Pick a random queue entry and seek to it. */
+
+          u32 tid;
+          do {
+
+            tid = rand_below(afl, afl->queued_items);
 
-            clone_len = choose_block_len(afl, new_len);
-            clone_from = rand_below(afl, new_len - clone_len + 1);
-            clone_to = rand_below(afl, temp_len + 1);
+          } while (unlikely(tid == afl->current_entry ||
 
-            u8 *temp_buf = afl_realloc(AFL_BUF_PARAM(out_scratch),
-                                       temp_len + clone_len + 1);
-            if (unlikely(!temp_buf)) { PFATAL("alloc"); }
+                            afl->queue_buf[tid]->len < 4));
+
+          /* Get the testcase for splicing. */
+          struct queue_entry *target = afl->queue_buf[tid];
+          u32                 new_len = target->len;
+          u8                 *new_buf = queue_testcase_get(afl, target);
+
+          /* insert mode */
+
+          u32 clone_from, clone_to, clone_len;
+
+          clone_len = choose_block_len(afl, new_len);
+          clone_from = rand_below(afl, new_len - clone_len + 1);
+          clone_to = rand_below(afl, temp_len + 1);
+
+          u8 *temp_buf =
+              afl_realloc(AFL_BUF_PARAM(out_scratch), temp_len + clone_len + 1);
+          if (unlikely(!temp_buf)) { PFATAL("alloc"); }
 
 #ifdef INTROSPECTION
-            snprintf(afl->m_tmp, sizeof(afl->m_tmp),
-                     " SPLICE_INSERT-%u-%u-%u-%s", clone_from, clone_to,
-                     clone_len, target->fname);
-            strcat(afl->mutation, afl->m_tmp);
+          snprintf(afl->m_tmp, sizeof(afl->m_tmp), " SPLICE-INSERT_%u_%u_%u_%s",
+                   clone_from, clone_to, clone_len, target->fname);
+          strcat(afl->mutation, afl->m_tmp);
 #endif
-            /* Head */
+          /* Head */
 
-            memcpy(temp_buf, out_buf, clone_to);
+          memcpy(temp_buf, out_buf, clone_to);
 
-            /* Inserted part */
+          /* Inserted part */
 
-            memcpy(temp_buf + clone_to, new_buf + clone_from, clone_len);
+          memcpy(temp_buf + clone_to, new_buf + clone_from, clone_len);
 
-            /* Tail */
-            memcpy(temp_buf + clone_to + clone_len, out_buf + clone_to,
-                   temp_len - clone_to);
+          /* Tail */
+          memcpy(temp_buf + clone_to + clone_len, out_buf + clone_to,
+                 temp_len - clone_to);
 
-            out_buf = temp_buf;
-            afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch));
-            temp_len += clone_len;
-
-          }
+          out_buf = temp_buf;
+          afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch));
+          temp_len += clone_len;
 
           break;
 
-          // end of default
+        }
 
       }
 
     }
 
+    }
+
     if (common_fuzz_stuff(afl, out_buf, temp_len)) { goto abandon_entry; }
 
     /* out_buf might have been mangled a bit, so let's restore it to its
@@ -3039,7 +3368,9 @@ retry_splicing:
 
       tid = rand_below(afl, afl->queued_items);
 
-    } while (tid == afl->current_entry || afl->queue_buf[tid]->len < 4);
+    } while (
+
+        unlikely(tid == afl->current_entry || afl->queue_buf[tid]->len < 4));
 
     /* Get the testcase */
     afl->splicing_with = tid;
diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c
index b10bf749..48fd33ec 100644
--- a/src/afl-fuzz-queue.c
+++ b/src/afl-fuzz-queue.c
@@ -612,7 +612,7 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
 
   }
 
-  if (likely(q->len > 4)) afl->ready_for_splicing_count++;
+  if (likely(q->len > 4)) { ++afl->ready_for_splicing_count; }
 
   ++afl->queued_items;
   ++afl->active_items;
diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c
index 5e736029..99f69314 100644
--- a/src/afl-fuzz-state.c
+++ b/src/afl-fuzz-state.c
@@ -108,6 +108,7 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) {
   afl->cmplog_lvl = 2;
   afl->min_length = 1;
   afl->max_length = MAX_FILE;
+  afl->switch_fuzz_mode = STRATEGY_SWITCH_TIME * 1000;
 #ifndef NO_SPLICING
   afl->use_splicing = 1;
 #endif
diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c
index 07157bf7..1499a7e4 100644
--- a/src/afl-fuzz-stats.c
+++ b/src/afl-fuzz-stats.c
@@ -27,6 +27,45 @@
 #include "envs.h"
 #include <limits.h>
 
+static char fuzzing_state[4][12] = {"started :-)", "in progress", "final phase",
+                                    "finished..."};
+
+char *get_fuzzing_state(afl_state_t *afl) {
+
+  u64 cur_ms = get_cur_time();
+  u64 last_find = cur_ms - afl->last_find_time;
+  u64 cur_run_time = cur_ms - afl->start_time;
+  u64 cur_total_run_time = afl->prev_run_time + cur_run_time;
+
+  if (unlikely(cur_run_time < 60 * 3 * 1000 ||
+               cur_total_run_time < 60 * 5 * 1000)) {
+
+    return fuzzing_state[0];
+
+  } else {
+
+    u64 last_find_100 = 100 * last_find;
+    u64 percent_cur = last_find_100 / cur_run_time;
+    u64 percent_total = last_find_100 / cur_total_run_time;
+
+    if (unlikely(percent_cur >= 80 && percent_total >= 80)) {
+
+      return fuzzing_state[3];
+
+    } else if (unlikely(percent_cur >= 55 && percent_total >= 55)) {
+
+      return fuzzing_state[2];
+
+    } else {
+
+      return fuzzing_state[1];
+
+    }
+
+  }
+
+}
+
 /* Write fuzzer setup file */
 
 void write_setup_file(afl_state_t *afl, u32 argc, char **argv) {
@@ -1282,7 +1321,11 @@ void show_stats_normal(afl_state_t *afl) {
   }
 
   /* Last line */
-  SAYF(SET_G1 "\n" bSTG bLB bH30 bH20 bH2 bRB bSTOP cRST RESET_G1);
+
+  SAYF(SET_G1 "\n" bSTG bLB bH cCYA          bSTOP " strategy:" cPIN
+              " %s " bSTG bH10 cCYA          bSTOP " state:" cPIN
+              " %s " bSTG bH2 bRB bSTOP cRST RESET_G1,
+       afl->fuzz_mode == 0 ? "explore" : "exploit", get_fuzzing_state(afl));
 
 #undef IB
 
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index 4134b99e..d727fff5 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -129,6 +129,13 @@ static void usage(u8 *argv0, int more_help) {
       "  -o dir        - output directory for fuzzer findings\n\n"
 
       "Execution control settings:\n"
+      "  -P strategy   - set fix mutation strategy: explore (focus on new "
+      "coverage),\n"
+      "                  exploit (focus on triggering crashes). You can also "
+      "set a\n"
+      "                  number of seconds after without any finds it switches "
+      "to\n"
+      "                  exploit mode, and back on new coverage (default: %u)\n"
       "  -p schedule   - power schedules compute a seed's performance score:\n"
       "                  fast(default), explore, exploit, seek, rare, mmopt, "
       "coe, lin\n"
@@ -157,6 +164,7 @@ static void usage(u8 *argv0, int more_help) {
       "\n"
 
       "Mutator settings:\n"
+      "  -a            - target expects ascii text input\n"
       "  -g minlength  - set min length of generated fuzz input (default: 1)\n"
       "  -G maxlength  - set max length of generated fuzz input (default: "
       "%lu)\n"
@@ -212,7 +220,8 @@ static void usage(u8 *argv0, int more_help) {
       "  -e ext        - file extension for the fuzz test input file (if "
       "needed)\n"
       "\n",
-      argv0, EXEC_TIMEOUT, MEM_LIMIT, MAX_FILE, FOREIGN_SYNCS_MAX);
+      argv0, STRATEGY_SWITCH_TIME, EXEC_TIMEOUT, MEM_LIMIT, MAX_FILE,
+      FOREIGN_SYNCS_MAX);
 
   if (more_help > 1) {
 
@@ -494,14 +503,48 @@ int main(int argc, char **argv_orig, char **envp) {
 
   afl->shmem_testcase_mode = 1;  // we always try to perform shmem fuzzing
 
-  while (
-      (opt = getopt(
-           argc, argv,
-           "+Ab:B:c:CdDe:E:hi:I:f:F:g:G:l:L:m:M:nNOo:p:RQs:S:t:T:UV:WXx:YZ")) >
-      0) {
+  // still available: HjJkKqruvwz
+  while ((opt = getopt(argc, argv,
+                       "+aAb:B:c:CdDe:E:f:F:g:G:hi:I:l:L:m:M:nNo:Op:P:QRs:S:t:"
+                       "T:UV:WXx:YZ")) > 0) {
 
     switch (opt) {
 
+      case 'a':
+        afl->text_input = 1;
+        break;
+
+      case 'P':
+        if (!stricmp(optarg, "explore") || !stricmp(optarg, "exploration")) {
+
+          afl->fuzz_mode = 0;
+          afl->switch_fuzz_mode = 0;
+
+        } else if (!stricmp(optarg, "exploit") ||
+
+                   !stricmp(optarg, "exploitation")) {
+
+          afl->fuzz_mode = 1;
+          afl->switch_fuzz_mode = 0;
+
+        } else {
+
+          if ((afl->switch_fuzz_mode = (u32)atoi(optarg)) > INT_MAX) {
+
+            FATAL(
+                "Parameter for option -P must be \"explore\", \"exploit\" or a "
+                "number!");
+
+          } else {
+
+            afl->switch_fuzz_mode *= 1000;
+
+          }
+
+        }
+
+        break;
+
       case 'g':
         afl->min_length = atoi(optarg);
         break;
@@ -2688,13 +2731,31 @@ int main(int argc, char **argv_orig, char **envp) {
 
     } while (skipped_fuzz && afl->queue_cur && !afl->stop_soon);
 
+    u64 cur_time = get_cur_time();
+
+    if (likely(afl->switch_fuzz_mode && afl->fuzz_mode == 0) &&
+        unlikely(cur_time > afl->last_find_time + afl->switch_fuzz_mode)) {
+
+      if (afl->afl_env.afl_no_ui) {
+
+        ACTF(
+            "No new coverage found for %llu seconds, switching to exploitation "
+            "strategy.",
+            afl->switch_fuzz_mode / 1000);
+
+      }
+
+      afl->fuzz_mode = 1;
+
+    }
+
     if (likely(!afl->stop_soon && afl->sync_id)) {
 
       if (likely(afl->skip_deterministic)) {
 
         if (unlikely(afl->is_main_node)) {
 
-          if (unlikely(get_cur_time() >
+          if (unlikely(cur_time >
                        (afl->sync_time >> 1) + afl->last_sync_time)) {
 
             if (!(sync_interval_cnt++ % (SYNC_INTERVAL / 3))) {
@@ -2707,7 +2768,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
         } else {
 
-          if (unlikely(get_cur_time() > afl->sync_time + afl->last_sync_time)) {
+          if (unlikely(cur_time > afl->sync_time + afl->last_sync_time)) {
 
             if (!(sync_interval_cnt++ % SYNC_INTERVAL)) { sync_fuzzers(afl); }