about summary refs log tree commit diff
path: root/custom_mutators
diff options
context:
space:
mode:
Diffstat (limited to 'custom_mutators')
-rw-r--r--custom_mutators/README.md33
-rw-r--r--custom_mutators/aflpp_tritondse/README.md22
-rw-r--r--custom_mutators/aflpp_tritondse/aflpp_tritondse.py220
-rw-r--r--custom_mutators/atnwalk/Makefile7
-rw-r--r--custom_mutators/atnwalk/README.md43
-rw-r--r--custom_mutators/atnwalk/atnwalk.c539
-rw-r--r--custom_mutators/examples/custom_mutator_helpers.h342
-rw-r--r--custom_mutators/examples/custom_send.c8
-rw-r--r--custom_mutators/examples/example.c116
-rw-r--r--custom_mutators/examples/post_library_gif.so.c53
-rw-r--r--custom_mutators/examples/post_library_png.so.c24
-rw-r--r--custom_mutators/examples/simple_example.c28
-rw-r--r--custom_mutators/honggfuzz/custom_mutator_helpers.h22
-rw-r--r--custom_mutators/honggfuzz/honggfuzz.c18
-rw-r--r--custom_mutators/honggfuzz/mangle.c1181
l---------custom_mutators/radamsa/custom_mutator_helpers.h1
-rw-r--r--custom_mutators/radamsa/radamsa-mutator.c11
-rw-r--r--custom_mutators/symcc/README.md2
-rw-r--r--custom_mutators/symqemu/Makefile14
-rw-r--r--custom_mutators/symqemu/README.md19
-rw-r--r--custom_mutators/symqemu/symqemu.c424
21 files changed, 2063 insertions, 1064 deletions
diff --git a/custom_mutators/README.md b/custom_mutators/README.md
index 8d01856f..a5a572c0 100644
--- a/custom_mutators/README.md
+++ b/custom_mutators/README.md
@@ -11,7 +11,20 @@ The `./examples` folder contains examples for custom mutators in python and C.
 
 In `./rust`, you will find rust bindings, including a simple example in `./rust/example` and an example for structured fuzzing, based on lain, in`./rust/example_lain`.
 
-## The AFL++ grammar agnostic grammar mutator
+## Production-Ready Custom Mutators
+
+This directory holds ready to use custom mutators.
+Just type "make" in the individual subdirectories.
+
+Use with e.g.
+
+`AFL_CUSTOM_MUTATOR_LIBRARY=custom_mutators/radamsa/radamsa-mutator.so afl-fuzz ....`
+
+and add `AFL_CUSTOM_MUTATOR_ONLY=1` if you only want to use the custom mutator.
+
+Multiple custom mutators can be used by separating their paths with `:` in the environment variable.
+
+### The AFL++ grammar agnostic grammar mutator
 
 In `./autotokens` you find a token-level fuzzer that does not need to know
 anything about the grammar of an input as long as it is in ascii and allows
@@ -21,7 +34,7 @@ It is very fast and effective.
 If you are looking for an example of how to effectively create a custom
 mutator take a look at this one.
 
-## The AFL++ Grammar Mutator
+### The AFL++ Grammar Mutator
 
 If you use git to clone AFL++, then the following will incorporate our
 excellent grammar custom mutator:
@@ -34,18 +47,18 @@ Read the README in the [Grammar-Mutator] repository on how to use it.
 
 [Grammar-Mutator]: https://github.com/AFLplusplus/Grammar-Mutator
 
-## Production-Ready Custom Mutators
-
-This directory holds ready to use custom mutators.
-Just type "make" in the individual subdirectories.
+Note that this custom mutator is not very good though!
 
-Use with e.g.
+### Other Mutators
 
-`AFL_CUSTOM_MUTATOR_LIBRARY=custom_mutators/radamsa/radamsa-mutator.so afl-fuzz ....`
+atnwalk and gramatron are grammar custom mutators. Example grammars are
+provided.
 
-and add `AFL_CUSTOM_MUTATOR_ONLY=1` if you only want to use the custom mutator.
+honggfuzz, libfuzzer and  libafl are partial implementations based on the
+mutator implementations of the respective fuzzers. 
+More for playing than serious usage.
 
-Multiple custom mutators can be used by separating their paths with `:` in the environment variable.
+radamsa is slow and not very good.
 
 ## 3rd Party Custom Mutators
 
diff --git a/custom_mutators/aflpp_tritondse/README.md b/custom_mutators/aflpp_tritondse/README.md
new file mode 100644
index 00000000..033655d2
--- /dev/null
+++ b/custom_mutators/aflpp_tritondse/README.md
@@ -0,0 +1,22 @@
+# An AFL++ custom mutator using TritonDSE
+
+## Installing the requirements
+
+`pip3 install tritondse`
+
+## How to run with an example
+
+```
+../../afl-cc -o ../../test-instr ../../test-instr.c
+mkdir -p in
+echo aaaa > in/in
+AFL_DISABLE_TRIM=1 AFL_CUSTOM_MUTATOR_ONLY=1 AFL_SYNC_TIME=1 AFL_PYTHON_MODULE=aflpp_tritondse PYTHONPATH=. ../../afl-fuzz -i in -o out -- ../../test-instr
+```
+
+Note that this custom mutator works differently, new finds are synced
+after 10-60 seconds to the fuzzing instance. This is necessary because only
+C/C++ custom mutators have access to the internal AFL++ state.
+
+Note that you should run first with `AFL_DEBUG` for 5-10 minutes and see if
+all important libraries and syscalls are hooked (look at `WARNING` and `CRITICAL`
+output during the run, best use with `AFL_NO_UI=1`)
diff --git a/custom_mutators/aflpp_tritondse/aflpp_tritondse.py b/custom_mutators/aflpp_tritondse/aflpp_tritondse.py
new file mode 100644
index 00000000..58b506b6
--- /dev/null
+++ b/custom_mutators/aflpp_tritondse/aflpp_tritondse.py
@@ -0,0 +1,220 @@
+import sys
+import os
+import logging
+import hashlib
+
+from tritondse import CleLoader
+from tritondse import CompositeData
+from tritondse import Config
+from tritondse import CoverageStrategy
+from tritondse import ProcessState
+from tritondse import Program
+from tritondse import Seed
+from tritondse import SeedFormat
+from tritondse import SymbolicExecutor
+from tritondse import SymbolicExplorator
+
+is_debug = False
+out_path = ""
+input_file = None
+prog = None
+config = None
+dse = None
+cycle = 0
+count = 0
+finding = 0
+hashes = set()
+format = SeedFormat.RAW
+
+def pre_exec_hook(se: SymbolicExecutor, state: ProcessState):
+    global count
+    global hashes
+    global finding
+    if se.seed.hash not in hashes:
+        hashes.add(se.seed.hash)
+        finding = 1
+        filename = out_path + "/id:" + f"{count:06}" + "," + se.seed.hash
+        if not os.path.exists(filename):
+            if is_debug:
+                print('Creating queue input ' + filename)
+            with open(filename, 'wb') as file:
+                if input_file:
+                    file.write(se.seed.content.files[input_file])
+                else:
+                    file.write(se.seed.content)
+                count += 1
+    #if input_file:
+    #    if is_debug:
+    #        print('Writing to ' + input_file + ' the content: ' + str(se.seed.content))
+    #    with open(input_file, 'wb') as file:
+    #        file.write(se.seed.content)
+
+
+#def rtn_open(se: SymbolicExecutor, pstate: ProcessState, pc):
+#    """
+#    The open behavior.
+#    """
+#    logging.debug('open hooked')
+#
+#    # Get arguments
+#    arg0 = pstate.get_argument_value(0)  # const char *pathname
+#    flags = pstate.get_argument_value(1)  # int flags
+#    mode = pstate.get_argument_value(2)  # int mode
+#    arg0s = pstate.memory.read_string(arg0)
+#
+#    # Concretize the whole path name
+#    pstate.concretize_memory_bytes(arg0, len(arg0s)+1)  # Concretize the whole string + \0
+#
+#    # We use flags as concrete value
+#    pstate.concretize_argument(1)
+#
+#    # Use the flags to open the file in the write mode.
+#    mode = ""
+#    if (flags & 0xFF) == 0x00:   # O_RDONLY
+#        mode = "r"
+#    elif (flags & 0xFF) == 0x01: # O_WRONLY
+#        mode = "w"
+#    elif (flags & 0xFF) == 0x02: # O_RDWR
+#        mode = "r+"
+#
+#    if (flags & 0x0100): # O_CREAT
+#        mode += "x"
+#    if (flags & 0x0200): # O_APPEND
+#        mode = "a"  # replace completely value
+#
+#    if se.seed.is_file_defined(arg0s) and "r" in mode:  # input file and opened in reading
+#        logging.info(f"opening an input file: {arg0s}")
+#        # Program is opening an input
+#        data = se.seed.get_file_input(arg0s)
+#        filedesc = pstate.create_file_descriptor(arg0s, io.BytesIO(data))
+#        fd = filedesc.id
+#    else:
+#        # Try to open it as a regular file
+#        try:
+#            fd = open(arg0s, mode)  # use the mode here
+#            filedesc = pstate.create_file_descriptor(arg0s, fd)
+#            fd = filedesc.id
+#        except Exception as e:
+#            logging.debug(f"Failed to open {arg0s} {e}")
+#            fd = pstate.minus_one
+#
+#    pstate.write_register("rax", fd)  # write the return value
+#    pstate.cpu.program_counter = pstate.pop_stack_value()  # pop the return value
+#    se.skip_instruction()  # skip the current instruction so that the engine go straight fetching the next instruction
+
+
+def init(seed):
+    global config
+    global dse
+    global format
+    global input_file
+    global is_debug
+    global out_path
+    global prog
+    # Load the program (LIEF-based program loader).
+    prog = CleLoader(os.environ['AFL_CUSTOM_INFO_PROGRAM'])
+    # Process other configuration environment variables.
+    argv = None
+    try:
+        foo = os.environ['AFL_DEBUG']
+        is_debug = True
+    except KeyError:
+        pass
+    if is_debug:
+        logging.basicConfig(level=logging.WARNING)
+    else:
+        logging.basicConfig(level=logging.CRITICAL)
+    try:
+        foo = os.environ['AFL_CUSTOM_INFO_OUT']
+        out_path = foo + '/../tritondse/queue'
+    except KeyError:
+        pass
+    try:
+        foo = os.environ['AFL_CUSTOM_INFO_PROGRAM_INPUT']
+        input_file = foo
+    except KeyError:
+        pass
+    try:
+        argv_list = os.environ['AFL_CUSTOM_INFO_PROGRAM_ARGV']
+        argv_tmp = [ os.environ['AFL_CUSTOM_INFO_PROGRAM'] ]
+        argv_tmp += argv_list.split()
+        argv = []
+        # now check for @@
+        for item in argv_tmp:
+            if "@@" in item:
+                input_file = out_path + '/../.input'
+                argv.append(input_file)
+            else:
+                argv.append(item)
+    except KeyError:
+        pass
+    # Create the output directory
+    os.makedirs(out_path, exist_ok=True)
+    # Debug
+    if is_debug:
+        print('DEBUG target: ' + os.environ['AFL_CUSTOM_INFO_PROGRAM'])
+        if argv:
+            print('DEBUG argv: ')
+            print(argv)
+        if input_file:
+            print('DEBUG input_file: ' + input_file)
+        print('DEBUG out_path: ' + out_path)
+        print('')
+    if input_file:
+        format = SeedFormat.COMPOSITE
+    # Now set up TritonDSE
+    config = Config(coverage_strategy = CoverageStrategy.PATH,
+                    debug = is_debug,
+                    pipe_stdout = is_debug,
+                    pipe_stderr = is_debug,
+                    execution_timeout = 1,
+                    program_argv = argv,
+                    smt_timeout= 50,
+                    seed_format = format)
+    # Create an instance of the Symbolic Explorator
+    dse = SymbolicExplorator(config, prog)
+    # Add callbacks.
+    dse.callback_manager.register_pre_execution_callback(pre_exec_hook)
+    #dse.callback_manager.register_function_callback("open", rtn_open)
+
+
+def fuzz(buf, add_buf, max_size):
+    global finding
+    finding = 1
+    while finding == 1:
+      finding = 0
+      dse.step()
+    return b""
+
+
+def queue_new_entry(filename_new_queue, filename_orig_queue):
+    global cycle
+    global dse
+    # Add seed to the worklist.
+    with open(filename_new_queue, "rb") as file:
+        data = file.read()
+    hash = hashlib.md5(data).hexdigest()
+    if hash not in hashes:
+        hashes.add(hash)
+        if is_debug:
+            print("NEW FILE " + filename_new_queue + " hash " + hash + " count " + str(cycle))
+            cycle += 1
+        if input_file:
+            seed = Seed(CompositeData(files={"stdin": b"", # nothing on stdin
+                                  input_file: data}))
+        else:
+            seed = Seed(data)
+        dse.add_input_seed(seed)
+        # Start exploration!
+        #dse.step()
+        #dse.explore()
+    pass
+
+
+# we simulate just doing one single fuzz in the custom mutator
+def fuzz_count(buf):
+    return 1
+
+
+def splice_optout():
+    pass
diff --git a/custom_mutators/atnwalk/Makefile b/custom_mutators/atnwalk/Makefile
new file mode 100644
index 00000000..bf83cae5
--- /dev/null
+++ b/custom_mutators/atnwalk/Makefile
@@ -0,0 +1,7 @@
+all:	atnwalk.so
+
+atnwalk.so:	atnwalk.c
+	$(CC) -I ../../include/ -shared -fPIC -O3 -o atnwalk.so atnwalk.c
+
+clean:
+	rm -f *.so *.o *~ core
diff --git a/custom_mutators/atnwalk/README.md b/custom_mutators/atnwalk/README.md
new file mode 100644
index 00000000..730349a3
--- /dev/null
+++ b/custom_mutators/atnwalk/README.md
@@ -0,0 +1,43 @@
+# ATNwalk: Grammar-Based Fuzzing using Only Bit-Mutations
+
+This is a custom mutator integration of ATNwalk that works by communicating via UNIX domain sockets.
+
+Refer to [https://github.com/atnwalk/testbed](https://github.com/atnwalk/testbed) for detailed instructions on how to get ATNwalk running.
+
+## Build
+
+Just type `make` to build `atnwalk.so`.
+
+## Run
+
+**NOTE:** The commands below just demonstrate an example how running ATNwalk looks like and require a working [testbed](https://github.com/atnwalk/testbed)
+
+```bash
+# create the required a random seed first
+mkdir -p ~/campaign/example/seeds
+cd ~/campaign/example/seeds
+head -c1 /dev/urandom | ~/atnwalk/build/javascript/bin/decode -wb > seed.decoded 2> seed.encoded
+
+# create the required atnwalk directory and copy the seed
+cd ../
+mkdir -p atnwalk/in
+cp ./seeds/seed.encoded atnwalk/in/seed
+cd atnwalk
+
+# assign to a single core when benchmarking it, change the CPU number as required
+CPU_ID=0
+
+# start the ATNwalk server
+nohup taskset -c ${CPU_ID} ${HOME}/atnwalk/build/javascript/bin/server 100 > server.log 2>&1 &
+
+# start AFL++ with ATNwalk
+AFL_SKIP_CPUFREQ=1 \
+  AFL_DISABLE_TRIM=1 \
+  AFL_CUSTOM_MUTATOR_ONLY=1 \
+  AFL_CUSTOM_MUTATOR_LIBRARY=${HOME}/AFLplusplus/custom_mutators/atnwalk/atnwalk.so \
+  AFL_POST_PROCESS_KEEP_ORIGINAL=1 \
+  ~/AFLplusplus/afl-fuzz -t 100 -i in/ -o out -b ${CPU_ID} -- ~/jerryscript/build/bin/jerry
+
+# make sure to kill the ATNwalk server process after you're done
+kill "$(cat atnwalk.pid)"
+```
diff --git a/custom_mutators/atnwalk/atnwalk.c b/custom_mutators/atnwalk/atnwalk.c
new file mode 100644
index 00000000..c3a2cd95
--- /dev/null
+++ b/custom_mutators/atnwalk/atnwalk.c
@@ -0,0 +1,539 @@
+#include "afl-fuzz.h"
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#define BUF_SIZE_INIT 4096
+#define SOCKET_NAME "./atnwalk.socket"
+
+// how many errors (e.g. timeouts) to tolerate until moving on to the next queue
+// entry
+#define ATNWALK_ERRORS_MAX 1
+
+// how many execution timeouts to tolerate until moving on to the next queue
+// entry
+#define EXEC_TIMEOUT_MAX 2
+
+// handshake constants
+const uint8_t SERVER_ARE_YOU_ALIVE = 213;
+const uint8_t SERVER_YES_I_AM_ALIVE = 42;
+
+// control bits
+const uint8_t SERVER_CROSSOVER_BIT = 0b00000001;
+const uint8_t SERVER_MUTATE_BIT = 0b00000010;
+const uint8_t SERVER_DECODE_BIT = 0b00000100;
+const uint8_t SERVER_ENCODE_BIT = 0b00001000;
+
+typedef struct atnwalk_mutator {
+
+  afl_state_t *afl;
+  uint8_t      atnwalk_error_count;
+  uint64_t     prev_timeouts;
+  uint32_t     prev_hits;
+  uint32_t     stage_havoc_cur;
+  uint32_t     stage_havoc_max;
+  uint32_t     stage_splice_cur;
+  uint32_t     stage_splice_max;
+  uint8_t     *fuzz_buf;
+  size_t       fuzz_size;
+  uint8_t     *post_process_buf;
+  size_t       post_process_size;
+
+} atnwalk_mutator_t;
+
+int read_all(int fd, uint8_t *buf, size_t buf_size) {
+
+  int    n;
+  size_t offset = 0;
+  while (offset < buf_size) {
+
+    n = read(fd, buf + offset, buf_size - offset);
+    if (n == -1) { return 0; }
+    offset += n;
+
+  }
+
+  return 1;
+
+}
+
+int write_all(int fd, uint8_t *buf, size_t buf_size) {
+
+  int    n;
+  size_t offset = 0;
+  while (offset < buf_size) {
+
+    n = write(fd, buf + offset, buf_size - offset);
+    if (n == -1) { return 0; }
+    offset += n;
+
+  }
+
+  return 1;
+
+}
+
+void put_uint32(uint8_t *buf, uint32_t val) {
+
+  buf[0] = (uint8_t)(val >> 24);
+  buf[1] = (uint8_t)((val & 0x00ff0000) >> 16);
+  buf[2] = (uint8_t)((val & 0x0000ff00) >> 8);
+  buf[3] = (uint8_t)(val & 0x000000ff);
+
+}
+
+uint32_t to_uint32(uint8_t *buf) {
+
+  uint32_t val = 0;
+  val |= (((uint32_t)buf[0]) << 24);
+  val |= (((uint32_t)buf[1]) << 16);
+  val |= (((uint32_t)buf[2]) << 8);
+  val |= ((uint32_t)buf[3]);
+  return val;
+
+}
+
+void put_uint64(uint8_t *buf, uint64_t val) {
+
+  buf[0] = (uint8_t)(val >> 56);
+  buf[1] = (uint8_t)((val & 0x00ff000000000000) >> 48);
+  buf[2] = (uint8_t)((val & 0x0000ff0000000000) >> 40);
+  buf[3] = (uint8_t)((val & 0x000000ff00000000) >> 32);
+  buf[4] = (uint8_t)((val & 0x00000000ff000000) >> 24);
+  buf[5] = (uint8_t)((val & 0x0000000000ff0000) >> 16);
+  buf[6] = (uint8_t)((val & 0x000000000000ff00) >> 8);
+  buf[7] = (uint8_t)(val & 0x00000000000000ff);
+
+}
+
+/**
+ * Initialize this custom mutator
+ *
+ * @param[in] afl a pointer to the internal state object. Can be ignored for
+ * now.
+ * @param[in] seed A seed for this mutator - the same seed should always mutate
+ * in the same way.
+ * @return Pointer to the data object this custom mutator instance should use.
+ *         There may be multiple instances of this mutator in one afl-fuzz run!
+ *         Return NULL on error.
+ */
+atnwalk_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
+
+  srand(seed);
+  atnwalk_mutator_t *data =
+      (atnwalk_mutator_t *)malloc(sizeof(atnwalk_mutator_t));
+  if (!data) {
+
+    perror("afl_custom_init alloc");
+    return NULL;
+
+  }
+
+  data->afl = afl;
+  data->prev_hits = 0;
+  data->fuzz_buf = (uint8_t *)malloc(BUF_SIZE_INIT);
+  data->fuzz_size = BUF_SIZE_INIT;
+  data->post_process_buf = (uint8_t *)malloc(BUF_SIZE_INIT);
+  data->post_process_size = BUF_SIZE_INIT;
+  return data;
+
+}
+
+unsigned int afl_custom_fuzz_count(atnwalk_mutator_t   *data,
+                                   const unsigned char *buf, size_t buf_size) {
+
+  // afl_custom_fuzz_count is called exactly once before entering the
+  // 'stage-loop' for the current queue entry thus, we use it to reset the error
+  // count and to initialize stage variables (somewhat not intended by the API,
+  // but still better than rewriting the whole thing to have a custom mutator
+  // stage)
+  data->atnwalk_error_count = 0;
+  data->prev_timeouts = data->afl->total_tmouts;
+
+  // it might happen that on the last execution of the splice stage a new path
+  // is found we need to fix that here and count it
+  if (data->prev_hits) {
+
+    data->afl->stage_finds[STAGE_SPLICE] +=
+        data->afl->queued_items + data->afl->saved_crashes - data->prev_hits;
+
+  }
+
+  data->prev_hits = data->afl->queued_items + data->afl->saved_crashes;
+  data->stage_havoc_cur = 0;
+  data->stage_splice_cur = 0;
+
+  // 50% havoc, 50% splice
+  data->stage_havoc_max = data->afl->stage_max >> 1;
+  if (data->stage_havoc_max < HAVOC_MIN) { data->stage_havoc_max = HAVOC_MIN; }
+  data->stage_splice_max = data->stage_havoc_max;
+  return data->stage_havoc_max + data->stage_splice_max;
+
+}
+
+size_t fail_fatal(int fd_socket, uint8_t **out_buf) {
+
+  if (fd_socket != -1) { close(fd_socket); }
+  *out_buf = NULL;
+  return 0;
+
+}
+
+size_t fail_gracefully(int fd_socket, atnwalk_mutator_t *data, uint8_t *buf,
+                       size_t buf_size, uint8_t **out_buf) {
+
+  if (fd_socket != -1) { close(fd_socket); }
+  data->atnwalk_error_count++;
+  if (data->atnwalk_error_count > ATNWALK_ERRORS_MAX) {
+
+    data->afl->stage_max = data->afl->stage_cur;
+
+  }
+
+  *out_buf = buf;
+  return buf_size;
+
+}
+
+/**
+ * Perform custom mutations on a given input
+ *
+ * (Optional for now. Required in the future)
+ *
+ * @param[in] data pointer returned in afl_custom_init for this fuzz case
+ * @param[in] buf Pointer to input data to be mutated
+ * @param[in] buf_size Size of input data
+ * @param[out] out_buf the buffer we will work on. we can reuse *buf. NULL on
+ * error.
+ * @param[in] add_buf Buffer containing the additional test case
+ * @param[in] add_buf_size Size of the additional test case
+ * @param[in] max_size Maximum size of the mutated output. The mutation must not
+ *     produce data larger than max_size.
+ * @return Size of the mutated output.
+ */
+size_t afl_custom_fuzz(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size,
+                       uint8_t **out_buf, uint8_t *add_buf, size_t add_buf_size,
+                       size_t max_size) {
+
+  struct sockaddr_un addr;
+  int                fd_socket;
+  uint8_t            ctrl_buf[8];
+  uint8_t            wanted;
+
+  // let's display what's going on in a nice way
+  if (data->stage_havoc_cur == 0) {
+
+    data->afl->stage_name = (uint8_t *)"atnwalk - havoc";
+
+  }
+
+  if (data->stage_havoc_cur == data->stage_havoc_max) {
+
+    data->afl->stage_name = (uint8_t *)"atnwalk - splice";
+
+  }
+
+  // increase the respective havoc or splice counters
+  if (data->stage_havoc_cur < data->stage_havoc_max) {
+
+    data->stage_havoc_cur++;
+    data->afl->stage_cycles[STAGE_HAVOC]++;
+
+  } else {
+
+    // if there is nothing to splice, continue with havoc and skip splicing this
+    // time
+    if (data->afl->ready_for_splicing_count < 1) {
+
+      data->stage_havoc_max = data->afl->stage_max;
+      data->stage_havoc_cur++;
+      data->afl->stage_cycles[STAGE_HAVOC]++;
+
+    } else {
+
+      data->stage_splice_cur++;
+      data->afl->stage_cycles[STAGE_SPLICE]++;
+
+    }
+
+  }
+
+  // keep track of found new corpus seeds per stage
+  if (data->afl->queued_items + data->afl->saved_crashes > data->prev_hits) {
+
+    if (data->stage_splice_cur <= 1) {
+
+      data->afl->stage_finds[STAGE_HAVOC] +=
+          data->afl->queued_items + data->afl->saved_crashes - data->prev_hits;
+
+    } else {
+
+      data->afl->stage_finds[STAGE_SPLICE] +=
+          data->afl->queued_items + data->afl->saved_crashes - data->prev_hits;
+
+    }
+
+  }
+
+  data->prev_hits = data->afl->queued_items + data->afl->saved_crashes;
+
+  // check whether this input produces a lot of timeouts, if it does then
+  // abandon this queue entry
+  if (data->afl->total_tmouts - data->prev_timeouts >= EXEC_TIMEOUT_MAX) {
+
+    data->afl->stage_max = data->afl->stage_cur;
+    return fail_gracefully(-1, data, buf, buf_size, out_buf);
+
+  }
+
+  // initialize the socket
+  fd_socket = socket(AF_UNIX, SOCK_STREAM, 0);
+  if (fd_socket == -1) { return fail_fatal(fd_socket, out_buf); }
+  memset(&addr, 0, sizeof(addr));
+  addr.sun_family = AF_UNIX;
+  strncpy(addr.sun_path, SOCKET_NAME, sizeof(addr.sun_path) - 1);
+  if (connect(fd_socket, (const struct sockaddr *)&addr, sizeof(addr)) == -1) {
+
+    return fail_fatal(fd_socket, out_buf);
+
+  }
+
+  // ask whether the server is alive
+  ctrl_buf[0] = SERVER_ARE_YOU_ALIVE;
+  if (!write_all(fd_socket, ctrl_buf, 1)) {
+
+    return fail_fatal(fd_socket, out_buf);
+
+  }
+
+  // see whether the server replies as expected
+  if (!read_all(fd_socket, ctrl_buf, 1) ||
+      ctrl_buf[0] != SERVER_YES_I_AM_ALIVE) {
+
+    return fail_fatal(fd_socket, out_buf);
+
+  }
+
+  // tell the server what we want to do
+  wanted = SERVER_MUTATE_BIT | SERVER_ENCODE_BIT;
+
+  // perform a crossover if we are splicing
+  if (data->stage_splice_cur > 0) { wanted |= SERVER_CROSSOVER_BIT; }
+
+  // tell the server what we want and how much data will be sent
+  ctrl_buf[0] = wanted;
+  put_uint32(ctrl_buf + 1, (uint32_t)buf_size);
+  if (!write_all(fd_socket, ctrl_buf, 5)) {
+
+    return fail_fatal(fd_socket, out_buf);
+
+  }
+
+  // send the data to mutate and encode
+  if (!write_all(fd_socket, buf, buf_size)) {
+
+    return fail_gracefully(fd_socket, data, buf, buf_size, out_buf);
+
+  }
+
+  if (wanted & SERVER_CROSSOVER_BIT) {
+
+    // since we requested crossover, we will first tell how much additional data
+    // is to be expected
+    put_uint32(ctrl_buf, (uint32_t)add_buf_size);
+    if (!write_all(fd_socket, ctrl_buf, 4)) {
+
+      return fail_gracefully(fd_socket, data, buf, buf_size, out_buf);
+
+    }
+
+    // send the additional data for crossover
+    if (!write_all(fd_socket, add_buf, add_buf_size)) {
+
+      return fail_gracefully(fd_socket, data, buf, buf_size, out_buf);
+
+    }
+
+    // lastly, a seed is required for crossover so send one
+    put_uint64(ctrl_buf, (uint64_t)rand());
+    if (!write_all(fd_socket, ctrl_buf, 8)) {
+
+      return fail_gracefully(fd_socket, data, buf, buf_size, out_buf);
+
+    }
+
+  }
+
+  // since we requested mutation, we need to provide a seed for that
+  put_uint64(ctrl_buf, (uint64_t)rand());
+  if (!write_all(fd_socket, ctrl_buf, 8)) {
+
+    return fail_gracefully(fd_socket, data, buf, buf_size, out_buf);
+
+  }
+
+  // obtain the required buffer size for the data that will be returned
+  if (!read_all(fd_socket, ctrl_buf, 4)) {
+
+    return fail_gracefully(fd_socket, data, buf, buf_size, out_buf);
+
+  }
+
+  size_t new_size = (size_t)to_uint32(ctrl_buf);
+
+  // if the data is too large then we ignore this round
+  if (new_size > max_size) {
+
+    return fail_gracefully(fd_socket, data, buf, buf_size, out_buf);
+
+  }
+
+  if (new_size > buf_size) {
+
+    // buf is too small, need to use data->fuzz_buf, let's see whether we need
+    // to reallocate
+    if (new_size > data->fuzz_size) {
+
+      data->fuzz_size = new_size << 1;
+      data->fuzz_buf = (uint8_t *)realloc(data->fuzz_buf, data->fuzz_size);
+
+    }
+
+    *out_buf = data->fuzz_buf;
+
+  } else {
+
+    // new_size fits into buf, so re-use it
+    *out_buf = buf;
+
+  }
+
+  // obtain the encoded data
+  if (!read_all(fd_socket, *out_buf, new_size)) {
+
+    return fail_gracefully(fd_socket, data, buf, buf_size, out_buf);
+
+  }
+
+  close(fd_socket);
+  return new_size;
+
+}
+
+/**
+ * A post-processing function to use right before AFL writes the test case to
+ * disk in order to execute the target.
+ *
+ * (Optional) If this functionality is not needed, simply don't define this
+ * function.
+ *
+ * @param[in] data pointer returned in afl_custom_init for this fuzz case
+ * @param[in] buf Buffer containing the test case to be executed
+ * @param[in] buf_size Size of the test case
+ * @param[out] out_buf Pointer to the buffer containing the test case after
+ *     processing. External library should allocate memory for out_buf.
+ *     The buf pointer may be reused (up to the given buf_size);
+ * @return Size of the output buffer after processing or the needed amount.
+ *     A return of 0 indicates an error.
+ */
+size_t afl_custom_post_process(atnwalk_mutator_t *data, uint8_t *buf,
+                               size_t buf_size, uint8_t **out_buf) {
+
+  struct sockaddr_un addr;
+  int                fd_socket;
+  uint8_t            ctrl_buf[8];
+
+  // initialize the socket
+  fd_socket = socket(AF_UNIX, SOCK_STREAM, 0);
+  if (fd_socket == -1) { return fail_fatal(fd_socket, out_buf); }
+  memset(&addr, 0, sizeof(addr));
+  addr.sun_family = AF_UNIX;
+  strncpy(addr.sun_path, SOCKET_NAME, sizeof(addr.sun_path) - 1);
+  if (connect(fd_socket, (const struct sockaddr *)&addr, sizeof(addr)) == -1) {
+
+    return fail_fatal(fd_socket, out_buf);
+
+  }
+
+  // ask whether the server is alive
+  ctrl_buf[0] = SERVER_ARE_YOU_ALIVE;
+  if (!write_all(fd_socket, ctrl_buf, 1)) {
+
+    return fail_fatal(fd_socket, out_buf);
+
+  }
+
+  // see whether the server replies as expected
+  if (!read_all(fd_socket, ctrl_buf, 1) ||
+      ctrl_buf[0] != SERVER_YES_I_AM_ALIVE) {
+
+    return fail_fatal(fd_socket, out_buf);
+
+  }
+
+  // tell the server what we want and how much data will be sent
+  ctrl_buf[0] = SERVER_DECODE_BIT;
+  put_uint32(ctrl_buf + 1, (uint32_t)buf_size);
+  if (!write_all(fd_socket, ctrl_buf, 5)) {
+
+    return fail_gracefully(fd_socket, data, buf, buf_size, out_buf);
+
+  }
+
+  // send the data to decode
+  if (!write_all(fd_socket, buf, buf_size)) {
+
+    return fail_gracefully(fd_socket, data, buf, buf_size, out_buf);
+
+  }
+
+  // obtain the required buffer size for the data that will be returned
+  if (!read_all(fd_socket, ctrl_buf, 4)) {
+
+    return fail_gracefully(fd_socket, data, buf, buf_size, out_buf);
+
+  }
+
+  size_t new_size = (size_t)to_uint32(ctrl_buf);
+
+  // need to use data->post_process_buf, let's see whether we need to reallocate
+  if (new_size > data->post_process_size) {
+
+    data->post_process_size = new_size << 1;
+    data->post_process_buf =
+        (uint8_t *)realloc(data->post_process_buf, data->post_process_size);
+
+  }
+
+  *out_buf = data->post_process_buf;
+
+  // obtain the decoded data
+  if (!read_all(fd_socket, *out_buf, new_size)) {
+
+    return fail_gracefully(fd_socket, data, buf, buf_size, out_buf);
+
+  }
+
+  close(fd_socket);
+  return new_size;
+
+}
+
+/**
+ * Deinitialize everything
+ *
+ * @param data The data ptr from afl_custom_init
+ */
+void afl_custom_deinit(atnwalk_mutator_t *data) {
+
+  free(data->fuzz_buf);
+  free(data->post_process_buf);
+  free(data);
+
+}
+
diff --git a/custom_mutators/examples/custom_mutator_helpers.h b/custom_mutators/examples/custom_mutator_helpers.h
deleted file mode 100644
index 62e6efba..00000000
--- a/custom_mutators/examples/custom_mutator_helpers.h
+++ /dev/null
@@ -1,342 +0,0 @@
-#ifndef CUSTOM_MUTATOR_HELPERS
-#define CUSTOM_MUTATOR_HELPERS
-
-#include "config.h"
-#include "types.h"
-#include <stdlib.h>
-
-#define INITIAL_GROWTH_SIZE (64)
-
-#define RAND_BELOW(limit) (rand() % (limit))
-
-/* Use in a struct: creates a name_buf and a name_size variable. */
-#define BUF_VAR(type, name) \
-  type * name##_buf;        \
-  size_t name##_size;
-/* this fills in `&structptr->something_buf, &structptr->something_size`. */
-#define BUF_PARAMS(struct, name) \
-  (void **)&struct->name##_buf, &struct->name##_size
-
-typedef struct {
-
-} afl_t;
-
-static void surgical_havoc_mutate(u8 *out_buf, s32 begin, s32 end) {
-
-  static s8  interesting_8[] = {INTERESTING_8};
-  static s16 interesting_16[] = {INTERESTING_8, INTERESTING_16};
-  static s32 interesting_32[] = {INTERESTING_8, INTERESTING_16, INTERESTING_32};
-
-  switch (RAND_BELOW(12)) {
-
-    case 0: {
-
-      /* Flip a single bit somewhere. Spooky! */
-
-      s32 bit_idx = ((RAND_BELOW(end - begin) + begin) << 3) + RAND_BELOW(8);
-
-      out_buf[bit_idx >> 3] ^= 128 >> (bit_idx & 7);
-
-      break;
-
-    }
-
-    case 1: {
-
-      /* Set byte to interesting value. */
-
-      u8 val = interesting_8[RAND_BELOW(sizeof(interesting_8))];
-      out_buf[(RAND_BELOW(end - begin) + begin)] = val;
-
-      break;
-
-    }
-
-    case 2: {
-
-      /* Set word to interesting value, randomly choosing endian. */
-
-      if (end - begin < 2) break;
-
-      s32 byte_idx = (RAND_BELOW(end - begin) + begin);
-
-      if (byte_idx >= end - 1) break;
-
-      switch (RAND_BELOW(2)) {
-
-        case 0:
-          *(u16 *)(out_buf + byte_idx) =
-              interesting_16[RAND_BELOW(sizeof(interesting_16) >> 1)];
-          break;
-        case 1:
-          *(u16 *)(out_buf + byte_idx) =
-              SWAP16(interesting_16[RAND_BELOW(sizeof(interesting_16) >> 1)]);
-          break;
-
-      }
-
-      break;
-
-    }
-
-    case 3: {
-
-      /* Set dword to interesting value, randomly choosing endian. */
-
-      if (end - begin < 4) break;
-
-      s32 byte_idx = (RAND_BELOW(end - begin) + begin);
-
-      if (byte_idx >= end - 3) break;
-
-      switch (RAND_BELOW(2)) {
-
-        case 0:
-          *(u32 *)(out_buf + byte_idx) =
-              interesting_32[RAND_BELOW(sizeof(interesting_32) >> 2)];
-          break;
-        case 1:
-          *(u32 *)(out_buf + byte_idx) =
-              SWAP32(interesting_32[RAND_BELOW(sizeof(interesting_32) >> 2)]);
-          break;
-
-      }
-
-      break;
-
-    }
-
-    case 4: {
-
-      /* Set qword to interesting value, randomly choosing endian. */
-
-      if (end - begin < 8) break;
-
-      s32 byte_idx = (RAND_BELOW(end - begin) + begin);
-
-      if (byte_idx >= end - 7) break;
-
-      switch (RAND_BELOW(2)) {
-
-        case 0:
-          *(u64 *)(out_buf + byte_idx) =
-              (s64)interesting_32[RAND_BELOW(sizeof(interesting_32) >> 2)];
-          break;
-        case 1:
-          *(u64 *)(out_buf + byte_idx) = SWAP64(
-              (s64)interesting_32[RAND_BELOW(sizeof(interesting_32) >> 2)]);
-          break;
-
-      }
-
-      break;
-
-    }
-
-    case 5: {
-
-      /* Randomly subtract from byte. */
-
-      out_buf[(RAND_BELOW(end - begin) + begin)] -= 1 + RAND_BELOW(ARITH_MAX);
-
-      break;
-
-    }
-
-    case 6: {
-
-      /* Randomly add to byte. */
-
-      out_buf[(RAND_BELOW(end - begin) + begin)] += 1 + RAND_BELOW(ARITH_MAX);
-
-      break;
-
-    }
-
-    case 7: {
-
-      /* Randomly subtract from word, random endian. */
-
-      if (end - begin < 2) break;
-
-      s32 byte_idx = (RAND_BELOW(end - begin) + begin);
-
-      if (byte_idx >= end - 1) break;
-
-      if (RAND_BELOW(2)) {
-
-        *(u16 *)(out_buf + byte_idx) -= 1 + RAND_BELOW(ARITH_MAX);
-
-      } else {
-
-        u16 num = 1 + RAND_BELOW(ARITH_MAX);
-
-        *(u16 *)(out_buf + byte_idx) =
-            SWAP16(SWAP16(*(u16 *)(out_buf + byte_idx)) - num);
-
-      }
-
-      break;
-
-    }
-
-    case 8: {
-
-      /* Randomly add to word, random endian. */
-
-      if (end - begin < 2) break;
-
-      s32 byte_idx = (RAND_BELOW(end - begin) + begin);
-
-      if (byte_idx >= end - 1) break;
-
-      if (RAND_BELOW(2)) {
-
-        *(u16 *)(out_buf + byte_idx) += 1 + RAND_BELOW(ARITH_MAX);
-
-      } else {
-
-        u16 num = 1 + RAND_BELOW(ARITH_MAX);
-
-        *(u16 *)(out_buf + byte_idx) =
-            SWAP16(SWAP16(*(u16 *)(out_buf + byte_idx)) + num);
-
-      }
-
-      break;
-
-    }
-
-    case 9: {
-
-      /* Randomly subtract from dword, random endian. */
-
-      if (end - begin < 4) break;
-
-      s32 byte_idx = (RAND_BELOW(end - begin) + begin);
-
-      if (byte_idx >= end - 3) break;
-
-      if (RAND_BELOW(2)) {
-
-        *(u32 *)(out_buf + byte_idx) -= 1 + RAND_BELOW(ARITH_MAX);
-
-      } else {
-
-        u32 num = 1 + RAND_BELOW(ARITH_MAX);
-
-        *(u32 *)(out_buf + byte_idx) =
-            SWAP32(SWAP32(*(u32 *)(out_buf + byte_idx)) - num);
-
-      }
-
-      break;
-
-    }
-
-    case 10: {
-
-      /* Randomly add to dword, random endian. */
-
-      if (end - begin < 4) break;
-
-      s32 byte_idx = (RAND_BELOW(end - begin) + begin);
-
-      if (byte_idx >= end - 3) break;
-
-      if (RAND_BELOW(2)) {
-
-        *(u32 *)(out_buf + byte_idx) += 1 + RAND_BELOW(ARITH_MAX);
-
-      } else {
-
-        u32 num = 1 + RAND_BELOW(ARITH_MAX);
-
-        *(u32 *)(out_buf + byte_idx) =
-            SWAP32(SWAP32(*(u32 *)(out_buf + byte_idx)) + num);
-
-      }
-
-      break;
-
-    }
-
-    case 11: {
-
-      /* 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. */
-
-      out_buf[(RAND_BELOW(end - begin) + begin)] ^= 1 + RAND_BELOW(255);
-
-      break;
-
-    }
-
-  }
-
-}
-
-/* This function calculates the next power of 2 greater or equal its argument.
- @return The rounded up power of 2 (if no overflow) or 0 on overflow.
-*/
-static inline size_t next_pow2(size_t in) {
-
-  if (in == 0 || in > (size_t)-1)
-    return 0;                  /* avoid undefined behaviour under-/overflow */
-  size_t out = in - 1;
-  out |= out >> 1;
-  out |= out >> 2;
-  out |= out >> 4;
-  out |= out >> 8;
-  out |= out >> 16;
-  return out + 1;
-
-}
-
-/* This function makes sure *size is > size_needed after call.
- It will realloc *buf otherwise.
- *size will grow exponentially as per:
- https://blog.mozilla.org/nnethercote/2014/11/04/please-grow-your-buffers-exponentially/
- Will return NULL and free *buf if size_needed is <1 or realloc failed.
- @return For convenience, this function returns *buf.
- */
-static inline void *maybe_grow(void **buf, size_t *size, size_t size_needed) {
-
-  /* No need to realloc */
-  if (likely(size_needed && *size >= size_needed)) return *buf;
-
-  /* No initial size was set */
-  if (size_needed < INITIAL_GROWTH_SIZE) size_needed = INITIAL_GROWTH_SIZE;
-
-  /* grow exponentially */
-  size_t next_size = next_pow2(size_needed);
-
-  /* handle overflow */
-  if (!next_size) { next_size = size_needed; }
-
-  /* alloc */
-  *buf = realloc(*buf, next_size);
-  *size = *buf ? next_size : 0;
-
-  return *buf;
-
-}
-
-/* Swaps buf1 ptr and buf2 ptr, as well as their sizes */
-static inline void afl_swap_bufs(void **buf1, size_t *size1, void **buf2,
-                                 size_t *size2) {
-
-  void * scratch_buf = *buf1;
-  size_t scratch_size = *size1;
-  *buf1 = *buf2;
-  *size1 = *size2;
-  *buf2 = scratch_buf;
-  *size2 = scratch_size;
-
-}
-
-#undef INITIAL_GROWTH_SIZE
-
-#endif
-
diff --git a/custom_mutators/examples/custom_send.c b/custom_mutators/examples/custom_send.c
index 7de72819..9cc4b160 100644
--- a/custom_mutators/examples/custom_send.c
+++ b/custom_mutators/examples/custom_send.c
@@ -10,21 +10,21 @@
 //   afl-fuzz -i in -o out -- ./test-instr -f /tmp/foo
 //
 
-#include "custom_mutator_helpers.h"
-
 #include <stdio.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <fcntl.h>
 
+#include "afl-fuzz.h"
+
 typedef struct my_mutator {
 
-  afl_t *afl;
+  afl_state_t *afl;
 
 } my_mutator_t;
 
-my_mutator_t *afl_custom_init(afl_t *afl, unsigned int seed) {
+my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
 
   my_mutator_t *data = calloc(1, sizeof(my_mutator_t));
   if (!data) {
diff --git a/custom_mutators/examples/example.c b/custom_mutators/examples/example.c
index e680ec8e..42c7469c 100644
--- a/custom_mutators/examples/example.c
+++ b/custom_mutators/examples/example.c
@@ -7,7 +7,7 @@
 */
 
 // You need to use -I/path/to/AFLplusplus/include -I.
-#include "custom_mutator_helpers.h"
+#include "afl-fuzz.h"
 
 #include <stdint.h>
 #include <stdlib.h>
@@ -26,19 +26,14 @@ static const char *commands[] = {
 
 typedef struct my_mutator {
 
-  afl_t *afl;
+  afl_state_t *afl;
 
   // any additional data here!
   size_t trim_size_current;
   int    trimmming_steps;
   int    cur_step;
 
-  // Reused buffers:
-  BUF_VAR(u8, fuzz);
-  BUF_VAR(u8, data);
-  BUF_VAR(u8, havoc);
-  BUF_VAR(u8, trim);
-  BUF_VAR(u8, post_process);
+  u8 *mutated_out, *post_process_buf, *trim_buf;
 
 } my_mutator_t;
 
@@ -53,7 +48,7 @@ typedef struct my_mutator {
  *         There may be multiple instances of this mutator in one afl-fuzz run!
  *         Return NULL on error.
  */
-my_mutator_t *afl_custom_init(afl_t *afl, unsigned int seed) {
+my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
 
   srand(seed);  // needed also by surgical_havoc_mutate()
 
@@ -65,6 +60,27 @@ my_mutator_t *afl_custom_init(afl_t *afl, unsigned int seed) {
 
   }
 
+  if ((data->mutated_out = (u8 *)malloc(MAX_FILE)) == NULL) {
+
+    perror("afl_custom_init malloc");
+    return NULL;
+
+  }
+
+  if ((data->post_process_buf = (u8 *)malloc(MAX_FILE)) == NULL) {
+
+    perror("afl_custom_init malloc");
+    return NULL;
+
+  }
+
+  if ((data->trim_buf = (u8 *)malloc(MAX_FILE)) == NULL) {
+
+    perror("afl_custom_init malloc");
+    return NULL;
+
+  }
+
   data->afl = afl;
 
   return data;
@@ -96,31 +112,14 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
   // the fuzzer
   size_t mutated_size = DATA_SIZE <= max_size ? DATA_SIZE : max_size;
 
-  // maybe_grow is optimized to be quick for reused buffers.
-  u8 *mutated_out = maybe_grow(BUF_PARAMS(data, fuzz), mutated_size);
-  if (!mutated_out) {
-
-    *out_buf = NULL;
-    perror("custom mutator allocation (maybe_grow)");
-    return 0;            /* afl-fuzz will very likely error out after this. */
-
-  }
+  memcpy(data->mutated_out, buf, buf_size);
 
   // Randomly select a command string to add as a header to the packet
-  memcpy(mutated_out, commands[rand() % 3], 3);
+  memcpy(data->mutated_out, commands[rand() % 3], 3);
 
-  // Mutate the payload of the packet
-  int i;
-  for (i = 0; i < 8; ++i) {
+  if (mutated_size > max_size) { mutated_size = max_size; }
 
-    // Randomly perform one of the (no len modification) havoc mutations
-    surgical_havoc_mutate(mutated_out, 3, mutated_size);
-
-  }
-
-  if (max_size > mutated_size) { mutated_size = max_size; }
-
-  *out_buf = mutated_out;
+  *out_buf = data->mutated_out;
   return mutated_size;
 
 }
@@ -144,24 +143,16 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
 size_t afl_custom_post_process(my_mutator_t *data, uint8_t *buf,
                                size_t buf_size, uint8_t **out_buf) {
 
-  uint8_t *post_process_buf =
-      maybe_grow(BUF_PARAMS(data, post_process), buf_size + 5);
-  if (!post_process_buf) {
+  if (buf_size + 5 > MAX_FILE) { buf_size = MAX_FILE - 5; }
 
-    perror("custom mutator realloc failed.");
-    *out_buf = NULL;
-    return 0;
+  memcpy(data->post_process_buf + 5, buf, buf_size);
+  data->post_process_buf[0] = 'A';
+  data->post_process_buf[1] = 'F';
+  data->post_process_buf[2] = 'L';
+  data->post_process_buf[3] = '+';
+  data->post_process_buf[4] = '+';
 
-  }
-
-  memcpy(post_process_buf + 5, buf, buf_size);
-  post_process_buf[0] = 'A';
-  post_process_buf[1] = 'F';
-  post_process_buf[2] = 'L';
-  post_process_buf[3] = '+';
-  post_process_buf[4] = '+';
-
-  *out_buf = post_process_buf;
+  *out_buf = data->post_process_buf;
 
   return buf_size + 5;
 
@@ -197,13 +188,6 @@ int32_t afl_custom_init_trim(my_mutator_t *data, uint8_t *buf,
 
   data->cur_step = 0;
 
-  if (!maybe_grow(BUF_PARAMS(data, trim), buf_size)) {
-
-    perror("init_trim grow");
-    return -1;
-
-  }
-
   memcpy(data->trim_buf, buf, buf_size);
 
   data->trim_size_current = buf_size;
@@ -284,27 +268,11 @@ int32_t afl_custom_post_trim(my_mutator_t *data, int success) {
 size_t afl_custom_havoc_mutation(my_mutator_t *data, u8 *buf, size_t buf_size,
                                  u8 **out_buf, size_t max_size) {
 
-  if (buf_size == 0) {
-
-    *out_buf = maybe_grow(BUF_PARAMS(data, havoc), 1);
-    if (!*out_buf) {
-
-      perror("custom havoc: maybe_grow");
-      return 0;
-
-    }
+  *out_buf = buf;  // in-place mutation
 
-    **out_buf = rand() % 256;
-    buf_size = 1;
-
-  } else {
-
-    // We reuse buf here. It's legal and faster.
-    *out_buf = buf;
-
-  }
+  if (buf_size <= sizeof(size_t)) { return buf_size; }
 
-  size_t victim = rand() % buf_size;
+  size_t victim = rand() % (buf_size - sizeof(size_t));
   (*out_buf)[victim] += rand() % 10;
 
   return buf_size;
@@ -371,9 +339,7 @@ uint8_t afl_custom_queue_new_entry(my_mutator_t  *data,
 void afl_custom_deinit(my_mutator_t *data) {
 
   free(data->post_process_buf);
-  free(data->havoc_buf);
-  free(data->data_buf);
-  free(data->fuzz_buf);
+  free(data->mutated_out);
   free(data->trim_buf);
   free(data);
 
diff --git a/custom_mutators/examples/post_library_gif.so.c b/custom_mutators/examples/post_library_gif.so.c
index 3cb018a6..6737c627 100644
--- a/custom_mutators/examples/post_library_gif.so.c
+++ b/custom_mutators/examples/post_library_gif.so.c
@@ -45,9 +45,8 @@
    1) If you don't want to modify the test case, simply set `*out_buf = in_buf`
       and return the original `len`.
 
-   NOTE: the following is currently NOT true, we abort in this case!
    2) If you want to skip this test case altogether and have AFL generate a
-      new one, return 0 or set `*out_buf = NULL`.
+      new one, return 0.
       Use this sparingly - it's faster than running the target program
       with patently useless inputs, but still wastes CPU time.
 
@@ -59,8 +58,6 @@
       Note that the buffer will *not* be freed for you. To avoid memory leaks,
       you need to free it or reuse it on subsequent calls (as shown below).
 
-      *** Feel free to reuse the original 'in_buf' BUFFER and return it. ***
-
     Alright. The example below shows a simple postprocessor that tries to make
     sure that all input files start with "GIF89a".
 
@@ -72,7 +69,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include "alloc-inl.h"
+#include "afl-fuzz.h"
 
 /* Header that must be present at the beginning of every test case: */
 
@@ -80,8 +77,7 @@
 
 typedef struct post_state {
 
-  unsigned char *buf;
-  size_t         size;
+  size_t size;
 
 } post_state_t;
 
@@ -95,15 +91,6 @@ void *afl_custom_init(void *afl) {
 
   }
 
-  state->buf = calloc(sizeof(unsigned char), 4096);
-  if (!state->buf) {
-
-    free(state);
-    perror("calloc");
-    return NULL;
-
-  }
-
   return state;
 
 }
@@ -113,6 +100,10 @@ void *afl_custom_init(void *afl) {
 size_t afl_custom_post_process(post_state_t *data, unsigned char *in_buf,
                                unsigned int len, unsigned char **out_buf) {
 
+  /* we do in-place modification as we do not increase the size */
+
+  *out_buf = in_buf;
+
   /* Skip execution altogether for buffers shorter than 6 bytes (just to
      show how it's done). We can trust len to be sane. */
 
@@ -120,34 +111,7 @@ size_t afl_custom_post_process(post_state_t *data, unsigned char *in_buf,
 
   /* Do nothing for buffers that already start with the expected header. */
 
-  if (!memcmp(in_buf, HEADER, strlen(HEADER))) {
-
-    *out_buf = in_buf;
-    return len;
-
-  }
-
-  /* Allocate memory for new buffer, reusing previous allocation if
-     possible. Note we have to use afl-fuzz's own realloc!
-     We use afl_realloc because it is effective.
-     You can also work within in_buf, and assign it to *out_buf. */
-
-  *out_buf = afl_realloc(out_buf, len);
-
-  /* If we're out of memory, the most graceful thing to do is to return the
-     original buffer and give up on modifying it. Let AFL handle OOM on its
-     own later on. */
-
-  if (!*out_buf) {
-
-    *out_buf = in_buf;
-    return len;
-
-  }
-
-  if (len > strlen(HEADER))
-    memcpy(*out_buf + strlen(HEADER), in_buf + strlen(HEADER),
-           len - strlen(HEADER));
+  if (!memcmp(in_buf, HEADER, strlen(HEADER))) { return len; }
 
   /* Insert the new header. */
 
@@ -162,7 +126,6 @@ size_t afl_custom_post_process(post_state_t *data, unsigned char *in_buf,
 /* Gets called afterwards */
 void afl_custom_deinit(post_state_t *data) {
 
-  free(data->buf);
   free(data);
 
 }
diff --git a/custom_mutators/examples/post_library_png.so.c b/custom_mutators/examples/post_library_png.so.c
index cd65b1bc..652da497 100644
--- a/custom_mutators/examples/post_library_png.so.c
+++ b/custom_mutators/examples/post_library_png.so.c
@@ -30,7 +30,7 @@
 #include <string.h>
 #include <zlib.h>
 #include <arpa/inet.h>
-#include "alloc-inl.h"
+#include "afl-fuzz.h"
 
 /* A macro to round an integer up to 4 kB. */
 
@@ -53,7 +53,7 @@ void *afl_custom_init(void *afl) {
 
   }
 
-  state->buf = calloc(sizeof(unsigned char), 4096);
+  state->buf = calloc(sizeof(unsigned char), MAX_FILE);
   if (!state->buf) {
 
     free(state);
@@ -80,21 +80,7 @@ size_t afl_custom_post_process(post_state_t *data, const unsigned char *in_buf,
 
   }
 
-  /* This is not a good way to do it, if you do not need to grow the buffer
-     then just work with in_buf instead for speed reasons.
-     But we want to show how to grow a buffer, so this is how it's done: */
-
-  unsigned int   pos = 8;
-  unsigned char *new_buf = afl_realloc(out_buf, UP4K(len));
-
-  if (!new_buf) {
-
-    *out_buf = in_buf;
-    return len;
-
-  }
-
-  memcpy(new_buf, in_buf, len);
+  unsigned int pos = 8;
 
   /* Minimum size of a zero-length PNG chunk is 12 bytes; if we
      don't have that, we can bail out. */
@@ -124,7 +110,7 @@ size_t afl_custom_post_process(post_state_t *data, const unsigned char *in_buf,
 
     if (real_cksum != file_cksum) {
 
-      *(uint32_t *)(new_buf + pos + 8 + chunk_len) = real_cksum;
+      *(uint32_t *)(data->buf + pos + 8 + chunk_len) = real_cksum;
 
     }
 
@@ -134,7 +120,7 @@ size_t afl_custom_post_process(post_state_t *data, const unsigned char *in_buf,
 
   }
 
-  *out_buf = new_buf;
+  *out_buf = data->buf;
   return len;
 
 }
diff --git a/custom_mutators/examples/simple_example.c b/custom_mutators/examples/simple_example.c
index d888ec1f..2c0abe29 100644
--- a/custom_mutators/examples/simple_example.c
+++ b/custom_mutators/examples/simple_example.c
@@ -1,6 +1,6 @@
 // This simple example just creates random buffer <= 100 filled with 'A'
 // needs -I /path/to/AFLplusplus/include
-#include "custom_mutator_helpers.h"
+#include "afl-fuzz.h"
 
 #include <stdint.h>
 #include <stdlib.h>
@@ -13,14 +13,14 @@
 
 typedef struct my_mutator {
 
-  afl_t *afl;
+  afl_state_t *afl;
 
   // Reused buffers:
-  BUF_VAR(u8, fuzz);
+  u8 *fuzz_buf;
 
 } my_mutator_t;
 
-my_mutator_t *afl_custom_init(afl_t *afl, unsigned int seed) {
+my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
 
   srand(seed);
   my_mutator_t *data = calloc(1, sizeof(my_mutator_t));
@@ -31,6 +31,14 @@ my_mutator_t *afl_custom_init(afl_t *afl, unsigned int seed) {
 
   }
 
+  data->fuzz_buf = (u8 *)malloc(MAX_FILE);
+  if (!data->fuzz_buf) {
+
+    perror("afl_custom_init malloc");
+    return NULL;
+
+  }
+
   data->afl = afl;
 
   return data;
@@ -44,18 +52,10 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
 
   int size = (rand() % 100) + 1;
   if (size > max_size) size = max_size;
-  u8 *mutated_out = maybe_grow(BUF_PARAMS(data, fuzz), size);
-  if (!mutated_out) {
-
-    *out_buf = NULL;
-    perror("custom mutator allocation (maybe_grow)");
-    return 0;            /* afl-fuzz will very likely error out after this. */
-
-  }
 
-  memset(mutated_out, _FIXED_CHAR, size);
+  memset(data->fuzz_buf, _FIXED_CHAR, size);
 
-  *out_buf = mutated_out;
+  *out_buf = data->fuzz_buf;
   return size;
 
 }
diff --git a/custom_mutators/honggfuzz/custom_mutator_helpers.h b/custom_mutators/honggfuzz/custom_mutator_helpers.h
deleted file mode 100644
index 57754697..00000000
--- a/custom_mutators/honggfuzz/custom_mutator_helpers.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef CUSTOM_MUTATOR_HELPERS
-#define CUSTOM_MUTATOR_HELPERS
-
-#include "config.h"
-#include "types.h"
-#include "afl-fuzz.h"
-#include <stdlib.h>
-
-#define INITIAL_GROWTH_SIZE (64)
-
-/* Use in a struct: creates a name_buf and a name_size variable. */
-#define BUF_VAR(type, name) \
-  type * name##_buf;        \
-  size_t name##_size;
-/* this filles in `&structptr->something_buf, &structptr->something_size`. */
-#define BUF_PARAMS(struct, name) \
-  (void **)&struct->name##_buf, &struct->name##_size
-
-#undef INITIAL_GROWTH_SIZE
-
-#endif
-
diff --git a/custom_mutators/honggfuzz/honggfuzz.c b/custom_mutators/honggfuzz/honggfuzz.c
index d7b3c9c5..0dd59aee 100644
--- a/custom_mutators/honggfuzz/honggfuzz.c
+++ b/custom_mutators/honggfuzz/honggfuzz.c
@@ -3,14 +3,14 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include "custom_mutator_helpers.h"
+#include "afl-fuzz.h"
 #include "mangle.h"
 
 #define NUMBER_OF_MUTATIONS 5
 
-uint8_t *         queue_input;
+uint8_t          *queue_input;
 size_t            queue_input_size;
-afl_state_t *     afl_struct;
+afl_state_t      *afl_struct;
 run_t             run;
 honggfuzz_t       global;
 struct _dynfile_t dynfile;
@@ -18,8 +18,8 @@ struct _dynfile_t dynfile;
 typedef struct my_mutator {
 
   afl_state_t *afl;
-  run_t *      run;
-  u8 *         mutator_buf;
+  run_t       *run;
+  u8          *mutator_buf;
   unsigned int seed;
   unsigned int extras_cnt, a_extras_cnt;
 
@@ -65,9 +65,9 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
 /* When a new queue entry is added we check if there are new dictionary
    entries to add to honggfuzz structure */
 
-uint8_t afl_custom_queue_new_entry(my_mutator_t * data,
-                                   const uint8_t *filename_new_queue,
-                                   const uint8_t *filename_orig_queue) {
+void afl_custom_queue_new_entry(my_mutator_t  *data,
+                                const uint8_t *filename_new_queue,
+                                const uint8_t *filename_orig_queue) {
 
   if (run.global->mutate.dictionaryCnt >= 1024) return;
 
@@ -97,7 +97,7 @@ uint8_t afl_custom_queue_new_entry(my_mutator_t * data,
 
   }
 
-  return 0;
+  return;
 
 }
 
diff --git a/custom_mutators/honggfuzz/mangle.c b/custom_mutators/honggfuzz/mangle.c
index 637d428d..7b7ccb91 100644
--- a/custom_mutators/honggfuzz/mangle.c
+++ b/custom_mutators/honggfuzz/mangle.c
@@ -39,11 +39,16 @@
 #include "libhfcommon/log.h"
 #include "libhfcommon/util.h"
 
-static inline size_t mangle_LenLeft(run_t* run, size_t off) {
-    if (off >= run->dynfile->size) {
-        LOG_F("Offset is too large: off:%zu >= len:%zu", off, run->dynfile->size);
-    }
-    return (run->dynfile->size - off - 1);
+static inline size_t mangle_LenLeft(run_t *run, size_t off) {
+
+  if (off >= run->dynfile->size) {
+
+    LOG_F("Offset is too large: off:%zu >= len:%zu", off, run->dynfile->size);
+
+  }
+
+  return (run->dynfile->size - off - 1);
+
 }
 
 /*
@@ -51,196 +56,233 @@ static inline size_t mangle_LenLeft(run_t* run, size_t off) {
  * Based on an idea by https://twitter.com/gamozolabs
  */
 static inline size_t mangle_getLen(size_t max) {
-    if (max > _HF_INPUT_MAX_SIZE) {
-        LOG_F("max (%zu) > _HF_INPUT_MAX_SIZE (%zu)", max, (size_t)_HF_INPUT_MAX_SIZE);
-    }
-    if (max == 0) {
-        LOG_F("max == 0");
-    }
-    if (max == 1) {
-        return 1;
-    }
 
-    /* Give 50% chance the the uniform distribution */
-    if (util_rnd64() & 1) {
-        return (size_t)util_rndGet(1, max);
-    }
+  if (max > _HF_INPUT_MAX_SIZE) {
+
+    LOG_F("max (%zu) > _HF_INPUT_MAX_SIZE (%zu)", max,
+          (size_t)_HF_INPUT_MAX_SIZE);
+
+  }
+
+  if (max == 0) { LOG_F("max == 0"); }
+  if (max == 1) { return 1; }
+
+  /* Give 50% chance the the uniform distribution */
+  if (util_rnd64() & 1) { return (size_t)util_rndGet(1, max); }
+
+  /* effectively exprand() */
+  return (size_t)util_rndGet(1, util_rndGet(1, max));
 
-    /* effectively exprand() */
-    return (size_t)util_rndGet(1, util_rndGet(1, max));
 }
 
 /* Prefer smaller values here, so use mangle_getLen() */
-static inline size_t mangle_getOffSet(run_t* run) {
-    return mangle_getLen(run->dynfile->size) - 1;
+static inline size_t mangle_getOffSet(run_t *run) {
+
+  return mangle_getLen(run->dynfile->size) - 1;
+
 }
 
 /* Offset which can be equal to the file size */
-static inline size_t mangle_getOffSetPlus1(run_t* run) {
-    size_t reqlen = HF_MIN(run->dynfile->size + 1, _HF_INPUT_MAX_SIZE);
-    return mangle_getLen(reqlen) - 1;
+static inline size_t mangle_getOffSetPlus1(run_t *run) {
+
+  size_t reqlen = HF_MIN(run->dynfile->size + 1, _HF_INPUT_MAX_SIZE);
+  return mangle_getLen(reqlen) - 1;
+
 }
 
-static inline void mangle_Move(run_t* run, size_t off_from, size_t off_to, size_t len) {
-    if (off_from >= run->dynfile->size) {
-        return;
-    }
-    if (off_to >= run->dynfile->size) {
-        return;
-    }
-    if (off_from == off_to) {
-        return;
-    }
+static inline void mangle_Move(run_t *run, size_t off_from, size_t off_to,
+                               size_t len) {
+
+  if (off_from >= run->dynfile->size) { return; }
+  if (off_to >= run->dynfile->size) { return; }
+  if (off_from == off_to) { return; }
 
-    size_t len_from = run->dynfile->size - off_from;
-    len             = HF_MIN(len, len_from);
+  size_t len_from = run->dynfile->size - off_from;
+  len = HF_MIN(len, len_from);
 
-    size_t len_to = run->dynfile->size - off_to;
-    len           = HF_MIN(len, len_to);
+  size_t len_to = run->dynfile->size - off_to;
+  len = HF_MIN(len, len_to);
+
+  memmove(&run->dynfile->data[off_to], &run->dynfile->data[off_from], len);
 
-    memmove(&run->dynfile->data[off_to], &run->dynfile->data[off_from], len);
 }
 
-static inline void mangle_Overwrite(
-    run_t* run, size_t off, const uint8_t* src, size_t len, bool printable) {
-    if (len == 0) {
-        return;
-    }
-    size_t maxToCopy = run->dynfile->size - off;
-    if (len > maxToCopy) {
-        len = maxToCopy;
-    }
+static inline void mangle_Overwrite(run_t *run, size_t off, const uint8_t *src,
+                                    size_t len, bool printable) {
+
+  if (len == 0) { return; }
+  size_t maxToCopy = run->dynfile->size - off;
+  if (len > maxToCopy) { len = maxToCopy; }
+
+  memmove(&run->dynfile->data[off], src, len);
+  if (printable) { util_turnToPrintable(&run->dynfile->data[off], len); }
 
-    memmove(&run->dynfile->data[off], src, len);
-    if (printable) {
-        util_turnToPrintable(&run->dynfile->data[off], len);
-    }
 }
 
-static inline size_t mangle_Inflate(run_t* run, size_t off, size_t len, bool printable) {
-    if (run->dynfile->size >= run->global->mutate.maxInputSz) {
-        return 0;
-    }
-    if (len > (run->global->mutate.maxInputSz - run->dynfile->size)) {
-        len = run->global->mutate.maxInputSz - run->dynfile->size;
-    }
+static inline size_t mangle_Inflate(run_t *run, size_t off, size_t len,
+                                    bool printable) {
 
-    input_setSize(run, run->dynfile->size + len);
-    mangle_Move(run, off, off + len, run->dynfile->size);
-    if (printable) {
-        memset(&run->dynfile->data[off], ' ', len);
-    }
+  if (run->dynfile->size >= run->global->mutate.maxInputSz) { return 0; }
+  if (len > (run->global->mutate.maxInputSz - run->dynfile->size)) {
+
+    len = run->global->mutate.maxInputSz - run->dynfile->size;
+
+  }
+
+  input_setSize(run, run->dynfile->size + len);
+  mangle_Move(run, off, off + len, run->dynfile->size);
+  if (printable) { memset(&run->dynfile->data[off], ' ', len); }
+
+  return len;
 
-    return len;
 }
 
-static inline void mangle_Insert(
-    run_t* run, size_t off, const uint8_t* val, size_t len, bool printable) {
-    len = mangle_Inflate(run, off, len, printable);
-    mangle_Overwrite(run, off, val, len, printable);
+static inline void mangle_Insert(run_t *run, size_t off, const uint8_t *val,
+                                 size_t len, bool printable) {
+
+  len = mangle_Inflate(run, off, len, printable);
+  mangle_Overwrite(run, off, val, len, printable);
+
 }
 
-static inline void mangle_UseValue(run_t* run, const uint8_t* val, size_t len, bool printable) {
-    if (util_rnd64() & 1) {
-        mangle_Overwrite(run, mangle_getOffSet(run), val, len, printable);
-    } else {
-        mangle_Insert(run, mangle_getOffSetPlus1(run), val, len, printable);
-    }
+static inline void mangle_UseValue(run_t *run, const uint8_t *val, size_t len,
+                                   bool printable) {
+
+  if (util_rnd64() & 1) {
+
+    mangle_Overwrite(run, mangle_getOffSet(run), val, len, printable);
+
+  } else {
+
+    mangle_Insert(run, mangle_getOffSetPlus1(run), val, len, printable);
+
+  }
+
 }
 
-static inline void mangle_UseValueAt(
-    run_t* run, size_t off, const uint8_t* val, size_t len, bool printable) {
-    if (util_rnd64() & 1) {
-        mangle_Overwrite(run, off, val, len, printable);
-    } else {
-        mangle_Insert(run, off, val, len, printable);
-    }
+static inline void mangle_UseValueAt(run_t *run, size_t off, const uint8_t *val,
+                                     size_t len, bool printable) {
+
+  if (util_rnd64() & 1) {
+
+    mangle_Overwrite(run, off, val, len, printable);
+
+  } else {
+
+    mangle_Insert(run, off, val, len, printable);
+
+  }
+
 }
 
-static void mangle_MemSwap(run_t* run, bool printable HF_ATTR_UNUSED) {
-    /* No big deal if those two are overlapping */
-    size_t off1    = mangle_getOffSet(run);
-    size_t maxlen1 = run->dynfile->size - off1;
-    size_t off2    = mangle_getOffSet(run);
-    size_t maxlen2 = run->dynfile->size - off2;
-    size_t len     = mangle_getLen(HF_MIN(maxlen1, maxlen2));
+static void mangle_MemSwap(run_t *run, bool printable HF_ATTR_UNUSED) {
 
-    if (off1 == off2) {
-        return;
-    }
+  /* No big deal if those two are overlapping */
+  size_t off1 = mangle_getOffSet(run);
+  size_t maxlen1 = run->dynfile->size - off1;
+  size_t off2 = mangle_getOffSet(run);
+  size_t maxlen2 = run->dynfile->size - off2;
+  size_t len = mangle_getLen(HF_MIN(maxlen1, maxlen2));
+
+  if (off1 == off2) { return; }
+
+  for (size_t i = 0; i < (len / 2); i++) {
+
+    /*
+     * First - from the head, next from the tail. Don't worry about layout of
+     * the overlapping part - there's no good solution to that, and it can be
+     * left somewhat scrambled, while still preserving the entropy
+     */
+    const uint8_t tmp1 = run->dynfile->data[off2 + i];
+    run->dynfile->data[off2 + i] = run->dynfile->data[off1 + i];
+    run->dynfile->data[off1 + i] = tmp1;
+    const uint8_t tmp2 = run->dynfile->data[off2 + (len - 1) - i];
+    run->dynfile->data[off2 + (len - 1) - i] =
+        run->dynfile->data[off1 + (len - 1) - i];
+    run->dynfile->data[off1 + (len - 1) - i] = tmp2;
+
+  }
 
-    for (size_t i = 0; i < (len / 2); i++) {
-        /*
-         * First - from the head, next from the tail. Don't worry about layout of the overlapping
-         * part - there's no good solution to that, and it can be left somewhat scrambled,
-         * while still preserving the entropy
-         */
-        const uint8_t tmp1                       = run->dynfile->data[off2 + i];
-        run->dynfile->data[off2 + i]             = run->dynfile->data[off1 + i];
-        run->dynfile->data[off1 + i]             = tmp1;
-        const uint8_t tmp2                       = run->dynfile->data[off2 + (len - 1) - i];
-        run->dynfile->data[off2 + (len - 1) - i] = run->dynfile->data[off1 + (len - 1) - i];
-        run->dynfile->data[off1 + (len - 1) - i] = tmp2;
-    }
 }
 
-static void mangle_MemCopy(run_t* run, bool printable HF_ATTR_UNUSED) {
-    size_t off = mangle_getOffSet(run);
-    size_t len = mangle_getLen(run->dynfile->size - off);
+static void mangle_MemCopy(run_t *run, bool printable HF_ATTR_UNUSED) {
+
+  size_t off = mangle_getOffSet(run);
+  size_t len = mangle_getLen(run->dynfile->size - off);
 
-    /* Use a temp buf, as Insert/Inflate can change source bytes */
-    uint8_t* tmpbuf = (uint8_t*)util_Malloc(len);
-    defer {
-        free(tmpbuf);
-    };
-    memmove(tmpbuf, &run->dynfile->data[off], len);
+  /* Use a temp buf, as Insert/Inflate can change source bytes */
+  uint8_t *tmpbuf = (uint8_t *)util_Malloc(len);
+  defer {
+
+    free(tmpbuf);
+
+  };
+
+  memmove(tmpbuf, &run->dynfile->data[off], len);
+
+  mangle_UseValue(run, tmpbuf, len, printable);
 
-    mangle_UseValue(run, tmpbuf, len, printable);
 }
 
-static void mangle_Bytes(run_t* run, bool printable) {
-    uint16_t buf;
-    if (printable) {
-        util_rndBufPrintable((uint8_t*)&buf, sizeof(buf));
-    } else {
-        buf = util_rnd64();
-    }
+static void mangle_Bytes(run_t *run, bool printable) {
+
+  uint16_t buf;
+  if (printable) {
+
+    util_rndBufPrintable((uint8_t *)&buf, sizeof(buf));
+
+  } else {
+
+    buf = util_rnd64();
+
+  }
+
+  /* Overwrite with random 1-2-byte values */
+  size_t toCopy = util_rndGet(1, 2);
+  mangle_UseValue(run, (const uint8_t *)&buf, toCopy, printable);
 
-    /* Overwrite with random 1-2-byte values */
-    size_t toCopy = util_rndGet(1, 2);
-    mangle_UseValue(run, (const uint8_t*)&buf, toCopy, printable);
 }
 
-static void mangle_ByteRepeat(run_t* run, bool printable) {
-    size_t off     = mangle_getOffSet(run);
-    size_t destOff = off + 1;
-    size_t maxSz   = run->dynfile->size - destOff;
+static void mangle_ByteRepeat(run_t *run, bool printable) {
 
-    /* No space to repeat */
-    if (!maxSz) {
-        mangle_Bytes(run, printable);
-        return;
-    }
+  size_t off = mangle_getOffSet(run);
+  size_t destOff = off + 1;
+  size_t maxSz = run->dynfile->size - destOff;
+
+  /* No space to repeat */
+  if (!maxSz) {
+
+    mangle_Bytes(run, printable);
+    return;
+
+  }
+
+  size_t len = mangle_getLen(maxSz);
+  if (util_rnd64() & 0x1) {
+
+    len = mangle_Inflate(run, destOff, len, printable);
+
+  }
+
+  memset(&run->dynfile->data[destOff], run->dynfile->data[off], len);
 
-    size_t len = mangle_getLen(maxSz);
-    if (util_rnd64() & 0x1) {
-        len = mangle_Inflate(run, destOff, len, printable);
-    }
-    memset(&run->dynfile->data[destOff], run->dynfile->data[off], len);
 }
 
-static void mangle_Bit(run_t* run, bool printable) {
-    size_t off = mangle_getOffSet(run);
-    run->dynfile->data[off] ^= (uint8_t)(1U << util_rndGet(0, 7));
-    if (printable) {
-        util_turnToPrintable(&(run->dynfile->data[off]), 1);
-    }
+static void mangle_Bit(run_t *run, bool printable) {
+
+  size_t off = mangle_getOffSet(run);
+  run->dynfile->data[off] ^= (uint8_t)(1U << util_rndGet(0, 7));
+  if (printable) { util_turnToPrintable(&(run->dynfile->data[off]), 1); }
+
 }
 
 static const struct {
-    const uint8_t val[8];
-    const size_t  size;
+
+  const uint8_t val[8];
+  const size_t  size;
+
 } mangleMagicVals[] = {
+
     /* 1B - No endianness */
     {"\x00\x00\x00\x00\x00\x00\x00\x00", 1},
     {"\x01\x00\x00\x00\x00\x00\x00\x00", 1},
@@ -472,436 +514,543 @@ static const struct {
     {"\x00\x00\x00\x00\x00\x00\x00\x80", 8},
     {"\x01\x00\x00\x00\x00\x00\x00\x80", 8},
     {"\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8},
+
 };
 
-static void mangle_Magic(run_t* run, bool printable) {
-    uint64_t choice = util_rndGet(0, ARRAYSIZE(mangleMagicVals) - 1);
-    mangle_UseValue(run, mangleMagicVals[choice].val, mangleMagicVals[choice].size, printable);
+static void mangle_Magic(run_t *run, bool printable) {
+
+  uint64_t choice = util_rndGet(0, ARRAYSIZE(mangleMagicVals) - 1);
+  mangle_UseValue(run, mangleMagicVals[choice].val,
+                  mangleMagicVals[choice].size, printable);
+
 }
 
-static void mangle_StaticDict(run_t* run, bool printable) {
-    if (run->global->mutate.dictionaryCnt == 0) {
-        mangle_Bytes(run, printable);
-        return;
-    }
-    uint64_t choice = util_rndGet(0, run->global->mutate.dictionaryCnt - 1);
-    mangle_UseValue(run, run->global->mutate.dictionary[choice].val,
-        run->global->mutate.dictionary[choice].len, printable);
+static void mangle_StaticDict(run_t *run, bool printable) {
+
+  if (run->global->mutate.dictionaryCnt == 0) {
+
+    mangle_Bytes(run, printable);
+    return;
+
+  }
+
+  uint64_t choice = util_rndGet(0, run->global->mutate.dictionaryCnt - 1);
+  mangle_UseValue(run, run->global->mutate.dictionary[choice].val,
+                  run->global->mutate.dictionary[choice].len, printable);
+
 }
 
-static inline const uint8_t* mangle_FeedbackDict(run_t* run, size_t* len) {
-    if (!run->global->feedback.cmpFeedback) {
-        return NULL;
-    }
-    cmpfeedback_t* cmpf = run->global->feedback.cmpFeedbackMap;
-    uint32_t       cnt  = ATOMIC_GET(cmpf->cnt);
-    if (cnt == 0) {
-        return NULL;
-    }
-    if (cnt > ARRAYSIZE(cmpf->valArr)) {
-        cnt = ARRAYSIZE(cmpf->valArr);
-    }
-    uint32_t choice = util_rndGet(0, cnt - 1);
-    *len            = (size_t)ATOMIC_GET(cmpf->valArr[choice].len);
-    if (*len == 0) {
-        return NULL;
-    }
-    return cmpf->valArr[choice].val;
+static inline const uint8_t *mangle_FeedbackDict(run_t *run, size_t *len) {
+
+  if (!run->global->feedback.cmpFeedback) { return NULL; }
+  cmpfeedback_t *cmpf = run->global->feedback.cmpFeedbackMap;
+  uint32_t       cnt = ATOMIC_GET(cmpf->cnt);
+  if (cnt == 0) { return NULL; }
+  if (cnt > ARRAYSIZE(cmpf->valArr)) { cnt = ARRAYSIZE(cmpf->valArr); }
+  uint32_t choice = util_rndGet(0, cnt - 1);
+  *len = (size_t)ATOMIC_GET(cmpf->valArr[choice].len);
+  if (*len == 0) { return NULL; }
+  return cmpf->valArr[choice].val;
+
 }
 
-static void mangle_ConstFeedbackDict(run_t* run, bool printable) {
-    size_t         len;
-    const uint8_t* val = mangle_FeedbackDict(run, &len);
-    if (val == NULL) {
-        mangle_Bytes(run, printable);
-        return;
-    }
-    mangle_UseValue(run, val, len, printable);
+static void mangle_ConstFeedbackDict(run_t *run, bool printable) {
+
+  size_t         len;
+  const uint8_t *val = mangle_FeedbackDict(run, &len);
+  if (val == NULL) {
+
+    mangle_Bytes(run, printable);
+    return;
+
+  }
+
+  mangle_UseValue(run, val, len, printable);
+
 }
 
-static void mangle_MemSet(run_t* run, bool printable) {
-    size_t off = mangle_getOffSet(run);
-    size_t len = mangle_getLen(run->dynfile->size - off);
-    int    val = printable ? (int)util_rndPrintable() : (int)util_rndGet(0, UINT8_MAX);
+static void mangle_MemSet(run_t *run, bool printable) {
 
-    if (util_rnd64() & 1) {
-        len = mangle_Inflate(run, off, len, printable);
-    }
+  size_t off = mangle_getOffSet(run);
+  size_t len = mangle_getLen(run->dynfile->size - off);
+  int    val =
+      printable ? (int)util_rndPrintable() : (int)util_rndGet(0, UINT8_MAX);
+
+  if (util_rnd64() & 1) { len = mangle_Inflate(run, off, len, printable); }
+
+  memset(&run->dynfile->data[off], val, len);
 
-    memset(&run->dynfile->data[off], val, len);
 }
 
-static void mangle_MemClr(run_t* run, bool printable) {
-    size_t off = mangle_getOffSet(run);
-    size_t len = mangle_getLen(run->dynfile->size - off);
-    int    val = printable ? ' ' : 0;
+static void mangle_MemClr(run_t *run, bool printable) {
 
-    if (util_rnd64() & 1) {
-        len = mangle_Inflate(run, off, len, printable);
-    }
+  size_t off = mangle_getOffSet(run);
+  size_t len = mangle_getLen(run->dynfile->size - off);
+  int    val = printable ? ' ' : 0;
+
+  if (util_rnd64() & 1) { len = mangle_Inflate(run, off, len, printable); }
+
+  memset(&run->dynfile->data[off], val, len);
 
-    memset(&run->dynfile->data[off], val, len);
 }
 
-static void mangle_RandomBuf(run_t* run, bool printable) {
-    size_t off = mangle_getOffSet(run);
-    size_t len = mangle_getLen(run->dynfile->size - off);
+static void mangle_RandomBuf(run_t *run, bool printable) {
+
+  size_t off = mangle_getOffSet(run);
+  size_t len = mangle_getLen(run->dynfile->size - off);
+
+  if (util_rnd64() & 1) { len = mangle_Inflate(run, off, len, printable); }
+
+  if (printable) {
+
+    util_rndBufPrintable(&run->dynfile->data[off], len);
+
+  } else {
+
+    util_rndBuf(&run->dynfile->data[off], len);
+
+  }
+
+}
+
+static inline void mangle_AddSubWithRange(run_t *run, size_t off, size_t varLen,
+                                          uint64_t range, bool printable) {
+
+  int64_t delta = (int64_t)util_rndGet(0, range * 2) - (int64_t)range;
+
+  switch (varLen) {
+
+    case 1: {
+
+      run->dynfile->data[off] += delta;
+      break;
 
-    if (util_rnd64() & 1) {
-        len = mangle_Inflate(run, off, len, printable);
     }
 
-    if (printable) {
-        util_rndBufPrintable(&run->dynfile->data[off], len);
-    } else {
-        util_rndBuf(&run->dynfile->data[off], len);
+    case 2: {
+
+      int16_t val;
+      memcpy(&val, &run->dynfile->data[off], sizeof(val));
+      if (util_rnd64() & 0x1) {
+
+        val += delta;
+
+      } else {
+
+        /* Foreign endianess */
+        val = __builtin_bswap16(val);
+        val += delta;
+        val = __builtin_bswap16(val);
+
+      }
+
+      mangle_Overwrite(run, off, (uint8_t *)&val, varLen, printable);
+      break;
+
     }
-}
 
-static inline void mangle_AddSubWithRange(
-    run_t* run, size_t off, size_t varLen, uint64_t range, bool printable) {
-    int64_t delta = (int64_t)util_rndGet(0, range * 2) - (int64_t)range;
-
-    switch (varLen) {
-        case 1: {
-            run->dynfile->data[off] += delta;
-            break;
-        }
-        case 2: {
-            int16_t val;
-            memcpy(&val, &run->dynfile->data[off], sizeof(val));
-            if (util_rnd64() & 0x1) {
-                val += delta;
-            } else {
-                /* Foreign endianess */
-                val = __builtin_bswap16(val);
-                val += delta;
-                val = __builtin_bswap16(val);
-            }
-            mangle_Overwrite(run, off, (uint8_t*)&val, varLen, printable);
-            break;
-        }
-        case 4: {
-            int32_t val;
-            memcpy(&val, &run->dynfile->data[off], sizeof(val));
-            if (util_rnd64() & 0x1) {
-                val += delta;
-            } else {
-                /* Foreign endianess */
-                val = __builtin_bswap32(val);
-                val += delta;
-                val = __builtin_bswap32(val);
-            }
-            mangle_Overwrite(run, off, (uint8_t*)&val, varLen, printable);
-            break;
-        }
-        case 8: {
-            int64_t val;
-            memcpy(&val, &run->dynfile->data[off], sizeof(val));
-            if (util_rnd64() & 0x1) {
-                val += delta;
-            } else {
-                /* Foreign endianess */
-                val = __builtin_bswap64(val);
-                val += delta;
-                val = __builtin_bswap64(val);
-            }
-            mangle_Overwrite(run, off, (uint8_t*)&val, varLen, printable);
-            break;
-        }
-        default: {
-            LOG_F("Unknown variable length size: %zu", varLen);
-        }
+    case 4: {
+
+      int32_t val;
+      memcpy(&val, &run->dynfile->data[off], sizeof(val));
+      if (util_rnd64() & 0x1) {
+
+        val += delta;
+
+      } else {
+
+        /* Foreign endianess */
+        val = __builtin_bswap32(val);
+        val += delta;
+        val = __builtin_bswap32(val);
+
+      }
+
+      mangle_Overwrite(run, off, (uint8_t *)&val, varLen, printable);
+      break;
+
     }
-}
 
-static void mangle_AddSub(run_t* run, bool printable) {
-    size_t off = mangle_getOffSet(run);
+    case 8: {
+
+      int64_t val;
+      memcpy(&val, &run->dynfile->data[off], sizeof(val));
+      if (util_rnd64() & 0x1) {
+
+        val += delta;
+
+      } else {
+
+        /* Foreign endianess */
+        val = __builtin_bswap64(val);
+        val += delta;
+        val = __builtin_bswap64(val);
+
+      }
+
+      mangle_Overwrite(run, off, (uint8_t *)&val, varLen, printable);
+      break;
 
-    /* 1,2,4,8 */
-    size_t varLen = 1U << util_rndGet(0, 3);
-    if ((run->dynfile->size - off) < varLen) {
-        varLen = 1;
     }
 
-    uint64_t range;
-    switch (varLen) {
-        case 1:
-            range = 16;
-            break;
-        case 2:
-            range = 4096;
-            break;
-        case 4:
-            range = 1048576;
-            break;
-        case 8:
-            range = 268435456;
-            break;
-        default:
-            LOG_F("Invalid operand size: %zu", varLen);
+    default: {
+
+      LOG_F("Unknown variable length size: %zu", varLen);
+
     }
 
-    mangle_AddSubWithRange(run, off, varLen, range, printable);
+  }
+
 }
 
-static void mangle_IncByte(run_t* run, bool printable) {
-    size_t off = mangle_getOffSet(run);
-    if (printable) {
-        run->dynfile->data[off] = (run->dynfile->data[off] - 32 + 1) % 95 + 32;
-    } else {
-        run->dynfile->data[off] += (uint8_t)1UL;
-    }
+static void mangle_AddSub(run_t *run, bool printable) {
+
+  size_t off = mangle_getOffSet(run);
+
+  /* 1,2,4,8 */
+  size_t varLen = 1U << util_rndGet(0, 3);
+  if ((run->dynfile->size - off) < varLen) { varLen = 1; }
+
+  uint64_t range;
+  switch (varLen) {
+
+    case 1:
+      range = 16;
+      break;
+    case 2:
+      range = 4096;
+      break;
+    case 4:
+      range = 1048576;
+      break;
+    case 8:
+      range = 268435456;
+      break;
+    default:
+      LOG_F("Invalid operand size: %zu", varLen);
+
+  }
+
+  mangle_AddSubWithRange(run, off, varLen, range, printable);
+
 }
 
-static void mangle_DecByte(run_t* run, bool printable) {
-    size_t off = mangle_getOffSet(run);
-    if (printable) {
-        run->dynfile->data[off] = (run->dynfile->data[off] - 32 + 94) % 95 + 32;
-    } else {
-        run->dynfile->data[off] -= (uint8_t)1UL;
-    }
+static void mangle_IncByte(run_t *run, bool printable) {
+
+  size_t off = mangle_getOffSet(run);
+  if (printable) {
+
+    run->dynfile->data[off] = (run->dynfile->data[off] - 32 + 1) % 95 + 32;
+
+  } else {
+
+    run->dynfile->data[off] += (uint8_t)1UL;
+
+  }
+
 }
 
-static void mangle_NegByte(run_t* run, bool printable) {
-    size_t off = mangle_getOffSet(run);
-    if (printable) {
-        run->dynfile->data[off] = 94 - (run->dynfile->data[off] - 32) + 32;
-    } else {
-        run->dynfile->data[off] = ~(run->dynfile->data[off]);
-    }
+static void mangle_DecByte(run_t *run, bool printable) {
+
+  size_t off = mangle_getOffSet(run);
+  if (printable) {
+
+    run->dynfile->data[off] = (run->dynfile->data[off] - 32 + 94) % 95 + 32;
+
+  } else {
+
+    run->dynfile->data[off] -= (uint8_t)1UL;
+
+  }
+
 }
 
-static void mangle_Expand(run_t* run, bool printable) {
-    size_t off = mangle_getOffSet(run);
-    size_t len;
-    if (util_rnd64() % 16) {
-        len = mangle_getLen(HF_MIN(16, run->global->mutate.maxInputSz - off));
-    } else {
-        len = mangle_getLen(run->global->mutate.maxInputSz - off);
-    }
+static void mangle_NegByte(run_t *run, bool printable) {
+
+  size_t off = mangle_getOffSet(run);
+  if (printable) {
+
+    run->dynfile->data[off] = 94 - (run->dynfile->data[off] - 32) + 32;
+
+  } else {
+
+    run->dynfile->data[off] = ~(run->dynfile->data[off]);
+
+  }
 
-    mangle_Inflate(run, off, len, printable);
 }
 
-static void mangle_Shrink(run_t* run, bool printable HF_ATTR_UNUSED) {
-    if (run->dynfile->size <= 2U) {
-        return;
-    }
+static void mangle_Expand(run_t *run, bool printable) {
 
-    size_t off_start = mangle_getOffSet(run);
-    size_t len       = mangle_LenLeft(run, off_start);
-    if (len == 0) {
-        return;
-    }
-    if (util_rnd64() % 16) {
-        len = mangle_getLen(HF_MIN(16, len));
-    } else {
-        len = mangle_getLen(len);
-    }
-    size_t off_end     = off_start + len;
-    size_t len_to_move = run->dynfile->size - off_end;
+  size_t off = mangle_getOffSet(run);
+  size_t len;
+  if (util_rnd64() % 16) {
+
+    len = mangle_getLen(HF_MIN(16, run->global->mutate.maxInputSz - off));
+
+  } else {
+
+    len = mangle_getLen(run->global->mutate.maxInputSz - off);
+
+  }
+
+  mangle_Inflate(run, off, len, printable);
 
-    mangle_Move(run, off_end, off_start, len_to_move);
-    input_setSize(run, run->dynfile->size - len);
 }
-static void mangle_ASCIINum(run_t* run, bool printable) {
-    size_t len = util_rndGet(2, 8);
 
-    char buf[20];
-    snprintf(buf, sizeof(buf), "%-19" PRId64, (int64_t)util_rnd64());
+static void mangle_Shrink(run_t *run, bool printable HF_ATTR_UNUSED) {
+
+  if (run->dynfile->size <= 2U) { return; }
+
+  size_t off_start = mangle_getOffSet(run);
+  size_t len = mangle_LenLeft(run, off_start);
+  if (len == 0) { return; }
+  if (util_rnd64() % 16) {
+
+    len = mangle_getLen(HF_MIN(16, len));
+
+  } else {
+
+    len = mangle_getLen(len);
+
+  }
+
+  size_t off_end = off_start + len;
+  size_t len_to_move = run->dynfile->size - off_end;
+
+  mangle_Move(run, off_end, off_start, len_to_move);
+  input_setSize(run, run->dynfile->size - len);
 
-    mangle_UseValue(run, (const uint8_t*)buf, len, printable);
 }
 
-static void mangle_ASCIINumChange(run_t* run, bool printable) {
-    size_t off = mangle_getOffSet(run);
+static void mangle_ASCIINum(run_t *run, bool printable) {
 
-    /* Find a digit */
-    for (; off < run->dynfile->size; off++) {
-        if (isdigit(run->dynfile->data[off])) {
-            break;
-        }
-    }
-    size_t left = run->dynfile->size - off;
-    if (left == 0) {
-        return;
-    }
+  size_t len = util_rndGet(2, 8);
 
-    size_t   len = 0;
-    uint64_t val = 0;
-    /* 20 is maximum lenght of a string representing a 64-bit unsigned value */
-    for (len = 0; (len < 20) && (len < left); len++) {
-        char c = run->dynfile->data[off + len];
-        if (!isdigit(c)) {
-            break;
-        }
-        val *= 10;
-        val += (c - '0');
-    }
+  char buf[20];
+  snprintf(buf, sizeof(buf), "%-19" PRId64, (int64_t)util_rnd64());
 
-    switch (util_rndGet(0, 7)) {
-        case 0:
-            val++;
-            break;
-        case 1:
-            val--;
-            break;
-        case 2:
-            val *= 2;
-            break;
-        case 3:
-            val /= 2;
-            break;
-        case 4:
-            val = util_rnd64();
-            break;
-        case 5:
-            val += util_rndGet(1, 256);
-            break;
-        case 6:
-            val -= util_rndGet(1, 256);
-            break;
-        case 7:
-            val = ~(val);
-            break;
-        default:
-            LOG_F("Invalid choice");
-    };
-
-    char buf[20];
-    snprintf(buf, sizeof(buf), "%-19" PRIu64, val);
-
-    mangle_UseValueAt(run, off, (const uint8_t*)buf, len, printable);
-}
-
-static void mangle_Splice(run_t* run, bool printable) {
-    if (run->global->feedback.dynFileMethod == _HF_DYNFILE_NONE) {
-        mangle_Bytes(run, printable);
-        return;
-    }
+  mangle_UseValue(run, (const uint8_t *)buf, len, printable);
 
-    size_t         sz  = 0;
-    const uint8_t* buf = input_getRandomInputAsBuf(run, &sz);
-    if (!buf) {
-        LOG_E("input_getRandomInputAsBuf() returned no input");
-        mangle_Bytes(run, printable);
-        return;
-    }
-    if (!sz) {
-        mangle_Bytes(run, printable);
-        return;
-    }
+}
 
-    size_t remoteOff = mangle_getLen(sz) - 1;
-    size_t len       = mangle_getLen(sz - remoteOff);
-    mangle_UseValue(run, &buf[remoteOff], len, printable);
-}
-
-static void mangle_Resize(run_t* run, bool printable) {
-    ssize_t oldsz = run->dynfile->size;
-    ssize_t newsz = 0;
-
-    uint64_t choice = util_rndGet(0, 32);
-    switch (choice) {
-        case 0: /* Set new size arbitrarily */
-            newsz = (ssize_t)util_rndGet(1, run->global->mutate.maxInputSz);
-            break;
-        case 1 ... 4: /* Increase size by a small value */
-            newsz = oldsz + (ssize_t)util_rndGet(0, 8);
-            break;
-        case 5: /* Increase size by a larger value */
-            newsz = oldsz + (ssize_t)util_rndGet(9, 128);
-            break;
-        case 6 ... 9: /* Decrease size by a small value */
-            newsz = oldsz - (ssize_t)util_rndGet(0, 8);
-            break;
-        case 10: /* Decrease size by a larger value */
-            newsz = oldsz - (ssize_t)util_rndGet(9, 128);
-            break;
-        case 11 ... 32: /* Do nothing */
-            newsz = oldsz;
-            break;
-        default:
-            LOG_F("Illegal value from util_rndGet: %" PRIu64, choice);
-            break;
-    }
-    if (newsz < 1) {
-        newsz = 1;
-    }
-    if (newsz > (ssize_t)run->global->mutate.maxInputSz) {
-        newsz = run->global->mutate.maxInputSz;
-    }
+static void mangle_ASCIINumChange(run_t *run, bool printable) {
+
+  size_t off = mangle_getOffSet(run);
+
+  /* Find a digit */
+  for (; off < run->dynfile->size; off++) {
+
+    if (isdigit(run->dynfile->data[off])) { break; }
+
+  }
+
+  size_t left = run->dynfile->size - off;
+  if (left == 0) { return; }
+
+  size_t   len = 0;
+  uint64_t val = 0;
+  /* 20 is maximum lenght of a string representing a 64-bit unsigned value */
+  for (len = 0; (len < 20) && (len < left); len++) {
+
+    char c = run->dynfile->data[off + len];
+    if (!isdigit(c)) { break; }
+    val *= 10;
+    val += (c - '0');
+
+  }
+
+  switch (util_rndGet(0, 7)) {
+
+    case 0:
+      val++;
+      break;
+    case 1:
+      val--;
+      break;
+    case 2:
+      val *= 2;
+      break;
+    case 3:
+      val /= 2;
+      break;
+    case 4:
+      val = util_rnd64();
+      break;
+    case 5:
+      val += util_rndGet(1, 256);
+      break;
+    case 6:
+      val -= util_rndGet(1, 256);
+      break;
+    case 7:
+      val = ~(val);
+      break;
+    default:
+      LOG_F("Invalid choice");
+
+  };
+
+  char buf[20];
+  snprintf(buf, sizeof(buf), "%-19" PRIu64, val);
+
+  mangle_UseValueAt(run, off, (const uint8_t *)buf, len, printable);
 
-    input_setSize(run, (size_t)newsz);
-    if (newsz > oldsz) {
-        if (printable) {
-            memset(&run->dynfile->data[oldsz], ' ', newsz - oldsz);
-        }
-    }
 }
 
-void mangle_mangleContent(run_t* run, int speed_factor) {
-    static void (*const mangleFuncs[])(run_t * run, bool printable) = {
-        mangle_Shrink,
-        mangle_Expand,
-        mangle_Bit,
-        mangle_IncByte,
-        mangle_DecByte,
-        mangle_NegByte,
-        mangle_AddSub,
-        mangle_MemSet,
-        mangle_MemClr,
-        mangle_MemSwap,
-        mangle_MemCopy,
-        mangle_Bytes,
-        mangle_ASCIINum,
-        mangle_ASCIINumChange,
-        mangle_ByteRepeat,
-        mangle_Magic,
-        mangle_StaticDict,
-        mangle_ConstFeedbackDict,
-        mangle_RandomBuf,
-        mangle_Splice,
-    };
-
-    if (run->mutationsPerRun == 0U) {
-        return;
-    }
-    if (run->dynfile->size == 0U) {
-        mangle_Resize(run, /* printable= */ run->global->cfg.only_printable);
+static void mangle_Splice(run_t *run, bool printable) {
+
+  if (run->global->feedback.dynFileMethod == _HF_DYNFILE_NONE) {
+
+    mangle_Bytes(run, printable);
+    return;
+
+  }
+
+  size_t         sz = 0;
+  const uint8_t *buf = input_getRandomInputAsBuf(run, &sz);
+  if (!buf) {
+
+    LOG_E("input_getRandomInputAsBuf() returned no input");
+    mangle_Bytes(run, printable);
+    return;
+
+  }
+
+  if (!sz) {
+
+    mangle_Bytes(run, printable);
+    return;
+
+  }
+
+  size_t remoteOff = mangle_getLen(sz) - 1;
+  size_t len = mangle_getLen(sz - remoteOff);
+  mangle_UseValue(run, &buf[remoteOff], len, printable);
+
+}
+
+static void mangle_Resize(run_t *run, bool printable) {
+
+  ssize_t oldsz = run->dynfile->size;
+  ssize_t newsz = 0;
+
+  uint64_t choice = util_rndGet(0, 32);
+  switch (choice) {
+
+    case 0:                                     /* Set new size arbitrarily */
+      newsz = (ssize_t)util_rndGet(1, run->global->mutate.maxInputSz);
+      break;
+    case 1 ... 4:                         /* Increase size by a small value */
+      newsz = oldsz + (ssize_t)util_rndGet(0, 8);
+      break;
+    case 5:                              /* Increase size by a larger value */
+      newsz = oldsz + (ssize_t)util_rndGet(9, 128);
+      break;
+    case 6 ... 9:                         /* Decrease size by a small value */
+      newsz = oldsz - (ssize_t)util_rndGet(0, 8);
+      break;
+    case 10:                             /* Decrease size by a larger value */
+      newsz = oldsz - (ssize_t)util_rndGet(9, 128);
+      break;
+    case 11 ... 32:                                           /* Do nothing */
+      newsz = oldsz;
+      break;
+    default:
+      LOG_F("Illegal value from util_rndGet: %" PRIu64, choice);
+      break;
+
+  }
+
+  if (newsz < 1) { newsz = 1; }
+  if (newsz > (ssize_t)run->global->mutate.maxInputSz) {
+
+    newsz = run->global->mutate.maxInputSz;
+
+  }
+
+  input_setSize(run, (size_t)newsz);
+  if (newsz > oldsz) {
+
+    if (printable) { memset(&run->dynfile->data[oldsz], ' ', newsz - oldsz); }
+
+  }
+
+}
+
+void mangle_mangleContent(run_t *run, int speed_factor) {
+
+  static void (*const mangleFuncs[])(run_t * run, bool printable) = {
+
+      mangle_Shrink,    mangle_Expand,         mangle_Bit,
+      mangle_IncByte,   mangle_DecByte,        mangle_NegByte,
+      mangle_AddSub,    mangle_MemSet,         mangle_MemClr,
+      mangle_MemSwap,   mangle_MemCopy,        mangle_Bytes,
+      mangle_ASCIINum,  mangle_ASCIINumChange, mangle_ByteRepeat,
+      mangle_Magic,     mangle_StaticDict,     mangle_ConstFeedbackDict,
+      mangle_RandomBuf, mangle_Splice,
+
+  };
+
+  if (run->mutationsPerRun == 0U) { return; }
+  if (run->dynfile->size == 0U) {
+
+    mangle_Resize(run, /* printable= */ run->global->cfg.only_printable);
+
+  }
+
+  uint64_t changesCnt = run->global->mutate.mutationsPerRun;
+
+  if (speed_factor < 5) {
+
+    changesCnt = util_rndGet(1, run->global->mutate.mutationsPerRun);
+
+  } else if (speed_factor < 10) {
+
+    changesCnt = run->global->mutate.mutationsPerRun;
+
+  } else {
+
+    changesCnt = HF_MIN(speed_factor, 10);
+    changesCnt = HF_MAX(changesCnt, (run->global->mutate.mutationsPerRun * 5));
+
+  }
+
+  /* If last coverage acquisition was more than 5 secs ago, use splicing more
+   * frequently */
+  if ((time(NULL) - ATOMIC_GET(run->global->timing.lastCovUpdate)) > 5) {
+
+    if (util_rnd64() & 0x1) {
+
+      mangle_Splice(run, run->global->cfg.only_printable);
+
     }
 
-    uint64_t changesCnt = run->global->mutate.mutationsPerRun;
+  }
+
+  for (uint64_t x = 0; x < changesCnt; x++) {
+
+    if (run->global->feedback.cmpFeedback && (util_rnd64() & 0x1)) {
+
+      /*
+       * mangle_ConstFeedbackDict() is quite powerful if the dynamic feedback
+       * dictionary exists. If so, give it 50% chance of being used among all
+       * mangling functions.
+       */
+      mangle_ConstFeedbackDict(
+          run, /* printable= */ run->global->cfg.only_printable);
 
-    if (speed_factor < 5) {
-        changesCnt = util_rndGet(1, run->global->mutate.mutationsPerRun);
-    } else if (speed_factor < 10) {
-        changesCnt = run->global->mutate.mutationsPerRun;
     } else {
-        changesCnt = HF_MIN(speed_factor, 10);
-        changesCnt = HF_MAX(changesCnt, (run->global->mutate.mutationsPerRun * 5));
-    }
 
-    /* If last coverage acquisition was more than 5 secs ago, use splicing more frequently */
-    if ((time(NULL) - ATOMIC_GET(run->global->timing.lastCovUpdate)) > 5) {
-        if (util_rnd64() & 0x1) {
-            mangle_Splice(run, run->global->cfg.only_printable);
-        }
-    }
+      uint64_t choice = util_rndGet(0, ARRAYSIZE(mangleFuncs) - 1);
+      mangleFuncs[choice](run,
+                          /* printable= */ run->global->cfg.only_printable);
 
-    for (uint64_t x = 0; x < changesCnt; x++) {
-        if (run->global->feedback.cmpFeedback && (util_rnd64() & 0x1)) {
-            /*
-             * mangle_ConstFeedbackDict() is quite powerful if the dynamic feedback dictionary
-             * exists. If so, give it 50% chance of being used among all mangling functions.
-             */
-            mangle_ConstFeedbackDict(run, /* printable= */ run->global->cfg.only_printable);
-        } else {
-            uint64_t choice = util_rndGet(0, ARRAYSIZE(mangleFuncs) - 1);
-            mangleFuncs[choice](run, /* printable= */ run->global->cfg.only_printable);
-        }
     }
 
-    wmb();
+  }
+
+  wmb();
+
 }
+
diff --git a/custom_mutators/radamsa/custom_mutator_helpers.h b/custom_mutators/radamsa/custom_mutator_helpers.h
deleted file mode 120000
index f7532ef9..00000000
--- a/custom_mutators/radamsa/custom_mutator_helpers.h
+++ /dev/null
@@ -1 +0,0 @@
-../examples/custom_mutator_helpers.h
\ No newline at end of file
diff --git a/custom_mutators/radamsa/radamsa-mutator.c b/custom_mutators/radamsa/radamsa-mutator.c
index 624ace3d..466bb5c3 100644
--- a/custom_mutators/radamsa/radamsa-mutator.c
+++ b/custom_mutators/radamsa/radamsa-mutator.c
@@ -1,6 +1,5 @@
 // This simple example just creates random buffer <= 100 filled with 'A'
 // needs -I /path/to/AFLplusplus/include
-//#include "custom_mutator_helpers.h"
 
 #include <stdint.h>
 #include <stdlib.h>
@@ -8,19 +7,17 @@
 #include <stdio.h>
 
 #include "radamsa.h"
-#include "custom_mutator_helpers.h"
+#include "afl-fuzz.h"
 
 typedef struct my_mutator {
 
-  afl_t *afl;
-
-  u8 *mutator_buf;
-
+  afl_state_t *afl;
+  u8          *mutator_buf;
   unsigned int seed;
 
 } my_mutator_t;
 
-my_mutator_t *afl_custom_init(afl_t *afl, unsigned int seed) {
+my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
 
   srand(seed);
   my_mutator_t *data = calloc(1, sizeof(my_mutator_t));
diff --git a/custom_mutators/symcc/README.md b/custom_mutators/symcc/README.md
index 364a348e..a6839a37 100644
--- a/custom_mutators/symcc/README.md
+++ b/custom_mutators/symcc/README.md
@@ -5,6 +5,8 @@ This uses the symcc to find new paths into the target.
 Note that this is a just a proof of concept example! It is better to use
 the fuzzing helpers of symcc, symqemu, Fuzzolic, etc. rather than this.
 
+Also the symqemu custom mutator is better than this.
+
 To use this custom mutator follow the steps in the symcc repository 
 [https://github.com/eurecom-s3/symcc/](https://github.com/eurecom-s3/symcc/) 
 on how to build symcc and how to instrument a target binary (the same target
diff --git a/custom_mutators/symqemu/Makefile b/custom_mutators/symqemu/Makefile
new file mode 100644
index 00000000..958aec19
--- /dev/null
+++ b/custom_mutators/symqemu/Makefile
@@ -0,0 +1,14 @@
+
+ifdef DEBUG
+  CFLAGS += -DDEBUG
+endif
+
+all: symqemu-mutator.so
+
+CFLAGS	+= -O3 -funroll-loops
+
+symqemu-mutator.so: symqemu.c
+	$(CC) -g $(CFLAGS) $(CPPFLAGS) -g -I../../include -shared -fPIC -o symqemu-mutator.so symqemu.c
+
+clean:
+	rm -f symqemu-mutator.so *.o *~ core
diff --git a/custom_mutators/symqemu/README.md b/custom_mutators/symqemu/README.md
new file mode 100644
index 00000000..c3071afc
--- /dev/null
+++ b/custom_mutators/symqemu/README.md
@@ -0,0 +1,19 @@
+# custum mutator: symqemu
+
+This uses the symcc to find new paths into the target.
+
+## How to build and use
+
+To use this custom mutator follow the steps in the symqemu repository 
+[https://github.com/eurecom-s3/symqemu/](https://github.com/eurecom-s3/symqemu/) 
+on how to build symqemu-x86_x64 and put it in your `PATH`.
+
+Just type `make` to build this custom mutator.
+
+```AFL_CUSTOM_MUTATOR_LIBRARY=custom_mutators/symqemu/symqemu-mutator.so AFL_DISABLE_TRIM=1 afl-fuzz ...```
+
+## Options
+
+`SYMQEMU_ALL=1` - use concolic solving on **all** queue items, not only interesting/favorite ones.
+
+`SYMQEMU_LATE=1` - use concolic solving only after there have been no finds for 5 minutes.
diff --git a/custom_mutators/symqemu/symqemu.c b/custom_mutators/symqemu/symqemu.c
new file mode 100644
index 00000000..73a1640a
--- /dev/null
+++ b/custom_mutators/symqemu/symqemu.c
@@ -0,0 +1,424 @@
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include "config.h"
+#include "debug.h"
+#include "afl-fuzz.h"
+#include "common.h"
+
+afl_state_t *afl_struct;
+static u32   debug = 0;
+static u32   found_items = 0;
+
+#define SYMQEMU_LOCATION "symqemu"
+
+#define DBG(x...) \
+  if (debug) { fprintf(stderr, x); }
+
+typedef struct my_mutator {
+
+  afl_state_t *afl;
+  u32          all;
+  u32          late;
+  u8          *mutator_buf;
+  u8          *out_dir;
+  u8          *target;
+  u8          *symqemu;
+  u8          *input_file;
+  u32          counter;
+  u32          seed;
+  u32          argc;
+  u8         **argv;
+
+} my_mutator_t;
+
+my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
+
+  if (getenv("AFL_DEBUG")) debug = 1;
+
+  my_mutator_t *data = calloc(1, sizeof(my_mutator_t));
+  if (!data) {
+
+    perror("afl_custom_init alloc");
+    return NULL;
+
+  }
+
+  char *path = getenv("PATH");
+  char *exec_name = "symqemu-x86_64";
+  char *token = strtok(path, ":");
+  char  exec_path[4096];
+
+  while (token != NULL && data->symqemu == NULL) {
+
+    snprintf(exec_path, sizeof(exec_path), "%s/%s", token, exec_name);
+    if (access(exec_path, X_OK) == 0) {
+
+      data->symqemu = (u8 *)strdup(exec_path);
+      break;
+
+    }
+
+    token = strtok(NULL, ":");
+
+  }
+
+  if (!data->symqemu) FATAL("symqemu binary %s not found", exec_name);
+  DBG("Found %s\n", data->symqemu);
+
+  if (getenv("AFL_CUSTOM_MUTATOR_ONLY")) {
+
+    WARNF(
+        "the symqemu module is not very effective with "
+        "AFL_CUSTOM_MUTATOR_ONLY.");
+
+  }
+
+  if ((data->mutator_buf = malloc(MAX_FILE)) == NULL) {
+
+    free(data);
+    perror("mutator_buf alloc");
+    return NULL;
+
+  }
+
+  data->target = getenv("AFL_CUSTOM_INFO_PROGRAM");
+
+  u8 *path_tmp = getenv("AFL_CUSTOM_INFO_OUT");
+  u32 len = strlen(path_tmp) + 32;
+  u8 *symqemu_path = malloc(len);
+  data->out_dir = malloc(len);
+  snprintf(symqemu_path, len, "%s/%s", path_tmp, SYMQEMU_LOCATION);
+  snprintf(data->out_dir, len, "%s/out", symqemu_path, path_tmp);
+
+  (void)mkdir(symqemu_path, 0755);
+  (void)mkdir(data->out_dir, 0755);
+
+  setenv("SYMCC_OUTPUT_DIR", data->out_dir, 1);
+
+  data->input_file = getenv("AFL_CUSTOM_INFO_PROGRAM_INPUT");
+
+  u8 *tmp = NULL;
+  if ((tmp = getenv("AFL_CUSTOM_INFO_PROGRAM_ARGV")) && *tmp) {
+
+    int argc = 0, index = 2;
+    for (u32 i = 0; i < strlen(tmp); ++i)
+      if (isspace(tmp[i])) ++argc;
+
+    data->argv = (u8 **)malloc((argc + 4) * sizeof(u8 **));
+    u8 *p = strdup(tmp);
+
+    do {
+
+      data->argv[index] = p;
+      while (*p && !isspace(*p))
+        ++p;
+      if (*p) {
+
+        *p++ = 0;
+        while (isspace(*p))
+          ++p;
+
+      }
+
+      if (strcmp(data->argv[index], "@@") == 0) {
+
+        if (!data->input_file) {
+
+          u32 ilen = strlen(symqemu_path) + 32;
+          data->input_file = malloc(ilen);
+          snprintf(data->input_file, ilen, "%s/.input", symqemu_path);
+
+        }
+
+        data->argv[index] = data->input_file;
+
+      }
+
+      DBG("%d: %s\n", index, data->argv[index]);
+      index++;
+
+    } while (*p);
+
+    data->argv[index] = NULL;
+    data->argc = index;
+
+  } else {
+
+    data->argv = (u8 **)malloc(8 * sizeof(u8 **));
+    data->argc = 2;
+    data->argv[2] = NULL;
+
+  }
+
+  data->argv[0] = data->symqemu;
+  data->argv[1] = data->target;
+  data->afl = afl;
+  data->seed = seed;
+  afl_struct = afl;
+
+  if (getenv("SYMQEMU_ALL")) { data->all = 1; }
+  if (getenv("SYMQEMU_LATE")) { data->late = 1; }
+  if (data->input_file) { setenv("SYMCC_INPUT_FILE", data->input_file, 1); }
+
+  DBG("out_dir=%s, target=%s, input_file=%s, argc=%u\n", data->out_dir,
+      data->target,
+      data->input_file ? (char *)data->input_file : (char *)"<stdin>",
+      data->argc);
+
+  if (debug) {
+
+    fprintf(stderr, "[");
+    for (u32 i = 0; i <= data->argc; ++i)
+      fprintf(stderr, " \"%s\"",
+              data->argv[i] ? (char *)data->argv[i] : "<NULL>");
+    fprintf(stderr, " ]\n");
+
+  }
+
+  return data;
+
+}
+
+/* No need to receive a splicing item */
+void afl_custom_splice_optout(void *data) {
+
+  (void)(data);
+
+}
+
+/* Get unix time in milliseconds */
+
+inline u64 get_cur_time(void) {
+
+  struct timeval  tv;
+  struct timezone tz;
+
+  gettimeofday(&tv, &tz);
+
+  return (tv.tv_sec * 1000ULL) + (tv.tv_usec / 1000);
+
+}
+
+u32 afl_custom_fuzz_count(my_mutator_t *data, const u8 *buf, size_t buf_size) {
+
+  if (likely((!afl_struct->queue_cur->favored && !data->all) ||
+             afl_struct->queue_cur->was_fuzzed)) {
+
+    return 0;
+
+  }
+
+  if (likely(data->late)) {
+
+    if (unlikely(get_cur_time() - afl_struct->last_find_time <=
+                 10 * 60 * 1000)) {
+
+      return 0;
+
+    }
+
+  }
+
+  int         pipefd[2];
+  struct stat st;
+
+  if (afl_struct->afl_env.afl_no_ui) {
+
+    ACTF("Sending to symqemu: %s", afl_struct->queue_cur->fname);
+
+  }
+
+  if (!(stat(afl_struct->queue_cur->fname, &st) == 0 && S_ISREG(st.st_mode) &&
+        st.st_size)) {
+
+    PFATAL("Couldn't find enqueued file: %s", afl_struct->queue_cur->fname);
+
+  }
+
+  if (afl_struct->fsrv.use_stdin) {
+
+    if (pipe(pipefd) == -1) {
+
+      PFATAL(
+          "Couldn't create a pipe for interacting with symqemu child process");
+
+    }
+
+  }
+
+  if (data->input_file) {
+
+    int     fd = open(data->input_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+    ssize_t s = write(fd, buf, buf_size);
+    close(fd);
+    DBG("wrote %zd/%zd to %s\n", s, buf_size, data->input_file);
+
+  }
+
+  int pid = fork();
+
+  if (pid == -1) return 0;
+
+  if (likely(pid)) {
+
+    if (!data->input_file || afl_struct->fsrv.use_stdin) {
+
+      close(pipefd[0]);
+
+      if (fcntl(pipefd[1], F_GETPIPE_SZ)) {
+
+        fcntl(pipefd[1], F_SETPIPE_SZ, MAX_FILE);
+
+      }
+
+      ck_write(pipefd[1], buf, buf_size, data->input_file);
+
+      close(pipefd[1]);
+
+    }
+
+    pid = waitpid(pid, NULL, 0);
+    DBG("symqemu finished executing!\n");
+
+  } else /* (pid == 0) */ {  // child
+
+    if (afl_struct->fsrv.use_stdin) {
+
+      close(pipefd[1]);
+      dup2(pipefd[0], 0);
+
+    }
+
+    DBG("exec=%s\n", data->target);
+    if (!debug) {
+
+      close(1);
+      close(2);
+      dup2(afl_struct->fsrv.dev_null_fd, 1);
+      dup2(afl_struct->fsrv.dev_null_fd, 2);
+
+    }
+
+    execvp((char *)data->argv[0], (char **)data->argv);
+    fprintf(stderr, "Executing: [");
+    for (u32 i = 0; i <= data->argc; ++i)
+      fprintf(stderr, " \"%s\"",
+              data->argv[i] ? (char *)data->argv[i] : "<NULL>");
+    fprintf(stderr, " ]\n");
+    FATAL("Failed to execute %s %s\n", data->argv[0], data->argv[1]);
+    exit(-1);
+
+  }
+
+  /* back in mother process */
+
+  struct dirent **nl;
+  s32             i, items = scandir(data->out_dir, &nl, NULL, NULL);
+  found_items = 0;
+  char source_name[4096];
+
+  if (items > 0) {
+
+    for (i = 0; i < (u32)items; ++i) {
+
+      // symqemu output files start with a digit
+      if (!isdigit(nl[i]->d_name[0])) continue;
+
+      struct stat st;
+      snprintf(source_name, sizeof(source_name), "%s/%s", data->out_dir,
+               nl[i]->d_name);
+      DBG("file=%s\n", source_name);
+
+      if (stat(source_name, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) {
+
+        ++found_items;
+
+      }
+
+      free(nl[i]);
+
+    }
+
+    free(nl);
+
+  }
+
+  DBG("Done, found %u items!\n", found_items);
+
+  return found_items;
+
+}
+
+size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size,
+                       u8 **out_buf, u8 *add_buf, size_t add_buf_size,
+                       size_t max_size) {
+
+  struct dirent **nl;
+  s32             done = 0, i, items = scandir(data->out_dir, &nl, NULL, NULL);
+  char            source_name[4096];
+
+  if (items > 0) {
+
+    for (i = 0; i < (u32)items; ++i) {
+
+      // symqemu output files start with a digit
+      if (!isdigit(nl[i]->d_name[0])) continue;
+
+      struct stat st;
+      snprintf(source_name, sizeof(source_name), "%s/%s", data->out_dir,
+               nl[i]->d_name);
+      DBG("file=%s\n", source_name);
+
+      if (stat(source_name, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) {
+
+        int fd = open(source_name, O_RDONLY);
+        if (fd < 0) { goto got_an_issue; }
+
+        ssize_t r = read(fd, data->mutator_buf, MAX_FILE);
+        close(fd);
+
+        DBG("fn=%s, fd=%d, size=%ld\n", source_name, fd, r);
+
+        if (r < 1) { goto got_an_issue; }
+
+        done = 1;
+        --found_items;
+        unlink(source_name);
+
+        *out_buf = data->mutator_buf;
+        return (u32)r;
+
+      }
+
+      free(nl[i]);
+
+    }
+
+    free(nl);
+
+  }
+
+got_an_issue:
+  *out_buf = NULL;
+  return 0;
+
+}
+
+/**
+ * Deinitialize everything
+ *
+ * @param data The data ptr from afl_custom_init
+ */
+void afl_custom_deinit(my_mutator_t *data) {
+
+  free(data->mutator_buf);
+  free(data);
+
+}
+