about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.gitignore5
-rw-r--r--.travis.yml4
-rw-r--r--GNUmakefile475
-rw-r--r--Makefile452
-rw-r--r--README.md41
-rwxr-xr-xafl-whatsup7
-rw-r--r--dictionaries/regexp.dict365
-rw-r--r--docs/Changelog.md10
-rw-r--r--docs/custom_mutators.md34
-rw-r--r--docs/env_variables.md4
-rw-r--r--docs/notes_for_asan.md2
-rw-r--r--examples/README.md10
-rw-r--r--examples/argv_fuzzing/GNUmakefile51
-rw-r--r--examples/argv_fuzzing/Makefile53
-rw-r--r--examples/custom_mutators/Makefile9
-rw-r--r--examples/custom_mutators/README.md4
-rw-r--r--examples/custom_mutators/custom_mutator_helpers.h82
-rw-r--r--examples/custom_mutators/example.c167
-rw-r--r--examples/custom_mutators/example.py19
-rw-r--r--examples/post_library/post_library.so.c85
-rw-r--r--examples/post_library/post_library_png.so.c72
-rw-r--r--examples/socket_fuzzing/GNUmakefile48
-rw-r--r--examples/socket_fuzzing/Makefile50
-rw-r--r--gcc_plugin/GNUmakefile160
-rw-r--r--gcc_plugin/Makefile152
-rw-r--r--gcc_plugin/afl-gcc-fast.c1
-rw-r--r--include/afl-fuzz.h129
-rw-r--r--include/afl-prealloc.h5
-rw-r--r--include/alloc-inl.h97
-rw-r--r--include/common.h326
-rw-r--r--include/list.h49
-rw-r--r--include/types.h22
-rw-r--r--libdislocator/GNUmakefile44
-rw-r--r--libdislocator/Makefile46
-rw-r--r--libtokencap/GNUmakefile63
-rw-r--r--libtokencap/Makefile65
-rw-r--r--llvm_mode/GNUmakefile375
-rw-r--r--llvm_mode/LLVMInsTrim.so.cc3
-rw-r--r--llvm_mode/Makefile372
-rw-r--r--llvm_mode/afl-clang-fast.c73
-rw-r--r--llvm_mode/afl-llvm-lto-instrumentation.so.cc3
-rw-r--r--llvm_mode/afl-llvm-pass.so.cc73
-rw-r--r--llvm_mode/llvm-ngram-coverage.h2
-rwxr-xr-xqbdi_mode/build.sh2
-rwxr-xr-xqemu_mode/build_qemu_support.sh2
-rw-r--r--qemu_mode/patches/__init__.py.diff17
-rw-r--r--qemu_mode/patches/afl-qemu-cpu-inl.h2
-rw-r--r--qemu_mode/patches/afl-qemu-tcg-inl.h1
-rw-r--r--qemu_mode/patches/make_strncpy_safe.diff31
-rw-r--r--qemu_mode/unsigaction/GNUmakefile34
-rw-r--r--qemu_mode/unsigaction/Makefile34
-rw-r--r--src/README.md24
-rw-r--r--src/README.src22
-rw-r--r--src/afl-analyze.c5
-rw-r--r--src/afl-common.c399
-rw-r--r--src/afl-forkserver.c30
-rw-r--r--src/afl-fuzz-bitmap.c47
-rw-r--r--src/afl-fuzz-cmplog.c76
-rw-r--r--src/afl-fuzz-init.c33
-rw-r--r--src/afl-fuzz-mutators.c61
-rw-r--r--src/afl-fuzz-one.c150
-rw-r--r--src/afl-fuzz-python.c130
-rw-r--r--src/afl-fuzz-queue.c57
-rw-r--r--src/afl-fuzz-redqueen.c5
-rw-r--r--src/afl-fuzz-run.c83
-rw-r--r--src/afl-fuzz-state.c (renamed from src/afl-fuzz-globals.c)13
-rw-r--r--src/afl-fuzz-stats.c125
-rw-r--r--src/afl-fuzz.c13
-rw-r--r--src/afl-showmap.c25
-rw-r--r--src/afl-tmin.c21
-rw-r--r--src/third_party/libradamsa/libradamsa.c2
-rw-r--r--test/test-custom-mutator.c19
-rwxr-xr-xtest/test.sh134
-rw-r--r--test/unittests/unit_list.c128
-rw-r--r--test/unittests/unit_maybe_alloc.c158
-rw-r--r--test/unittests/unit_preallocable.c111
-rw-r--r--unicorn_mode/samples/c/GNUmakefile42
-rw-r--r--unicorn_mode/samples/c/Makefile44
-rw-r--r--unicorn_mode/samples/persistent/GNUmakefile42
-rw-r--r--unicorn_mode/samples/persistent/Makefile44
80 files changed, 3567 insertions, 2708 deletions
diff --git a/.gitignore b/.gitignore
index 6bb2092a..c8a92b7d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,6 +16,7 @@ afl-gcc
 afl-gcc-fast
 afl-g++-fast
 afl-gotcpu
+afl-ld
 afl-qemu-trace
 afl-showmap
 afl-tmin
@@ -39,8 +40,12 @@ afl-tmin.8
 afl-whatsup.8
 qemu_mode/libcompcov/compcovtest
 as
+ld
 qemu_mode/qemu-*
 unicorn_mode/unicornafl/
 unicorn_mode/samples/*/\.test-*
 unicorn_mode/samples/*/output/
 core\.*
+test/unittests/unit_maybe_alloc
+test/unittests/unit_preallocable
+test/unittests/unit_list
diff --git a/.travis.yml b/.travis.yml
index 2c8c8bea..e6c6affa 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -41,8 +41,8 @@ before_install:
   # export LLVM_DIR=${TRAVIS_BUILD_DIR}/${LLVM_PACKAGE}
   - echo Testing on $NAME
   - if [ "$TRAVIS_OS_NAME" = "osx" ]; then wget "$LINK""$NAME".tar.xz ; export LLVM_CONFIG=`pwd`/"$NAME" ; tar xJf "$NAME".tar.xz ; fi
-  - if [ "$MODERN" = "yes" ]; then sudo apt update ; sudo apt upgrade ; sudo apt install -y libtool libtool-bin automake bison libglib2.0 build-essential clang gcc-"$GCC" gcc-"$GCC"-plugin-dev libc++-"$GCC"-dev findutils ; fi
-  - if [ "$MODERN" = "no" ]; then sudo apt update ; sudo apt install -y libtool $EXTRA libpixman-1-dev automake bison libglib2.0 build-essential gcc-"$GCC" gcc-"$GCC"-plugin-dev libc++-dev findutils ; fi
+  - if [ "$MODERN" = "yes" ]; then sudo apt update ; sudo apt upgrade ; sudo apt install -y libtool libtool-bin automake bison libglib2.0 build-essential clang gcc-"$GCC" gcc-"$GCC"-plugin-dev libc++-"$GCC"-dev findutils libcmocka-dev ; fi
+  - if [ "$MODERN" = "no" ]; then sudo apt update ; sudo apt install -y libtool $EXTRA libpixman-1-dev automake bison libglib2.0 build-essential gcc-"$GCC" gcc-"$GCC"-plugin-dev libc++-dev findutils libcmocka-dev ; fi
 
 script:
   - gcc -v
diff --git a/GNUmakefile b/GNUmakefile
new file mode 100644
index 00000000..c03d635c
--- /dev/null
+++ b/GNUmakefile
@@ -0,0 +1,475 @@
+#
+# american fuzzy lop++ - makefile
+# -----------------------------
+#
+# Originally written by Michal Zalewski
+#
+# Copyright 2013, 2014, 2015, 2016, 2017 Google Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+
+# For Heiko:
+#TEST_MMAP=1
+# the hash character is treated differently in different make versions
+# so use a variable for '#'
+HASH=\#
+
+PREFIX     ?= /usr/local
+BIN_PATH    = $(PREFIX)/bin
+HELPER_PATH = $(PREFIX)/lib/afl
+DOC_PATH    = $(PREFIX)/share/doc/afl
+MISC_PATH   = $(PREFIX)/share/afl
+MAN_PATH    = $(PREFIX)/man/man8
+
+PROGNAME    = afl
+VERSION     = $(shell grep '^$(HASH)define VERSION ' ../config.h | cut -d '"' -f2)
+
+# PROGS intentionally omit afl-as, which gets installed elsewhere.
+
+PROGS       = afl-gcc afl-fuzz afl-showmap afl-tmin afl-gotcpu afl-analyze
+SH_PROGS    = afl-plot afl-cmin afl-cmin.bash afl-whatsup afl-system-config
+MANPAGES=$(foreach p, $(PROGS) $(SH_PROGS), $(p).8) afl-as.8
+ASAN_OPTIONS=detect_leaks=0
+
+ifeq "$(shell echo 'int main() {return 0; }' | $(CC) $(CFLAGS) -Werror -x c - -flto=full -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
+	CFLAGS_FLTO ?= -flto=full
+else
+ ifeq "$(shell echo 'int main() {return 0; }' | $(CC) $(CFLAGS) -Werror -x c - -flto=thin -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
+	CFLAGS_FLTO ?= -flto=thin
+ else
+  ifeq "$(shell echo 'int main() {return 0; }' | $(CC) $(CFLAGS) -Werror -x c - -flto -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
+	CFLAGS_FLTO ?= -flto
+  endif
+ endif
+endif
+
+ifneq "$(shell uname)" "Darwin"
+ ifeq "$(shell echo 'int main() {return 0; }' | $(CC) $(CFLAGS) -Werror -x c - -march=native -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
+	CFLAGS_OPT = -march=native
+ endif
+endif
+
+ifneq "$(shell uname -m)" "x86_64"
+ ifneq "$(shell uname -m)" "i386"
+  ifneq "$(shell uname -m)" "amd64"
+   ifneq "$(shell uname -m)" "i86pc"
+	AFL_NO_X86=1
+   endif
+  endif
+ endif
+endif
+
+CFLAGS     ?= -O3 -funroll-loops $(CFLAGS_OPT) -D_FORTIFY_SOURCE=2
+override CFLAGS += -Wall -g -Wno-pointer-sign \
+			  -I include/ -Werror -DAFL_PATH=\"$(HELPER_PATH)\" \
+			  -DBIN_PATH=\"$(BIN_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\"
+
+AFL_FUZZ_FILES = $(wildcard src/afl-fuzz*.c)
+
+ifneq "$(shell type python3m 2>/dev/null)" ""
+  ifneq "$(shell type python3m-config 2>/dev/null)" ""
+    PYTHON_INCLUDE  ?= $(shell python3m-config --includes)
+    PYTHON_VERSION  ?= $(strip $(shell python3m --version 2>&1))
+    # Starting with python3.8, we need to pass the `embed` flag. Earier versions didn't know this flag.
+    ifeq "$(shell python3m-config --embed --libs 2>/dev/null | grep -q lpython && echo 1 )" "1"
+      PYTHON_LIB      ?= $(shell python3m-config --libs --embed)
+    else
+      PYTHON_LIB      ?= $(shell python3m-config --ldflags)
+    endif
+  endif
+endif
+
+ifneq "$(shell type python3 2>/dev/null)" ""
+  ifneq "$(shell type python3-config 2>/dev/null)" ""
+    PYTHON_INCLUDE  ?= $(shell python3-config --includes)
+    PYTHON_VERSION  ?= $(strip $(shell python3 --version 2>&1))
+    # Starting with python3.8, we need to pass the `embed` flag. Earier versions didn't know this flag.
+    ifeq "$(shell python3-config --embed --libs 2>/dev/null | grep -q lpython && echo 1 )" "1"
+      PYTHON_LIB      ?= $(shell python3-config --libs --embed)
+    else
+      PYTHON_LIB      ?= $(shell python3-config --ldflags)
+    endif
+  endif
+endif
+
+ifneq "$(shell type python 2>/dev/null)" ""
+  ifneq "$(shell type python-config 2>/dev/null)" ""
+    PYTHON_INCLUDE  ?= $(shell python-config --includes)
+    PYTHON_LIB      ?= $(shell python-config --ldflags)
+    PYTHON_VERSION  ?= $(strip $(shell python --version 2>&1))
+  endif
+endif
+
+ifdef SOURCE_DATE_EPOCH
+    BUILD_DATE ?= $(shell date -u -d "@$(SOURCE_DATE_EPOCH)" "+%Y-%m-%d" 2>/dev/null || date -u -r "$(SOURCE_DATE_EPOCH)" "+%Y-%m-%d" 2>/dev/null || date -u "+%Y-%m-%d")
+else
+    BUILD_DATE ?= $(shell date "+%Y-%m-%d")
+endif
+
+ifneq "$(filter Linux GNU%,$(shell uname))" ""
+  LDFLAGS  += -ldl
+endif
+
+ifneq "$(findstring FreeBSD, $(shell uname))" ""
+  CFLAGS += -pthread
+  LDFLAGS  += -lpthread
+endif
+
+ifneq "$(findstring NetBSD, $(shell uname))" ""
+  CFLAGS += -pthread
+  LDFLAGS  += -lpthread
+endif
+
+ifeq "$(findstring clang, $(shell $(CC) --version 2>/dev/null))" ""
+  TEST_CC   = afl-gcc
+else
+  TEST_CC   = afl-clang
+endif
+
+COMM_HDR    = include/alloc-inl.h include/config.h include/debug.h include/types.h
+
+ifeq "$(shell echo '$(HASH)include <Python.h>@int main() {return 0; }' | tr @ '\n' | $(CC) $(CFLAGS) -x c - -o .test $(PYTHON_INCLUDE) $(LDFLAGS) $(PYTHON_LIB) 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
+	PYTHON_OK=1
+	PYFLAGS=-DUSE_PYTHON $(PYTHON_INCLUDE) $(LDFLAGS) $(PYTHON_LIB) -DPYTHON_VERSION="\"$(PYTHON_VERSION)\""
+else
+	PYTHON_OK=0
+	PYFLAGS=
+endif
+
+ifdef STATIC
+  $(info Compiling static version of binaries)
+  # Disable python for static compilation to simplify things
+  PYTHON_OK=0
+  PYFLAGS=
+
+  CFLAGS += -static
+  LDFLAGS += -lm -lpthread -lz -lutil
+endif
+
+ASAN_CFLAGS=-fsanitize=address -fstack-protector-all -fno-omit-frame-pointer
+ASAN_LDFLAGS+=-fsanitize=address -fstack-protector-all -fno-omit-frame-pointer
+
+ifdef ASAN_BUILD
+  $(info Compiling ASAN version of binaries)
+  CFLAGS+=$(ASAN_CFLAGS)
+  LDFLAGS+=$(ASAN_LDFLAGS)
+endif
+
+ifdef PROFILING
+  $(info Compiling profiling version of binaries)
+  CFLAGS+=-pg
+  LDFLAGS+=-pg
+endif
+
+ifeq "$(shell echo '$(HASH)include <sys/ipc.h>@$(HASH)include <sys/shm.h>@int main() { int _id = shmget(IPC_PRIVATE, 65536, IPC_CREAT | IPC_EXCL | 0600); shmctl(_id, IPC_RMID, 0); return 0;}' | tr @ '\n' | $(CC) $(CFLAGS) -x c - -o .test2 2>/dev/null && echo 1 || echo 0 ; rm -f .test2 )" "1"
+	SHMAT_OK=1
+else
+	SHMAT_OK=0
+	CFLAGS+=-DUSEMMAP=1
+	LDFLAGS+=-Wno-deprecated-declarations
+endif
+
+ifeq "$(TEST_MMAP)" "1"
+	SHMAT_OK=0
+	CFLAGS+=-DUSEMMAP=1
+	LDFLAGS+=-Wno-deprecated-declarations
+endif
+
+all:	test_x86 test_shm test_python ready $(PROGS) afl-as test_build all_done
+
+man:    $(MANPAGES)
+
+tests:	source-only
+	@cd test ; ./test.sh
+	@rm -f test/errors
+
+performance-tests:	performance-test
+test-performance:	performance-test
+
+performance-test:	source-only
+	@cd test ; ./test-performance.sh
+
+
+help:
+	@echo "HELP --- the following make targets exist:"
+	@echo "=========================================="
+	@echo "all: just the main afl++ binaries"
+	@echo "binary-only: everything for binary-only fuzzing: qemu_mode, unicorn_mode, libdislocator, libtokencap, radamsa"
+	@echo "source-only: everything for source code fuzzing: llvm_mode, gcc_plugin, libdislocator, libtokencap, radamsa"
+	@echo "distrib: everything (for both binary-only and source code fuzzing)"
+	@echo "man: creates simple man pages from the help option of the programs"
+	@echo "install: installs everything you have compiled with the build option above"
+	@echo "clean: cleans everything. for qemu_mode it means it deletes all downloads as well"
+	@echo "code-format: format the code, do this before you commit and send a PR please!"
+	@echo "tests: this runs the test framework. It is more catered for the developers, but if you run into problems this helps pinpointing the problem"
+	@echo "unit: perform unit tests (based on cmocka)"
+	@echo "document: creates afl-fuzz-document which will only do one run and save all manipulated inputs into out/queue/mutations"
+	@echo "help: shows these build options :-)"
+	@echo "=========================================="
+	@echo "Recommended: \"distrib\" or \"source-only\", then \"install\""
+	@echo
+	@echo Known build environment options:
+	@echo "=========================================="
+	@echo STATIC - compile AFL++ static
+	@echo ASAN_BUILD - compiles with memory sanitizer for debug purposes
+	@echo PROFILING - compile afl-fuzz with profiling information
+	@echo AFL_NO_X86 - if compiling on non-intel/amd platforms
+	@echo "=========================================="
+	@echo e.g.: make ASAN_BUILD=1
+
+ifndef AFL_NO_X86
+
+test_x86:
+	@echo "[*] Checking for the default compiler cc..."
+	@type $(CC) >/dev/null || ( echo; echo "Oops, looks like there is no compiler '"$(CC)"' in your path."; echo; echo "Don't panic! You can restart with '"$(_)" CC=<yourCcompiler>'."; echo; exit 1 )
+	@echo "[*] Checking for the ability to compile x86 code..."
+	@echo 'main() { __asm__("xorb %al, %al"); }' | $(CC) $(CFLAGS) -w -x c - -o .test1 || ( echo; echo "Oops, looks like your compiler can't generate x86 code."; echo; echo "Don't panic! You can use the LLVM or QEMU mode, but see docs/INSTALL first."; echo "(To ignore this error, set AFL_NO_X86=1 and try again.)"; echo; exit 1 )
+	@rm -f .test1
+
+else
+
+test_x86:
+	@echo "[!] Note: skipping x86 compilation checks (AFL_NO_X86 set)."
+
+endif
+
+
+ifeq "$(SHMAT_OK)" "1"
+
+test_shm:
+	@echo "[+] shmat seems to be working."
+	@rm -f .test2
+
+else
+
+test_shm:
+	@echo "[-] shmat seems not to be working, switching to mmap implementation"
+
+endif
+
+
+ifeq "$(PYTHON_OK)" "1"
+
+test_python:
+	@rm -f .test 2> /dev/null
+	@echo "[+] $(PYTHON_VERSION) support seems to be working."
+
+else
+
+test_python:
+	@echo "[-] You seem to need to install the package python3-dev or python2-dev (and perhaps python[23]-apt), but it is optional so we continue"
+
+endif
+
+
+ready:
+	@echo "[+] Everything seems to be working, ready to compile."
+
+afl-gcc: src/afl-gcc.c $(COMM_HDR) | test_x86
+	$(CC) $(CFLAGS) src/$@.c -o $@ $(LDFLAGS)
+	set -e; for i in afl-g++ afl-clang afl-clang++; do ln -sf afl-gcc $$i; done
+
+afl-as: src/afl-as.c include/afl-as.h $(COMM_HDR) | test_x86
+	$(CC) $(CFLAGS) src/$@.c -o $@ $(LDFLAGS)
+	ln -sf afl-as as
+
+src/afl-common.o : $(COMM_HDR) src/afl-common.c include/common.h
+	$(CC) $(CFLAGS) $(CFLAGS_FLTO) -c src/afl-common.c -o src/afl-common.o
+
+src/afl-forkserver.o : $(COMM_HDR) src/afl-forkserver.c include/forkserver.h
+	$(CC) $(CFLAGS) $(CFLAGS_FLTO) -c src/afl-forkserver.c -o src/afl-forkserver.o
+
+src/afl-sharedmem.o : $(COMM_HDR) src/afl-sharedmem.c include/sharedmem.h
+	$(CC) $(CFLAGS) $(CFLAGS_FLTO) -c src/afl-sharedmem.c -o src/afl-sharedmem.o
+
+radamsa: src/third_party/libradamsa/libradamsa.so
+	cp src/third_party/libradamsa/libradamsa.so .
+
+src/third_party/libradamsa/libradamsa.so: src/third_party/libradamsa/libradamsa.c src/third_party/libradamsa/radamsa.h
+	$(MAKE) -C src/third_party/libradamsa/ CFLAGS="$(CFLAGS)"
+
+afl-fuzz: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o | test_x86
+	$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o -o $@ $(PYFLAGS) $(LDFLAGS)
+
+afl-showmap: src/afl-showmap.c src/afl-common.o src/afl-sharedmem.o $(COMM_HDR) | test_x86
+	$(CC) $(CFLAGS) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o -o $@ $(LDFLAGS)
+
+afl-tmin: src/afl-tmin.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o $(COMM_HDR) | test_x86
+	$(CC) $(CFLAGS) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o -o $@ $(LDFLAGS)
+
+afl-analyze: src/afl-analyze.c src/afl-common.o src/afl-sharedmem.o $(COMM_HDR) | test_x86
+	$(CC) $(CFLAGS) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o -o $@ $(LDFLAGS)
+
+afl-gotcpu: src/afl-gotcpu.c src/afl-common.o $(COMM_HDR) | test_x86
+	$(CC) $(CFLAGS) src/$@.c src/afl-common.o -o $@ $(LDFLAGS)
+
+
+# document all mutations and only do one run (use with only one input file!)
+document: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o | test_x86
+	$(CC) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o -o afl-fuzz-document $(PYFLAGS) $(LDFLAGS)
+
+test/unittests/unit_maybe_alloc.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_maybe_alloc.c $(AFL_FUZZ_FILES)
+	$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_maybe_alloc.c -o test/unittests/unit_maybe_alloc.o
+
+test/unittests/unit_preallocable.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_preallocable.c $(AFL_FUZZ_FILES)
+	$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_preallocable.c -o test/unittests/unit_preallocable.o
+
+unit_maybe_alloc: test/unittests/unit_maybe_alloc.o
+	$(CC) $(CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_maybe_alloc.o -o test/unittests/unit_maybe_alloc $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
+	./test/unittests/unit_maybe_alloc
+
+test/unittests/unit_list.o : $(COMM_HDR) include/list.h test/unittests/unit_list.c $(AFL_FUZZ_FILES)
+	$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_list.c -o test/unittests/unit_list.o
+
+unit_list: test/unittests/unit_list.o
+	$(CC) $(CFLAGS) $(ASAN_CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_list.o -o test/unittests/unit_list  $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
+	./test/unittests/unit_list
+
+test/unittests/preallocable.o : $(COMM_HDR) include/afl-prealloc.h test/unittests/preallocable.c $(AFL_FUZZ_FILES)
+	$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(CFLAGS_FLTO) -c test/unittests/preallocable.c -o test/unittests/preallocable.o
+
+unit_preallocable: test/unittests/unit_preallocable.o
+	$(CC) $(CFLAGS) $(ASAN_CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_preallocable.o -o test/unittests/unit_preallocable $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
+	./test/unittests/unit_preallocable
+
+unit: unit_maybe_alloc unit_preallocable unit_list
+
+code-format:
+	./.custom-format.py -i src/*.c
+	./.custom-format.py -i include/*.h
+	./.custom-format.py -i libdislocator/*.c
+	./.custom-format.py -i libtokencap/*.c
+	./.custom-format.py -i llvm_mode/*.c
+	./.custom-format.py -i llvm_mode/*.h
+	./.custom-format.py -i llvm_mode/*.cc
+	./.custom-format.py -i gcc_plugin/*.c
+	#./.custom-format.py -i gcc_plugin/*.h
+	./.custom-format.py -i gcc_plugin/*.cc
+	./.custom-format.py -i examples/*/*.c
+	./.custom-format.py -i examples/*/*.h
+	./.custom-format.py -i qemu_mode/patches/*.h
+	./.custom-format.py -i qemu_mode/libcompcov/*.c
+	./.custom-format.py -i qemu_mode/libcompcov/*.cc
+	./.custom-format.py -i qemu_mode/libcompcov/*.h
+	./.custom-format.py -i qbdi_mode/*.c
+	./.custom-format.py -i qbdi_mode/*.cpp
+	./.custom-format.py -i *.h
+	./.custom-format.py -i *.c
+
+
+ifndef AFL_NO_X86
+
+test_build: afl-gcc afl-as afl-showmap
+	@echo "[*] Testing the CC wrapper and instrumentation output..."
+	@unset AFL_USE_ASAN AFL_USE_MSAN AFL_CC; AFL_DEBUG=1 AFL_INST_RATIO=100 AFL_PATH=. ./$(TEST_CC) $(CFLAGS) test-instr.c -o test-instr $(LDFLAGS) 2>&1 | grep 'afl-as' >/dev/null || (echo "Oops, afl-as did not get called from "$(TEST_CC)". This is normally achieved by "$(CC)" honoring the -B option."; exit 1 )
+	ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null
+	echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
+	@rm -f test-instr
+	@cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation does not seem to be behaving correctly!"; echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue."; echo; exit 1; fi
+	@echo "[+] All right, the instrumentation seems to be working!"
+
+else
+
+test_build: afl-gcc afl-as afl-showmap
+	@echo "[!] Note: skipping build tests (you may need to use LLVM or QEMU mode)."
+
+endif
+
+
+all_done: test_build
+	@if [ ! "`type clang 2>/dev/null`" = "" ]; then echo "[+] LLVM users: see llvm_mode/README.md for a faster alternative to afl-gcc."; fi
+	@echo "[+] All done! Be sure to review the README.md - it's pretty short and useful."
+	@if [ "`uname`" = "Darwin" ]; then printf "\nWARNING: Fuzzing on MacOS X is slow because of the unusually high overhead of\nfork() on this OS. Consider using Linux or *BSD. You can also use VirtualBox\n(virtualbox.org) to put AFL inside a Linux or *BSD VM.\n\n"; fi
+	@! tty <&1 >/dev/null || printf "\033[0;30mNOTE: If you can read this, your terminal probably uses white background.\nThis will make the UI hard to read. See docs/status_screen.md for advice.\033[0m\n" 2>/dev/null
+
+.NOTPARALLEL: clean
+
+clean:
+	rm -f $(PROGS) libradamsa.so afl-fuzz-document afl-as as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 qemu_mode/qemu-3.1.1.tar.xz afl-qemu-trace afl-gcc-fast afl-gcc-pass.so afl-gcc-rt.o afl-g++-fast ld *.so *.8 test/unittests/*.o test/unittests/unit_maybe_alloc test/unittests/preallocable
+	rm -rf out_dir qemu_mode/qemu-3.1.1 *.dSYM */*.dSYM
+	-$(MAKE) -C llvm_mode clean
+	-$(MAKE) -C gcc_plugin clean
+	$(MAKE) -C libdislocator clean
+	$(MAKE) -C libtokencap clean
+	$(MAKE) -C examples/socket_fuzzing clean
+	$(MAKE) -C examples/argv_fuzzing clean
+	$(MAKE) -C qemu_mode/unsigaction clean
+	$(MAKE) -C qemu_mode/libcompcov clean
+	$(MAKE) -C src/third_party/libradamsa/ clean
+	-rm -rf unicorn_mode/unicornafl
+
+distrib: all radamsa
+	-$(MAKE) -C llvm_mode
+	-$(MAKE) -C gcc_plugin
+	$(MAKE) -C libdislocator
+	$(MAKE) -C libtokencap
+	$(MAKE) -C examples/socket_fuzzing
+	$(MAKE) -C examples/argv_fuzzing
+	cd qemu_mode && sh ./build_qemu_support.sh
+	cd unicorn_mode && sh ./build_unicorn_support.sh
+
+binary-only: all radamsa
+	$(MAKE) -C libdislocator
+	$(MAKE) -C libtokencap
+	$(MAKE) -C examples/socket_fuzzing
+	$(MAKE) -C examples/argv_fuzzing
+	cd qemu_mode && sh ./build_qemu_support.sh
+	cd unicorn_mode && sh ./build_unicorn_support.sh
+
+source-only: all radamsa
+	-$(MAKE) -C llvm_mode
+	-$(MAKE) -C gcc_plugin
+	$(MAKE) -C libdislocator
+	$(MAKE) -C libtokencap
+
+%.8:	%
+	@echo .TH $* 8 $(BUILD_DATE) "afl++" > $@
+	@echo .SH NAME >> $@
+	@echo .B $* >> $@
+	@echo >> $@
+	@echo .SH SYNOPSIS >> $@
+	@./$* -h 2>&1 | head -n 3 | tail -n 1 | sed 's/^\.\///' >> $@
+	@echo >> $@
+	@echo .SH OPTIONS >> $@
+	@echo .nf >> $@
+	@./$* -hh 2>&1 | tail -n +4 >> $@
+	@echo >> $@
+	@echo .SH AUTHOR >> $@
+	@echo "afl++ was written by Michal \"lcamtuf\" Zalewski and is maintained by Marc \"van Hauser\" Heuse <mh@mh-sec.de>, Heiko \"hexcoder-\" Eissfeldt <heiko.eissfeldt@hexco.de>, Andrea Fioraldi <andreafioraldi@gmail.com> and Dominik Maier <domenukk@gmail.com>" >> $@
+	@echo  The homepage of afl++ is: https://github.com/AFLplusplus/AFLplusplus >> $@
+	@echo >> $@
+	@echo .SH LICENSE >> $@
+	@echo Apache License Version 2.0, January 2004 >> $@
+
+install: all $(MANPAGES)
+	install -d -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) $${DESTDIR}$(DOC_PATH) $${DESTDIR}$(MISC_PATH)
+	rm -f $${DESTDIR}$(BIN_PATH)/afl-plot.sh
+	install -m 755 $(PROGS) $(SH_PROGS) $${DESTDIR}$(BIN_PATH)
+	rm -f $${DESTDIR}$(BIN_PATH)/afl-as
+	if [ -f afl-qemu-trace ]; then install -m 755 afl-qemu-trace $${DESTDIR}$(BIN_PATH); fi
+	if [ -f afl-gcc-fast ]; then set e; install -m 755 afl-gcc-fast $${DESTDIR}$(BIN_PATH); ln -sf afl-gcc-fast $${DESTDIR}$(BIN_PATH)/afl-g++-fast; install -m 755 afl-gcc-pass.so afl-gcc-rt.o $${DESTDIR}$(HELPER_PATH); fi
+	if [ -f afl-clang-fast ]; then $(MAKE) -C llvm_mode install; fi
+	if [ -f libdislocator.so ]; then set -e; install -m 755 libdislocator.so $${DESTDIR}$(HELPER_PATH); fi
+	if [ -f libtokencap.so ]; then set -e; install -m 755 libtokencap.so $${DESTDIR}$(HELPER_PATH); fi
+	if [ -f libcompcov.so ]; then set -e; install -m 755 libcompcov.so $${DESTDIR}$(HELPER_PATH); fi
+	if [ -f libradamsa.so ]; then set -e; install -m 755 libradamsa.so $${DESTDIR}$(HELPER_PATH); fi
+	if [ -f afl-fuzz-document ]; then set -e; install -m 755 afl-fuzz-document $${DESTDIR}$(BIN_PATH); fi
+	if [ -f socketfuzz32.so -o -f socketfuzz64.so ]; then $(MAKE) -C examples/socket_fuzzing install; fi
+	if [ -f argvfuzz32.so -o -f argvfuzz64.so ]; then $(MAKE) -C examples/argv_fuzzing install; fi
+
+	set -e; ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-g++
+	set -e; if [ -f afl-clang-fast ] ; then ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang++ ; else ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-clang++; fi
+
+	mkdir -m 0755 -p ${DESTDIR}$(MAN_PATH)
+	install -m0644 *.8 ${DESTDIR}$(MAN_PATH)
+
+	install -m 755 afl-as $${DESTDIR}$(HELPER_PATH)
+	ln -sf afl-as $${DESTDIR}$(HELPER_PATH)/as
+	install -m 644 docs/*.md $${DESTDIR}$(DOC_PATH)
+	cp -r testcases/ $${DESTDIR}$(MISC_PATH)
+	cp -r dictionaries/ $${DESTDIR}$(MISC_PATH)
diff --git a/Makefile b/Makefile
index 9913c603..0b306dde 100644
--- a/Makefile
+++ b/Makefile
@@ -1,450 +1,2 @@
-#
-# american fuzzy lop++ - makefile
-# -----------------------------
-#
-# Originally written by Michal Zalewski
-# 
-# Copyright 2013, 2014, 2015, 2016, 2017 Google Inc. All rights reserved.
-# 
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-# 
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-
-# For Heiko:
-#TEST_MMAP=1
-# the hash character is treated differently in different make versions
-# so use a variable for '#'
-HASH=\#
-
-PREFIX     ?= /usr/local
-BIN_PATH    = $(PREFIX)/bin
-HELPER_PATH = $(PREFIX)/lib/afl
-DOC_PATH    = $(PREFIX)/share/doc/afl
-MISC_PATH   = $(PREFIX)/share/afl
-MAN_PATH    = $(PREFIX)/man/man8
-
-PROGNAME    = afl
-VERSION     = $(shell grep '^$(HASH)define VERSION ' ../config.h | cut -d '"' -f2)
-
-# PROGS intentionally omit afl-as, which gets installed elsewhere.
-
-PROGS       = afl-gcc afl-fuzz afl-showmap afl-tmin afl-gotcpu afl-analyze
-SH_PROGS    = afl-plot afl-cmin afl-cmin.bash afl-whatsup afl-system-config
-MANPAGES=$(foreach p, $(PROGS) $(SH_PROGS), $(p).8) afl-as.8
-ASAN_OPTIONS=detect_leaks=0
-
-ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -flto=full -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
-	CFLAGS_FLTO ?= -flto=full
-else
- ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -flto=thin -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
-	CFLAGS_FLTO ?= -flto=thin
- else
-  ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -flto -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
-	CFLAGS_FLTO ?= -flto
-  endif
- endif
-endif
-
-ifneq "$(shell uname)" "Darwin"
- ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -march=native -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
-	CFLAGS_OPT = -march=native
- endif
-endif
-
-ifneq "$(shell uname -m)" "x86_64"
- ifneq "$(shell uname -m)" "i386"
-  ifneq "$(shell uname -m)" "amd64"
-   ifneq "$(shell uname -m)" "i86pc"
-	AFL_NO_X86=1
-   endif
-  endif
- endif
-endif
-
-CFLAGS     ?= -O3 -funroll-loops $(CFLAGS_OPT)
-override CFLAGS     += -Wall -g -Wno-pointer-sign -I include/ \
-              -DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \
-              -DDOC_PATH=\"$(DOC_PATH)\" -Wno-unused-function -fcommon
-
-AFL_FUZZ_FILES = $(wildcard src/afl-fuzz*.c)
-
-ifneq "$(shell type python3m 2>/dev/null)" ""
-  ifneq "$(shell type python3m-config 2>/dev/null)" ""
-    PYTHON_INCLUDE  ?= $(shell python3m-config --includes)
-    PYTHON_VERSION  ?= $(strip $(shell python3m --version 2>&1))
-    # Starting with python3.8, we need to pass the `embed` flag. Earier versions didn't know this flag.
-    ifeq "$(shell python3m-config --embed --libs 2>/dev/null | grep -q lpython && echo 1 )" "1"
-      PYTHON_LIB      ?= $(shell python3m-config --libs --embed)
-    else
-      PYTHON_LIB      ?= $(shell python3m-config --ldflags)
-    endif
-  endif
-endif
-
-ifneq "$(shell type python3 2>/dev/null)" ""
-  ifneq "$(shell type python3-config 2>/dev/null)" ""
-    PYTHON_INCLUDE  ?= $(shell python3-config --includes)
-    PYTHON_VERSION  ?= $(strip $(shell python3 --version 2>&1))
-    # Starting with python3.8, we need to pass the `embed` flag. Earier versions didn't know this flag.
-    ifeq "$(shell python3-config --embed --libs 2>/dev/null | grep -q lpython && echo 1 )" "1"
-      PYTHON_LIB      ?= $(shell python3-config --libs --embed)
-    else
-      PYTHON_LIB      ?= $(shell python3-config --ldflags)
-    endif
-  endif
-endif
-
-ifneq "$(shell type python 2>/dev/null)" ""
-  ifneq "$(shell type python-config 2>/dev/null)" ""
-    PYTHON_INCLUDE  ?= $(shell python-config --includes)
-    PYTHON_LIB      ?= $(shell python-config --ldflags)
-    PYTHON_VERSION  ?= $(strip $(shell python --version 2>&1))
-  endif
-endif
-
-ifdef SOURCE_DATE_EPOCH
-    BUILD_DATE ?= $(shell date -u -d "@$(SOURCE_DATE_EPOCH)" "+%Y-%m-%d" 2>/dev/null || date -u -r "$(SOURCE_DATE_EPOCH)" "+%Y-%m-%d" 2>/dev/null || date -u "+%Y-%m-%d")
-else
-    BUILD_DATE ?= $(shell date "+%Y-%m-%d")
-endif
-
-ifneq "$(filter Linux GNU%,$(shell uname))" ""
-  LDFLAGS  += -ldl
-endif
-
-ifneq "$(findstring FreeBSD, $(shell uname))" ""
-  CFLAGS += -pthread
-  LDFLAGS  += -lpthread
-endif
-
-ifneq "$(findstring NetBSD, $(shell uname))" ""
-  CFLAGS += -pthread
-  LDFLAGS  += -lpthread
-endif
-
-ifeq "$(findstring clang, $(shell $(CC) --version 2>/dev/null))" ""
-  TEST_CC   = afl-gcc
-else
-  TEST_CC   = afl-clang
-endif
-
-COMM_HDR    = include/alloc-inl.h include/config.h include/debug.h include/types.h
-
-ifeq "$(shell echo '$(HASH)include <Python.h>@int main() {return 0; }' | tr @ '\n' | $(CC) -x c - -o .test $(PYTHON_INCLUDE) $(LDFLAGS) $(PYTHON_LIB) 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
-	PYTHON_OK=1
-	PYFLAGS=-DUSE_PYTHON $(PYTHON_INCLUDE) $(LDFLAGS) $(PYTHON_LIB) -DPYTHON_VERSION="\"$(PYTHON_VERSION)\""
-else
-	PYTHON_OK=0
-	PYFLAGS=
-endif
-
-ifdef STATIC
-  $(info Compiling static version of binaries)
-  # Disable python for static compilation to simplify things
-  PYTHON_OK=0
-  PYFLAGS=
-
-  CFLAGS += -static
-  LDFLAGS += -lm -lpthread -lz -lutil
-endif
-
-ifdef ASAN_BUILD
-  $(info Compiling ASAN version of binaries)
-  CFLAGS+=-fsanitize=address
-  LDFLAGS+=-fsanitize=address
-endif
-
-ifdef PROFILING
-  $(info Compiling profiling version of binaries)
-  CFLAGS+=-pg
-  LDFLAGS+=-pg
-endif
-
-ifeq "$(shell echo '$(HASH)include <sys/ipc.h>@$(HASH)include <sys/shm.h>@int main() { int _id = shmget(IPC_PRIVATE, 65536, IPC_CREAT | IPC_EXCL | 0600); shmctl(_id, IPC_RMID, 0); return 0;}' | tr @ '\n' | $(CC) -x c - -o .test2 2>/dev/null && echo 1 || echo 0 ; rm -f .test2 )" "1"
-	SHMAT_OK=1
-else
-	SHMAT_OK=0
-	CFLAGS+=-DUSEMMAP=1
-	LDFLAGS+=-Wno-deprecated-declarations
-endif
-
-ifeq "$(TEST_MMAP)" "1"
-	SHMAT_OK=0
-	CFLAGS+=-DUSEMMAP=1
-	LDFLAGS+=-Wno-deprecated-declarations
-endif
-
-all:	test_x86 test_shm test_python ready $(PROGS) afl-as test_build all_done
-
-man:    $(MANPAGES) 
-	-$(MAKE) -C llvm_mode
-	-$(MAKE) -C gcc_plugin
-
-tests:	source-only
-	@cd test ; ./test.sh
-	@rm -f test/errors
-
-performance-tests:	performance-test
-test-performance:	performance-test
-
-performance-test:	source-only
-	@cd test ; ./test-performance.sh
-
-
-help:
-	@echo "HELP --- the following make targets exist:"
-	@echo "=========================================="
-	@echo "all: just the main afl++ binaries"
-	@echo "binary-only: everything for binary-only fuzzing: qemu_mode, unicorn_mode, libdislocator, libtokencap, radamsa"
-	@echo "source-only: everything for source code fuzzing: llvm_mode, gcc_plugin, libdislocator, libtokencap, radamsa"
-	@echo "distrib: everything (for both binary-only and source code fuzzing)"
-	@echo "man: creates simple man pages from the help option of the programs"
-	@echo "install: installs everything you have compiled with the build option above"
-	@echo "clean: cleans everything. for qemu_mode it means it deletes all downloads as well"
-	@echo "code-format: format the code, do this before you commit and send a PR please!"
-	@echo "tests: this runs the test framework. It is more catered for the developers, but if you run into problems this helps pinpointing the problem"
-	@echo "document: creates afl-fuzz-document which will only do one run and save all manipulated inputs into out/queue/mutations"
-	@echo "help: shows these build options :-)"
-	@echo "=========================================="
-	@echo "Recommended: \"distrib\" or \"source-only\", then \"install\""
-	@echo
-	@echo Known build environment options:
-	@echo "=========================================="
-	@echo STATIC - compile AFL++ static
-	@echo ASAN_BUILD - compiles with memory sanitizer for debug purposes
-	@echo PROFILING - compile afl-fuzz with profiling information
-	@echo AFL_NO_X86 - if compiling on non-intel/amd platforms
-	@echo "=========================================="
-	@echo e.g.: make ASAN_BUILD=1
-
-ifndef AFL_NO_X86
-
-test_x86:
-	@echo "[*] Checking for the default compiler cc..."
-	@type $(CC) >/dev/null || ( echo; echo "Oops, looks like there is no compiler '"$(CC)"' in your path."; echo; echo "Don't panic! You can restart with '"$(_)" CC=<yourCcompiler>'."; echo; exit 1 )
-	@echo "[*] Checking for the ability to compile x86 code..."
-	@echo 'main() { __asm__("xorb %al, %al"); }' | $(CC) -w -x c - -o .test1 || ( echo; echo "Oops, looks like your compiler can't generate x86 code."; echo; echo "Don't panic! You can use the LLVM or QEMU mode, but see docs/INSTALL first."; echo "(To ignore this error, set AFL_NO_X86=1 and try again.)"; echo; exit 1 )
-	@rm -f .test1
-
-else
-
-test_x86:
-	@echo "[!] Note: skipping x86 compilation checks (AFL_NO_X86 set)."
-
-endif
-
-
-ifeq "$(SHMAT_OK)" "1"
-
-test_shm:
-	@echo "[+] shmat seems to be working."
-	@rm -f .test2
-
-else
-
-test_shm:
-	@echo "[-] shmat seems not to be working, switching to mmap implementation"
-
-endif
-
-
-ifeq "$(PYTHON_OK)" "1"
-
-test_python:
-	@rm -f .test 2> /dev/null
-	@echo "[+] $(PYTHON_VERSION) support seems to be working."
-
-else
-
-test_python:
-	@echo "[-] You seem to need to install the package python3-dev or python2-dev (and perhaps python[23]-apt), but it is optional so we continue"
-
-endif
-
-
-ready:
-	@echo "[+] Everything seems to be working, ready to compile."
-
-afl-gcc: src/afl-gcc.c $(COMM_HDR) | test_x86
-	$(CC) $(CFLAGS) src/$@.c -o $@ $(LDFLAGS)
-	set -e; for i in afl-g++ afl-clang afl-clang++; do ln -sf afl-gcc $$i; done
-
-afl-as: src/afl-as.c include/afl-as.h $(COMM_HDR) | test_x86
-	$(CC) $(CFLAGS) src/$@.c -o $@ $(LDFLAGS)
-	ln -sf afl-as as
-
-src/afl-common.o : $(COMM_HDR) src/afl-common.c include/common.h
-	$(CC) $(CFLAGS) $(CFLAGS_FLTO) -c src/afl-common.c -o src/afl-common.o
-
-src/afl-forkserver.o : $(COMM_HDR) src/afl-forkserver.c include/forkserver.h
-	$(CC) $(CFLAGS) $(CFLAGS_FLTO) -c src/afl-forkserver.c -o src/afl-forkserver.o
-
-src/afl-sharedmem.o : $(COMM_HDR) src/afl-sharedmem.c include/sharedmem.h
-	$(CC) $(CFLAGS) $(CFLAGS_FLTO) -c src/afl-sharedmem.c -o src/afl-sharedmem.o
-
-radamsa: src/third_party/libradamsa/libradamsa.so
-	cp src/third_party/libradamsa/libradamsa.so .
-
-src/third_party/libradamsa/libradamsa.so: src/third_party/libradamsa/libradamsa.c src/third_party/libradamsa/radamsa.h
-	$(MAKE) -C src/third_party/libradamsa/ CFLAGS="$(CFLAGS)"
-
-afl-fuzz: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o | test_x86
-	$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o -o $@ $(PYFLAGS) $(LDFLAGS)
-
-afl-showmap: src/afl-showmap.c src/afl-common.o src/afl-sharedmem.o $(COMM_HDR) | test_x86
-	$(CC) $(CFLAGS) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o -o $@ $(LDFLAGS)
-
-afl-tmin: src/afl-tmin.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o $(COMM_HDR) | test_x86
-	$(CC) $(CFLAGS) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o -o $@ $(LDFLAGS)
-
-afl-analyze: src/afl-analyze.c src/afl-common.o src/afl-sharedmem.o $(COMM_HDR) | test_x86
-	$(CC) $(CFLAGS) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o -o $@ $(LDFLAGS)
-
-afl-gotcpu: src/afl-gotcpu.c $(COMM_HDR) | test_x86
-	$(CC) $(CFLAGS) src/$@.c -o $@ $(LDFLAGS)
-
-
-# document all mutations and only do one run (use with only one input file!)
-document: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o | test_x86
-	$(CC) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o -o afl-fuzz-document $(PYFLAGS) $(LDFLAGS)
-
-
-
-code-format:
-	./.custom-format.py -i src/*.c
-	./.custom-format.py -i include/*.h
-	./.custom-format.py -i libdislocator/*.c 
-	./.custom-format.py -i libtokencap/*.c 
-	./.custom-format.py -i llvm_mode/*.c
-	./.custom-format.py -i llvm_mode/*.h
-	./.custom-format.py -i llvm_mode/*.cc
-	./.custom-format.py -i gcc_plugin/*.c
-	#./.custom-format.py -i gcc_plugin/*.h
-	./.custom-format.py -i gcc_plugin/*.cc
-	./.custom-format.py -i examples/*/*.c
-	./.custom-format.py -i examples/*/*.h
-	./.custom-format.py -i qemu_mode/patches/*.h
-	./.custom-format.py -i qemu_mode/libcompcov/*.c
-	./.custom-format.py -i qemu_mode/libcompcov/*.cc
-	./.custom-format.py -i qemu_mode/libcompcov/*.h
-	./.custom-format.py -i qbdi_mode/*.c
-	./.custom-format.py -i qbdi_mode/*.cpp
-	./.custom-format.py -i *.h
-	./.custom-format.py -i *.c
-
-
-ifndef AFL_NO_X86
-
-test_build: afl-gcc afl-as afl-showmap
-	@echo "[*] Testing the CC wrapper and instrumentation output..."
-	@unset AFL_USE_ASAN AFL_USE_MSAN AFL_CC; AFL_DEBUG=1 AFL_INST_RATIO=100 AFL_PATH=. ./$(TEST_CC) $(CFLAGS) test-instr.c -o test-instr $(LDFLAGS) 2>&1 | grep 'afl-as' >/dev/null || (echo "Oops, afl-as did not get called from "$(TEST_CC)". This is normally achieved by "$(CC)" honoring the -B option."; exit 1 )
-	ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null
-	echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
-	@rm -f test-instr
-	@cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation does not seem to be behaving correctly!"; echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue."; echo; exit 1; fi
-	@echo "[+] All right, the instrumentation seems to be working!"
-
-else
-
-test_build: afl-gcc afl-as afl-showmap
-	@echo "[!] Note: skipping build tests (you may need to use LLVM or QEMU mode)."
-
-endif
-
-
-all_done: test_build
-	@if [ ! "`type clang 2>/dev/null`" = "" ]; then echo "[+] LLVM users: see llvm_mode/README.md for a faster alternative to afl-gcc."; fi
-	@echo "[+] All done! Be sure to review the README.md - it's pretty short and useful."
-	@if [ "`uname`" = "Darwin" ]; then printf "\nWARNING: Fuzzing on MacOS X is slow because of the unusually high overhead of\nfork() on this OS. Consider using Linux or *BSD. You can also use VirtualBox\n(virtualbox.org) to put AFL inside a Linux or *BSD VM.\n\n"; fi
-	@! tty <&1 >/dev/null || printf "\033[0;30mNOTE: If you can read this, your terminal probably uses white background.\nThis will make the UI hard to read. See docs/status_screen.md for advice.\033[0m\n" 2>/dev/null
-
-.NOTPARALLEL: clean
-
-clean:
-	rm -f $(PROGS) libradamsa.so afl-fuzz-document afl-as as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 qemu_mode/qemu-3.1.1.tar.xz afl-qemu-trace afl-gcc-fast afl-gcc-pass.so afl-gcc-rt.o afl-g++-fast ld *.so *.8
-	rm -rf out_dir qemu_mode/qemu-3.1.1 *.dSYM */*.dSYM
-	-$(MAKE) -C llvm_mode clean
-	-$(MAKE) -C gcc_plugin clean
-	$(MAKE) -C libdislocator clean
-	$(MAKE) -C libtokencap clean
-	$(MAKE) -C examples/socket_fuzzing clean
-	$(MAKE) -C examples/argv_fuzzing clean
-	$(MAKE) -C qemu_mode/unsigaction clean
-	$(MAKE) -C qemu_mode/libcompcov clean
-	$(MAKE) -C src/third_party/libradamsa/ clean
-	-rm -rf unicorn_mode/unicornafl
-
-distrib: all radamsa
-	-$(MAKE) -C llvm_mode
-	-$(MAKE) -C gcc_plugin
-	$(MAKE) -C libdislocator
-	$(MAKE) -C libtokencap
-	$(MAKE) -C examples/socket_fuzzing
-	$(MAKE) -C examples/argv_fuzzing
-	cd qemu_mode && sh ./build_qemu_support.sh
-	cd unicorn_mode && sh ./build_unicorn_support.sh
-
-binary-only: all radamsa
-	$(MAKE) -C libdislocator
-	$(MAKE) -C libtokencap
-	$(MAKE) -C examples/socket_fuzzing
-	$(MAKE) -C examples/argv_fuzzing
-	cd qemu_mode && sh ./build_qemu_support.sh
-	cd unicorn_mode && sh ./build_unicorn_support.sh
-
-source-only: all radamsa
-	-$(MAKE) -C llvm_mode
-	-$(MAKE) -C gcc_plugin
-	$(MAKE) -C libdislocator
-	$(MAKE) -C libtokencap
-
-%.8:	%
-	@echo .TH $* 8 $(BUILD_DATE) "afl++" > $@
-	@echo .SH NAME >> $@
-	@echo .B $* >> $@
-	@echo >> $@
-	@echo .SH SYNOPSIS >> $@
-	@./$* -h 2>&1 | head -n 3 | tail -n 1 | sed 's/^\.\///' >> $@
-	@echo >> $@
-	@echo .SH OPTIONS >> $@
-	@echo .nf >> $@
-	@./$* -hh 2>&1 | tail -n +4 >> $@
-	@echo >> $@
-	@echo .SH AUTHOR >> $@
-	@echo "afl++ was written by Michal \"lcamtuf\" Zalewski and is maintained by Marc \"van Hauser\" Heuse <mh@mh-sec.de>, Heiko \"hexcoder-\" Eissfeldt <heiko.eissfeldt@hexco.de>, Andrea Fioraldi <andreafioraldi@gmail.com> and Dominik Maier <domenukk@gmail.com>" >> $@
-	@echo  The homepage of afl++ is: https://github.com/AFLplusplus/AFLplusplus >> $@
-	@echo >> $@
-	@echo .SH LICENSE >> $@
-	@echo Apache License Version 2.0, January 2004 >> $@
-
-install: all $(MANPAGES)
-	install -d -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) $${DESTDIR}$(DOC_PATH) $${DESTDIR}$(MISC_PATH)
-	rm -f $${DESTDIR}$(BIN_PATH)/afl-plot.sh
-	install -m 755 $(PROGS) $(SH_PROGS) $${DESTDIR}$(BIN_PATH)
-	rm -f $${DESTDIR}$(BIN_PATH)/afl-as
-	if [ -f afl-qemu-trace ]; then install -m 755 afl-qemu-trace $${DESTDIR}$(BIN_PATH); fi
-	if [ -f afl-gcc-fast ]; then set e; install -m 755 afl-gcc-fast $${DESTDIR}$(BIN_PATH); ln -sf afl-gcc-fast $${DESTDIR}$(BIN_PATH)/afl-g++-fast; install -m 755 afl-gcc-pass.so afl-gcc-rt.o $${DESTDIR}$(HELPER_PATH); fi
-	$(MAKE) -C llvm_mode install
-	if [ -f libdislocator.so ]; then set -e; install -m 755 libdislocator.so $${DESTDIR}$(HELPER_PATH); fi
-	if [ -f libtokencap.so ]; then set -e; install -m 755 libtokencap.so $${DESTDIR}$(HELPER_PATH); fi
-	if [ -f libcompcov.so ]; then set -e; install -m 755 libcompcov.so $${DESTDIR}$(HELPER_PATH); fi
-	if [ -f libradamsa.so ]; then set -e; install -m 755 libradamsa.so $${DESTDIR}$(HELPER_PATH); fi
-	if [ -f afl-fuzz-document ]; then set -e; install -m 755 afl-fuzz-document $${DESTDIR}$(BIN_PATH); fi
-	$(MAKE) -C examples/socket_fuzzing install
-	$(MAKE) -C examples/argv_fuzzing install
-
-	set -e; ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-g++
-	set -e; if [ -f afl-clang-fast ] ; then ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang++ ; else ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-clang++; fi
-
-	mkdir -m 0755 -p ${DESTDIR}$(MAN_PATH)
-	install -m0644 *.8 ${DESTDIR}$(MAN_PATH)
-
-	install -m 755 afl-as $${DESTDIR}$(HELPER_PATH)
-	ln -sf afl-as $${DESTDIR}$(HELPER_PATH)/as
-	install -m 644 docs/*.md $${DESTDIR}$(DOC_PATH)
-	cp -r testcases/ $${DESTDIR}$(MISC_PATH)
-	cp -r dictionaries/ $${DESTDIR}$(MISC_PATH)
-
+all:
+	@echo please use GNU make, thanks!
diff --git a/README.md b/README.md
index 5b2995d8..e1ca5949 100644
--- a/README.md
+++ b/README.md
@@ -54,7 +54,7 @@
   
   * Win32 PE binary-only fuzzing with QEMU and Wine
 
-  * Radamsa mutator (enable with `-R` to add or `-RR` to run it exclusivly).
+  * Radamsa mutator (enable with `-R` to add or `-RR` to run it exclusively).
 
   * QBDI mode to fuzz android native libraries via QBDI framework
 
@@ -85,7 +85,7 @@
 
   (4) Only for LLVM >= 9 and not all targets compile
 
-  (5) upcoming, development in branch
+  (5) upcoming, development in the branch
 
   (6) not compatible with LTO and InsTrim modes
 
@@ -118,7 +118,7 @@
 We are happy to be part of [Google Summer of Code 2020](https://summerofcode.withgoogle.com/organizations/5100744400699392/)! :-)
 
 We have several ideas we would like to see in AFL++ to make it even better.
-However we already work on so many things that we do not have the time for
+However, we already work on so many things that we do not have the time for
 all the big ideas.
 
 This can be your way to support and contribute to AFL++ - extend it to
@@ -160,6 +160,7 @@ These build targets exist:
 * clean: cleans everything. for qemu_mode and unicorn_mode it means it deletes all downloads as well
 * code-format: format the code, do this before you commit and send a PR please!
 * tests: runs test cases to ensure that all features are still working as they should
+* unit: perform unit tests (based on cmocka)
 * help: shows these build options
 
 [Unless you are on Mac OS X](https://developer.apple.com/library/archive/qa/qa1118/_index.html) you can also build statically linked versions of the 
@@ -205,9 +206,9 @@ There have been numerous attempts to solve this problem. One of the early
 approaches - pioneered by Tavis Ormandy - is corpus distillation. The method
 relies on coverage signals to select a subset of interesting seeds from a
 massive, high-quality corpus of candidate files, and then fuzz them by
-traditional means. The approach works exceptionally well, but requires such
+traditional means. The approach works exceptionally well but requires such
 a corpus to be readily available. In addition, block coverage measurements
-provide only a very simplistic understanding of program state, and are less
+provide only a very simplistic understanding of the program state and are less
 useful for guiding the fuzzing effort in the long haul.
 
 Other, more sophisticated research has focused on techniques such as program
@@ -228,7 +229,7 @@ Simplifying a bit, the overall algorithm can be summed up as:
 
   1) Load user-supplied initial test cases into the queue,
 
-  2) Take next input file from the queue,
+  2) Take the next input file from the queue,
 
   3) Attempt to trim the test case to the smallest size that doesn't alter
      the measured behavior of the program,
@@ -259,7 +260,7 @@ superior to blind fuzzing or coverage-only tools.
 ## Instrumenting programs for use with AFL
 
 PLEASE NOTE: llvm_mode compilation with afl-clang-fast/afl-clang-fast++
-instead of afl-gcc/afl-g++ is much faster and has a few cool features.
+instead of afl-gcc/afl-g++ is much faster and has many cool features.
 See llvm_mode/ - however few code does not compile with llvm.
 We support llvm versions 3.8.0 to 11.
 
@@ -295,7 +296,7 @@ Using partial instrumentation is also recommended, see
 When testing libraries, you need to find or write a simple program that reads
 data from stdin or from a file and passes it to the tested library. In such a
 case, it is essential to link this executable against a static version of the
-instrumented library, or to make sure that the correct .so file is loaded at
+instrumented library or to make sure that the correct .so file is loaded at
 runtime (usually by setting `LD_LIBRARY_PATH`). The simplest option is a static
 build, usually possible via:
 
@@ -342,7 +343,7 @@ A more comprehensive description of these and other options can be found in
 
 ## Good examples and writeups
 
-Here are some good writeups to show how to effectibly use AFL++:
+Here are some good writeups to show how to effectively use AFL++:
 
  * [https://aflplus.plus/docs/tutorials/libxml2_tutorial/](https://aflplus.plus/docs/tutorials/libxml2_tutorial/)
  * [https://bananamafia.dev/post/gb-fuzz/](https://bananamafia.dev/post/gb-fuzz/)
@@ -372,7 +373,7 @@ The available schedules are:
  - mmopt (experimental)
  - rare (experimental)
 
-In parallel mode (-M/-S, several instances with shared queue), we suggest to
+In parallel mode (-M/-S, several instances with the shared queue), we suggest to
 run the master using the explore or fast schedule (-p explore) and the slaves
 with a combination of cut-off-exponential (-p coe), exponential (-p fast),
 explore (-p explore) and mmopt (-p mmopt) schedules. If a schedule does
@@ -380,7 +381,7 @@ not perform well for a target, restart the slave with a different schedule.
 
 In single mode, using -p fast is usually slightly more beneficial than the
 default explore mode.
-(We don't want to change the default behaviour of afl, so "fast" has not been
+(We don't want to change the default behavior of afl, so "fast" has not been
 made the default mode).
 
 More details can be found in the paper published at the 23rd ACM Conference on
@@ -450,12 +451,12 @@ See the [docs/status_screen.md](docs/status_screen.md) file for information on
 how to interpret the displayed stats and monitor the health of the process. Be
 sure to consult this file especially if any UI elements are highlighted in red.
 
-The fuzzing process will continue until you press Ctrl-C. At minimum, you want
+The fuzzing process will continue until you press Ctrl-C. At a minimum, you want
 to allow the fuzzer to complete one queue cycle, which may take anywhere from a
 couple of hours to a week or so.
 
 There are three subdirectories created within the output directory and updated
-in real time:
+in real-time:
 
   - queue/   - test cases for every distinctive execution path, plus all the
                starting files given by the user. This is the synthesized corpus
@@ -480,7 +481,7 @@ involve any state transitions not seen in previously-recorded faults. If a
 single bug can be reached in multiple ways, there will be some count inflation
 early in the process, but this should quickly taper off.
 
-The file names for crashes and hangs are correlated with parent, non-faulting
+The file names for crashes and hangs are correlated with the parent, non-faulting
 queue entries. This should help with debugging.
 
 When you can't reproduce a crash found by afl-fuzz, the most likely cause is
@@ -544,10 +545,10 @@ instrumentation feedback alone. This actually works in practice, say:
 PS. Even when no explicit dictionary is given, afl-fuzz will try to extract
 existing syntax tokens in the input corpus by watching the instrumentation
 very closely during deterministic byte flips. This works for some types of
-parsers and grammars, but isn't nearly as good as the -x mode.
+parsers and grammars but isn't nearly as good as the -x mode.
 
 If a dictionary is really hard to come by, another option is to let AFL run
-for a while, and then use the token capture library that comes as a companion
+for a while and then use the token capture library that comes as a companion
 utility with AFL. For that, see [libtokencap/README.md](libtokencap/README.tokencap.md).
 
 ## Crash triage
@@ -562,7 +563,7 @@ difficult to quickly evaluate for exploitability without a lot of debugging and
 code analysis work. To assist with this task, afl-fuzz supports a very unique
 "crash exploration" mode enabled with the -C flag.
 
-In this mode, the fuzzer takes one or more crashing test cases as the input,
+In this mode, the fuzzer takes one or more crashing test cases as the input
 and uses its feedback-driven fuzzing strategies to very quickly enumerate all
 code paths that can be reached in the program while keeping it in the
 crashing state.
@@ -601,7 +602,7 @@ near the end of [docs/technical_details.md](docs/technical_details.md).
 
 Fuzzing is a wonderful and underutilized technique for discovering non-crashing
 design and implementation errors, too. Quite a few interesting bugs have been
-found by modifying the target programs to call abort() when, say:
+found by modifying the target programs to call abort() when say:
 
   - Two bignum libraries produce different outputs when given the same
     fuzzer-generated input,
@@ -623,7 +624,7 @@ shared with libfuzzer) or `#ifdef __AFL_COMPILER` (this one is just for AFL).
 ## Common-sense risks
 
 Please keep in mind that, similarly to many other computationally-intensive
-tasks, fuzzing may put strain on your hardware and on the OS. In particular:
+tasks, fuzzing may put a strain on your hardware and on the OS. In particular:
 
   - Your CPU will run hot and will need adequate cooling. In most cases, if
     cooling is insufficient or stops working properly, CPU speeds will be
@@ -656,7 +657,7 @@ Here are some of the most important caveats for AFL:
   - AFL detects faults by checking for the first spawned process dying due to
     a signal (SIGSEGV, SIGABRT, etc). Programs that install custom handlers for
     these signals may need to have the relevant code commented out. In the same
-    vein, faults in child processed spawned by the fuzzed target may evade
+    vein, faults in child processes spawned by the fuzzed target may evade
     detection unless you manually add some code to catch that.
 
   - As with any other brute-force tool, the fuzzer offers limited coverage if
diff --git a/afl-whatsup b/afl-whatsup
index 01edb210..1a276964 100755
--- a/afl-whatsup
+++ b/afl-whatsup
@@ -122,6 +122,7 @@ fmt_duration()
 
 FIRST=true
 TOTAL_WCOP=
+TOTAL_LAST_PATH=0
 
 for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do
 
@@ -171,6 +172,10 @@ for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do
   TOTAL_PENDING=$((TOTAL_PENDING + pending_total))
   TOTAL_PFAV=$((TOTAL_PFAV + pending_favs))
 
+  if [ "$last_path" -gt "$TOTAL_LAST_PATH" ]; then
+    TOTAL_LAST_PATH=$last_path
+  fi
+
   if [ "$SUMMARY_ONLY" = "" ]; then
 
     # Warnings in red
@@ -236,6 +241,7 @@ TOTAL_DAYS=$((TOTAL_TIME / 60 / 60 / 24))
 TOTAL_HRS=$(((TOTAL_TIME / 60 / 60) % 24))
 
 test -z "$TOTAL_WCOP" && TOTAL_WCOP="not available"
+fmt_duration $TOTAL_LAST_PATH && TOTAL_LAST_PATH=$DUR_STRING
 
 test "$TOTAL_TIME" = "0" && TOTAL_TIME=1
 
@@ -262,6 +268,7 @@ fi
 
 echo "       Crashes found : $TOTAL_CRASHES locally unique"
 echo "Cycles without finds : $TOTAL_WCOP"
+echo "  Time without finds : $TOTAL_LAST_PATH"
 echo
 
 exit 0
diff --git a/dictionaries/regexp.dict b/dictionaries/regexp.dict
index 2f29357e..4e2d7a0f 100644
--- a/dictionaries/regexp.dict
+++ b/dictionaries/regexp.dict
@@ -238,362 +238,6 @@
 "\\p{Nd}"
 "\\P{Any}"
 "\\p{Changes_When_NFKC_Casefolded}"
-"L~"
-"P{scx=Greek}??"
-"Q~"
-"R??"
-"R!??oo(E=?ar)baz-"
-"Sc?Sc{?{?"
-"U~"
-"V~"
-"W~"
-"Xdtc"
-"X~"
-"X?"
-"[-123],}"
-"[-????]+,}"
-"[00011],}"
-"[011],}"
-"[0],}"
-"[1111],}"
-"[111],}"
-"[118],}"
-"[11],}"
-"[11a],}"
-"[[]{}()%^# ],}"
-"[]"
-"[],}"
-"[]{}()%^# ,}"
-"[^123],}"
-"[a-b-c],}"
-"[a-zA-Z0-9],}"
-"[b"
-"[bfoo(?!bar)baz"
-"[c!],}"
-"[c1],}"
-"[cA],}"
-"[cZ],}"
-"[c_],}"
-"[ca],}"
-"[cz],}"
-"[c~],}"
-"[c~]w"
-"[d-d],}"
-"[d-z],}"
-"[u???[11<([c?]?:u??<a>)dccc]"
-"[ud808udf45-ud809udccc],}"
-"[x"
-"[x],}"
-"[xdz],}"
-"[xyz],}"
-"[x?"
-"[x?n4n4"
-"[x??19?"
-"[z-d],}"
-"[~?"
-"[?????"
-"[?"
-"[???],}"
-"[????-????],}"
-"[????"
-"]"
-"],}"
-"]QrC[w~]Qr"
-"]}"
-"]~"
-"^?000???????????????????????????x60?"
-"^12(a(?:1(b12))2)1dyb?9"
-"^xi!q"
-"^xxx$,}"
-"abc"
-"abc60,0}?{?"
-"aic"
-"b~"
-"c"
-"c!,}"
-"c,}"
-"cA,}"
-"c_,}"
-"cjcJcicIckcK,}"
-"c~"
-"c~,}"
-"d"
-"d?"
-"d??"
-"d(?:ab[]?9}"
-"dpN?(?<a>.)?"
-"duu{123a?"
-"d{1,9"
-"d~"
-"e"
-"e~"
-"e?}"
-"f~"
-"g~"
-"h~"
-"i~"
-"j~"
-"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xx?~"
-"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxb~"
-"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxc~"
-"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxd~"
-"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxe~"
-"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxf~"
-"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxg~"
-"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxh~"
-"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxi~"
-"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxj~"
-"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxk~"
-"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxl~"
-"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxm~"
-"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxn~"
-"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxo~"
-"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxp~"
-"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxq~"
-"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxr~"
-"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxs~"
-"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxt~"
-"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxu~"
-"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxv~"
-"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxw~"
-"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxx~"
-"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxy~"
-"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxz~"
-"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xx?~"
-"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxn~"
-"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxo~"
-"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxp~"
-"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxq~"
-"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxr~"
-"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxs~"
-"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxt~"
-"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxu~"
-"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxv~"
-"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxw~"
-"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxx~"
-"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxy~"
-"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxz~"
-"k?@a(?=bbb.~"
-"k?@a(?=bbbb~"
-"k?@a(?=bbbc~"
-"k?@a(?=bbbd~"
-"k?@a(?=bbbe~"
-"k?@a(?=bbbf~"
-"k?@a(?=bbbg~"
-"k?@a(?=bbbh~"
-"k?@a(?=bbbi~"
-"k?@a(?=bbbj~"
-"k?@a(?=bbbk~"
-"k?@a(?=bbbl~"
-"k?@a(?=bbbm~"
-"k?@a(?=bbbn~"
-"k?@a(?=bbbo~"
-"k?@a(?=bbbp~"
-"k?@a(?=bbbq~"
-"k?@a(?=bbbr~"
-"k?@a(?=bbbs~"
-"k?@a(?=bbbt~"
-"k?@a(?=bbbu~"
-"k?@a(?=bbbv~"
-"k?@a(?=bbbw~"
-"k?@a(?=bbbx~"
-"k?@a(?=bbby~"
-"k?@a(?=bbbz~"
-"k?@a(?=by?bC?:!k??????????????b~"
-"k?@a(?=by?bC?:!k??????????????c~"
-"k?@a(?=by?bC?:!k??????????????d~"
-"k?@a(?=by?bC?:!k??????????????e~"
-"k?@a(?=by?bC?:!k??????????????f~"
-"k?@a(?=by?bC?:!k??????????????g~"
-"k?@a(?=by?bC?:!k??????????????h~"
-"k?@a(?=by?bC?:!k??????????????i~"
-"k?@a(?=by?bC?:!k??????????????j~"
-"k?@a(?=by?bC?:!k??????????????k~"
-"k?@a(?=by?bC?:!k??????????????l~"
-"k?@a(?=by?bC?:!k??????????????m~"
-"k?@a(?=by?bC?:!k??????????????n~"
-"k?@a(?=by?bC?:!k??????????????o~"
-"k?@a(?=by?bC?:!k??????????????p~"
-"k?@a(?=by?bC?:!k??????????????q~"
-"k?@a(?=by?bC?:!k??????????????r~"
-"k?@a(?=by?bC?:!k??????????????s~"
-"k?@a(?=by?bC?:!k??????????????t~"
-"k?@a(?=by?bC?:!k??????????????u~"
-"k?@a(?=by?bC?:!k??????????????v~"
-"k?@a(?=by?bC?:!k??????????????w~"
-"k?@a(?=by?bC?:!k??????????????x~"
-"k?@a(?=by?bC?:!k??????????????y~"
-"k?@a(?=by?bC?:!k??????????????z~"
-"k?@a(?=by?bC?:!k???????????????~"
-"k?@a(?~"
-"k?@a(b~"
-"k?@a(c~"
-"k?@a(d~"
-"k?@a(e~"
-"k?@a(f~"
-"k?@a(g~"
-"k?@a(h~"
-"k?@a(i~"
-"k?@a(j~"
-"k?@a(k~"
-"k?@a(l~"
-"k?@a(m~"
-"k?@a(n~"
-"k?@a(o~"
-"k?@a(p~"
-"k?@a(q~"
-"k?@a(r~"
-"k?@a(s~"
-"k?@a(t~"
-"k?@a(u~"
-"k?@a(v~"
-"k?@a(w~"
-"k?@a(x~"
-"k?@a(y~"
-"k?@a(z~"
-"k0X@ab~"
-"k0X@ac~"
-"k0X@ad~"
-"k0X@ae~"
-"k0X@af~"
-"k0X@ag~"
-"k0X@ah~"
-"k0X@ai~"
-"k0X@aj~"
-"k0X@ak~"
-"k0X@al~"
-"k0X@am~"
-"k0X@an~"
-"k0X@ao~"
-"k0X@ap~"
-"k0X@aq~"
-"k0X@ar~"
-"k0X@as~"
-"k0X@at~"
-"k0X@au~"
-"k0X@av~"
-"k0X@aw~"
-"k0X@ax~"
-"k0X@ay~"
-"k0X@az~"
-"k0X@a?~"
-"k~"
-"l~"
-"m~"
-"n~"
-"o~"
-"p~"
-"q,}"
-"q~"
-"r~"
-"r?[c~]"
-"s~"
-"t~"
-"u0034,}"
-"u003z,}"
-"u0060,}"
-"ud808udf45*,}"
-"u~"
-"v~"
-"w"
-"w~"
-"x3z,}"
-"x60,}"
-"xyz?9"
-"x~"
-"y~"
-"z~"
-"{"
-"{??"
-"{ ,,?"
-"{-"
-"{0,d?????!"
-"{12345}pu{234:P}?"
-"{1?5"
-"{@"
-"{M,??"
-"{M,P{scx=Greek}???sn"
-"{M,??"
-"{M,??"
-"{M,?M,??"
-"{O"
-"{r~"
-"{s~"
-"{t~"
-"{u~"
-"{v~"
-"{w~"
-"{x~"
-"{y~"
-"{z~"
-"{}"
-"{}~"
-"{??@"
-"{?~"
-"},}"
-"}}"
-"}}}}}?}!}}}}}}}}}}}}}}}}}?},}"
-"}~"
-"}?w~???"
-"~~"
-"?!~"
-"?$"
-"?*?9?nnRnnn?"
-"?.~"
-"?123222222??"
-"?:??"
-"?R"
-"?b~"
-"?c~"
-"?d~"
-"?d???"
-"?e~"
-"?f~"
-"?g~"
-"?h~"
-"?i~"
-"?j~"
-"?k~"
-"?l~"
-"?m~"
-"?n~"
-"?o~"
-"?p~"
-"?q~"
-"?r~"
-"?s~"
-"?t~"
-"?u~"
-"?v~"
-"?v~?v"
-"?w~"
-"?x~"
-"?y~"
-"?z~"
-"?}"
-"??~"
-"?????????dadi(?!bbb"
-"??~"
-"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxq~>>>>>>>>>>>>>>>>>>"
-"?f??123222222??"
-"?fP{gc=Decimal_Number}"
-"?f2jq?oo@ooooh??"
-"?[???],}f?"
-"?[???],}nbbc2jocom"
-"?[]"
-"?[],}?"
-"?[],}f?"
-"?[]f?"
-"?[]{}()%^#"
-"?[^123],}f?"
-"?[^123]nbbc2jocom"
-"?[a-b-c],}f?"
-"?[a-b-c]nbbc2jocom"
-"?[a-zA-Z0-9],}f?"
-"?[a-zA-Z0-9],}jocom"
-"?[a-zA-Z0-9]c2jocom"
-"?[bfoo(?!bar)bazcom"
-"?[bfoo(?!bar)bazf?"
 "(?:a?)??"
 "a?)"xyz{93}"
 "{93}"
@@ -601,3 +245,12 @@
 "[\x8f]"
 "[\xf0\x9f\x92\xa9-\xf4\x8f\xbf\x92\xa9-\xf4\x8f\xbf\xbf]"
 "[\x92\xa9-\xf4\x8f\xbf\xbf]"
+"\\1\\2(b\\1\\2))\\2)\\1"
+"\\1\\2(a(?:\\1\\2))\\2)\\1"
+"?:\\1"
+"\\1(b\\1\\2))\\2)\\1"
+"\\1\\2(a(?:\\1(b\\1\\2))\\2)\\1"
+"foo(?=bar)bar)baz"
+"fo(?o(?o(?o(?=bar)baz"
+"foo(?=bar)baz"
+"foo(?=bar)bar)az"
diff --git a/docs/Changelog.md b/docs/Changelog.md
index 6af269ce..72336b11 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -16,12 +16,15 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
   ! development and acceptance of PRs now happen only in the dev branch
     and only occasionally when everything is fine we PR to master
   - all:
-    - big code changes to make afl-fuzz thread-safe so afl-fuzz can spawn 
+    - big code changes to make afl-fuzz thread-safe so afl-fuzz can spawn
       multiple fuzzing threads in the future or even become a library
     - afl basic tools now report on the environment variables picked up
     - more tools get environment variable usage info in the help output
     - force all output to stdout (some OK/SAY/WARN messages were sent to
       stdout, some to stderr)
+    - uninstrumented mode uses an internal forkserver ("fauxserver")
+    - now builds with `-D_FORTIFY_SOURCE=2`
+    - drastically reduced number of (de)allocations during fuzzing
   - afl-fuzz:
     - python mutator modules and custom mutator modules now use the same
       interface and hence the API changed
@@ -31,13 +34,14 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
                the last 5 queue entries
       - rare: puts focus on queue entries that hits rare branches, also ignores
               runtime
+  - llvm_mode: added Control Flow Integrity sanitizer (AFL_USE_CFISAN)
   - LTO collision free instrumented added in llvm_mode with afl-clang-lto -
     note that this mode is amazing, but quite some targets won't compile
   - Added llvm_mode NGRAM prev_loc coverage by Adrean Herrera
     (https://github.com/adrianherrera/afl-ngram-pass/), activate by setting
     AFL_LLVM_NGRAM_SIZE
   - llvm_mode InsTrim mode:
-    - removed workaround for bug where paths were not instrumented and 
+    - removed workaround for bug where paths were not instrumented and
       imported fix by author
     - made skipping 1 block functions an option and is disable by default,
       set AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK=1 to re-enable this
@@ -202,7 +206,7 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
 
   - big code refactoring:
     * all includes are now in include/
-    * all afl sources are now in src/ - see src/README.src
+    * all afl sources are now in src/ - see src/README.md
     * afl-fuzz was splitted up in various individual files for including
       functionality in other programs (e.g. forkserver, memory map, etc.)
       for better readability.
diff --git a/docs/custom_mutators.md b/docs/custom_mutators.md
index 14d8f518..49ce761e 100644
--- a/docs/custom_mutators.md
+++ b/docs/custom_mutators.md
@@ -27,18 +27,16 @@ performed with the custom mutator.
 
 C/C++:
 ```c
-void afl_custom_init(unsigned int seed);
-size_t afl_custom_fuzz(uint8_t** buf, size_t buf_size, uint8_t* add_buf,
-                       size_t add_buf_size, size_t max_size);
-size_t afl_custom_pre_save(uint8_t* buf, size_t buf_size, uint8_t** out_buf);
-uint32_t afl_custom_init_trim(uint8_t* buf, size_t buf_size);
-void afl_custom_trim(uint8_t** out_buf, size_t* out_buf_size);
-uint32_t afl_custom_post_trim(uint8_t success);
-size_t afl_custom_havoc_mutation(uint8_t** buf, size_t buf_size, size_t max_size);
-uint8_t afl_custom_havoc_mutation_probability(void);
-uint8_t afl_custom_queue_get(const uint8_t* filename);
-void afl_custom_queue_new_entry(const uint8_t* filename_new_queue,
-                                const uint8_t* filename_orig_queue);
+void *afl_custom_init(afl_t *afl, unsigned int seed);
+size_t afl_custom_fuzz(void *data, uint8_t *buf, size_t buf_size, u8 **out_buf, uint8_t *add_buf, size_t add_buf_size, size_t max_size);
+size_t afl_custom_pre_save(void *data, uint8_t *buf, size_t buf_size, uint8_t **out_buf);
+int32_t afl_custom_init_trim(void *data, uint8_t *buf, size_t buf_size);
+size_t afl_custom_trim(void *data, uint8_t **out_buf);
+int32_t afl_custom_post_trim(void *data, int success) {
+size_t afl_custom_havoc_mutation(void *data, u8 *buf, size_t buf_size, u8 **out_buf, size_t max_size);
+uint8_t afl_custom_havoc_mutation_probability(void *data);
+uint8_t afl_custom_queue_get(void *data, const uint8_t *filename); void afl_custom_queue_new_entry(void *data, const uint8_t *filename_new_queue, const uint8_t *filename_orig_queue);
+void afl_custom_deinit(void *data);
 ```
 
 Python:
@@ -76,9 +74,9 @@ def queue_new_entry(filename_new_queue, filename_orig_queue):
 
 ### Custom Mutation
 
-- `init` (optional):
+- `init`:
 
-    This method is called when AFL++ starts up and is used to seed RNG.
+    This method is called when AFL++ starts up and is used to seed RNG and set up buffers and state.
 
 - `queue_get` (optional):
 
@@ -110,7 +108,7 @@ def queue_new_entry(filename_new_queue, filename_orig_queue):
 
 - `queue_new_entry` (optional):
 
-    This methods is called after adding a new test case to the queue. 
+    This methods is called after adding a new test case to the queue.
 
 ### Trimming Support
 
@@ -144,7 +142,7 @@ trimmed input. Here's a quick API description:
 
     This method is called for each trimming operation. It doesn't have any
     arguments because we already have the initial buffer from `init_trim` and we
-    can memorize the current state in global variables. This can also save
+    can memorize the current state in the data variables. This can also save
     reparsing steps for each iteration. It should return the trimmed input
     buffer, where the returned data must not exceed the initial input data in
     length. Returning anything that is larger than the original data (passed to
@@ -158,6 +156,8 @@ trimmed input. Here's a quick API description:
     In any case, this method must return the next trim iteration index (from 0
     to the maximum amount of steps you returned in `init_trim`).
 
+`deinit` the last method to be called, deinitializing the state.
+
 Omitting any of three methods will cause the trimming to be disabled and trigger
 a fallback to the builtin default trimming routine.
 
@@ -166,7 +166,7 @@ a fallback to the builtin default trimming routine.
 Optionally, the following environment variables are supported:
 
 - `AFL_CUSTOM_MUTATOR_ONLY`
- 
+
     Disable all other mutation stages. This can prevent broken testcases
     (those that your Python module can't work with anymore) to fill up your
     queue. Best combined with a custom trimming routine (see below) because
diff --git a/docs/env_variables.md b/docs/env_variables.md
index 98f27bdf..ae283b1c 100644
--- a/docs/env_variables.md
+++ b/docs/env_variables.md
@@ -31,7 +31,9 @@ tools make fairly broad use of environmental variables:
 
     (You can also enable MSAN via AFL_USE_MSAN; ASAN and MSAN come with the
     same gotchas; the modes are mutually exclusive. UBSAN can be enabled
-    similarly by setting the environment variable AFL_USE_UBSAN=1)
+    similarly by setting the environment variable AFL_USE_UBSAN=1. Finally
+    there is the Control Flow Integrity sanitizer that can be activated by
+    AFL_USE_CFISAN=1)
 
   - Setting AFL_CC, AFL_CXX, and AFL_AS lets you use alternate downstream
     compilation tools, rather than the default 'clang', 'gcc', or 'as' binaries
diff --git a/docs/notes_for_asan.md b/docs/notes_for_asan.md
index b65873be..6a4806c0 100644
--- a/docs/notes_for_asan.md
+++ b/docs/notes_for_asan.md
@@ -29,7 +29,7 @@ Note that ASAN is incompatible with -static, so be mindful of that.
 (You can also use AFL_USE_MSAN=1 to enable MSAN instead.)
 
 NOTE: if you run several slaves only one should run the target compiled with
-ASAN (and UBSAN), the others should run the target with no sanitizers
+ASAN (and UBSAN, CFISAN), the others should run the target with no sanitizers
 compiled in.
 
 There is also the option of generating a corpus using a non-ASAN binary, and
diff --git a/examples/README.md b/examples/README.md
index 37fae1a0..3c5aa9f2 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -2,9 +2,7 @@
 
 Here's a quick overview of the stuff you can find in this directory:
 
-  - custom_mutstors      - An example custom mutator
-  
-  - python_mutators      - Python mutators examples
+  - custom_mutators      - example custom mutators in python an c
 
   - argv_fuzzing         - a simple wrapper to allow cmdline to be fuzzed
                            (e.g., to test setuid programs).
@@ -15,8 +13,8 @@ Here's a quick overview of the stuff you can find in this directory:
   - bash_shellshock      - a simple hack used to find a bunch of
                            post-Shellshock bugs in bash.
 
-  - canvas_harness       - a test harness used to find browser bugs with a 
-                           corpus generated using simple image parsing 
+  - canvas_harness       - a test harness used to find browser bugs with a
+                           corpus generated using simple image parsing
                            binaries & afl-fuzz.
 
   - clang_asm_normalize  - a script that makes it easy to instrument
@@ -34,7 +32,7 @@ Here's a quick overview of the stuff you can find in this directory:
                            mode to speed up certain fuzzing jobs.
 
   - post_library         - an example of how to build postprocessors for AFL.
-  
+
   - socket_fuzzing       - a LD_PRELOAD library 'redirects' a socket to stdin
                            for fuzzing access with afl++
 
diff --git a/examples/argv_fuzzing/GNUmakefile b/examples/argv_fuzzing/GNUmakefile
new file mode 100644
index 00000000..34192e39
--- /dev/null
+++ b/examples/argv_fuzzing/GNUmakefile
@@ -0,0 +1,51 @@
+#
+# american fuzzy lop++ - argvfuzz
+# --------------------------------
+#
+# Copyright 2019-2020 Kjell Braden <afflux@pentabarf.de>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+
+.PHONY: all install clean
+
+PREFIX     ?= /usr/local
+BIN_PATH    = $(PREFIX)/bin
+HELPER_PATH = $(PREFIX)/lib/afl
+
+CFLAGS = -fPIC -Wall -Wextra
+LDFLAGS = -shared
+
+ifneq "$(filter Linux GNU%,$(shell uname))" ""
+  LDFLAGS  += -ldl
+endif
+
+# on gcc for arm there is no -m32, but -mbe32
+M32FLAG = -m32
+M64FLAG = -m64
+ifeq "$(findstring clang, $(shell $(CC) --version 2>/dev/null))" ""
+ ifneq (,$(findstring arm, "$(shell $(CC) -v 2>&1 >/dev/null)"))
+  M32FLAG = -mbe32
+ endif
+endif
+
+
+all: argvfuzz32.so argvfuzz64.so
+
+argvfuzz32.so: argvfuzz.c
+	-$(CC) $(M32FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ || echo "argvfuzz32 build failure (that's fine)"
+
+argvfuzz64.so: argvfuzz.c
+	-$(CC) $(M64FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ || echo "argvfuzz64 build failure (that's fine)"
+
+install: argvfuzz32.so argvfuzz64.so
+	install -d -m 755 $(DESTDIR)$(HELPER_PATH)/
+	if [ -f argvfuzz32.so ]; then set -e; install -m 755 argvfuzz32.so $(DESTDIR)$(HELPER_PATH)/; fi
+	if [ -f argvfuzz64.so ]; then set -e; install -m 755 argvfuzz64.so $(DESTDIR)$(HELPER_PATH)/; fi
+
+clean:
+	rm -f argvfuzz32.so argvfuzz64.so
diff --git a/examples/argv_fuzzing/Makefile b/examples/argv_fuzzing/Makefile
index 34192e39..0b306dde 100644
--- a/examples/argv_fuzzing/Makefile
+++ b/examples/argv_fuzzing/Makefile
@@ -1,51 +1,2 @@
-#
-# american fuzzy lop++ - argvfuzz
-# --------------------------------
-#
-# Copyright 2019-2020 Kjell Braden <afflux@pentabarf.de>
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-
-.PHONY: all install clean
-
-PREFIX     ?= /usr/local
-BIN_PATH    = $(PREFIX)/bin
-HELPER_PATH = $(PREFIX)/lib/afl
-
-CFLAGS = -fPIC -Wall -Wextra
-LDFLAGS = -shared
-
-ifneq "$(filter Linux GNU%,$(shell uname))" ""
-  LDFLAGS  += -ldl
-endif
-
-# on gcc for arm there is no -m32, but -mbe32
-M32FLAG = -m32
-M64FLAG = -m64
-ifeq "$(findstring clang, $(shell $(CC) --version 2>/dev/null))" ""
- ifneq (,$(findstring arm, "$(shell $(CC) -v 2>&1 >/dev/null)"))
-  M32FLAG = -mbe32
- endif
-endif
-
-
-all: argvfuzz32.so argvfuzz64.so
-
-argvfuzz32.so: argvfuzz.c
-	-$(CC) $(M32FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ || echo "argvfuzz32 build failure (that's fine)"
-
-argvfuzz64.so: argvfuzz.c
-	-$(CC) $(M64FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ || echo "argvfuzz64 build failure (that's fine)"
-
-install: argvfuzz32.so argvfuzz64.so
-	install -d -m 755 $(DESTDIR)$(HELPER_PATH)/
-	if [ -f argvfuzz32.so ]; then set -e; install -m 755 argvfuzz32.so $(DESTDIR)$(HELPER_PATH)/; fi
-	if [ -f argvfuzz64.so ]; then set -e; install -m 755 argvfuzz64.so $(DESTDIR)$(HELPER_PATH)/; fi
-
-clean:
-	rm -f argvfuzz32.so argvfuzz64.so
+all:
+	@echo please use GNU make, thanks!
diff --git a/examples/custom_mutators/Makefile b/examples/custom_mutators/Makefile
index a83e87fe..9849f3f4 100644
--- a/examples/custom_mutators/Makefile
+++ b/examples/custom_mutators/Makefile
@@ -1,2 +1,7 @@
-all:
-	$(CC) $(CFLAGS) -fPIC -shared -g -I ../../include example.c -o libexamplemutator.so
+all: libexamplemutator.so
+
+libexamplemutator.so:
+	$(CC) $(CFLAGS) -D_FORTIFY_SOURCE=2 -O3 -fPIC -shared -g -I ../../include example.c -o libexamplemutator.so
+
+clean:
+	rm -rf libexamplemutator.so
diff --git a/examples/custom_mutators/README.md b/examples/custom_mutators/README.md
index 32acbd30..6fc7be6c 100644
--- a/examples/custom_mutators/README.md
+++ b/examples/custom_mutators/README.md
@@ -1,10 +1,10 @@
 # Examples for the custom mutator
 
 These are example and helper files for the custom mutator feature.
-See [docs/python_mutators.md](../docs/custom_mutators.md) for more information
+See [docs/custom_mutators.md](../docs/custom_mutators.md) for more information
 
 Note that if you compile with python3.7 you must use python3 scripts, and if
-you use pyton2.7 to compile python2 scripts!
+you use python2.7 to compile python2 scripts!
 
 example.c - this is a simple example written in C and should be compiled to a
           shared library. Use make to compile it and produce libexamplemutator.so
diff --git a/examples/custom_mutators/custom_mutator_helpers.h b/examples/custom_mutators/custom_mutator_helpers.h
index 844ccf94..0848321f 100644
--- a/examples/custom_mutators/custom_mutator_helpers.h
+++ b/examples/custom_mutators/custom_mutator_helpers.h
@@ -5,13 +5,25 @@
 #include "types.h"
 #include <stdlib.h>
 
+#define INITIAL_GROWTH_SIZE (64)
+
 #define RAND_BELOW(limit) (rand() % (limit))
 
-typedef struct{} afl_t;
+/* 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
+
+typedef struct {
+
+} afl_t;
 
 static void surgical_havoc_mutate(u8 *out_buf, s32 begin, s32 end) {
 
-  static s8  interesting_8[]  = {INTERESTING_8};
+  static s8  interesting_8[] = {INTERESTING_8};
   static s16 interesting_16[] = {INTERESTING_8, INTERESTING_16};
   static s32 interesting_32[] = {INTERESTING_8, INTERESTING_16, INTERESTING_32};
 
@@ -111,8 +123,8 @@ static void surgical_havoc_mutate(u8 *out_buf, s32 begin, s32 end) {
               (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)]);
+          *(u64 *)(out_buf + byte_idx) = SWAP64(
+              (s64)interesting_32[RAND_BELOW(sizeof(interesting_32) >> 2)]);
           break;
 
       }
@@ -265,4 +277,66 @@ static void surgical_havoc_mutate(u8 *out_buf, s32 begin, s32 end) {
 
 }
 
+/* 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 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/examples/custom_mutators/example.c b/examples/custom_mutators/example.c
index 560a5919..c8200b26 100644
--- a/examples/custom_mutators/example.c
+++ b/examples/custom_mutators/example.c
@@ -12,6 +12,7 @@
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
+#include <stdio.h>
 
 #define DATA_SIZE (100)
 
@@ -23,32 +24,47 @@ static const char *commands[] = {
 
 };
 
-
 typedef struct my_mutator {
 
   afl_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, pre_save);
 
 } my_mutator_t;
 
 /**
  * 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.
+ * @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!
- *         Returns NULL on error.
+ *         Return NULL on error.
  */
 my_mutator_t *afl_custom_init(afl_t *afl, unsigned int seed) {
 
-  srand(seed); // needed also by surgical_havoc_mutate()
+  srand(seed);  // needed also by surgical_havoc_mutate()
 
   my_mutator_t *data = calloc(1, sizeof(my_mutator_t));
   if (!data) {
+
     perror("afl_custom_init alloc");
     return NULL;
+
   }
+
   data->afl = afl;
 
   return data;
@@ -63,14 +79,16 @@ my_mutator_t *afl_custom_init(afl_t *afl, unsigned int seed) {
  * @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(my_mutator_t *data, uint8_t **buf, size_t buf_size,
-                       uint8_t *add_buf,
+size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
+                       u8 **out_buf, uint8_t *add_buf,
                        size_t add_buf_size,  // add_buf can be NULL
                        size_t max_size) {
 
@@ -78,9 +96,15 @@ 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;
 
-  if (mutated_size > buf_size) *buf = realloc(*buf, mutated_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) {
 
-  uint8_t *mutated_out = *buf;
+    *out_buf = NULL;
+    perror("custom mutator allocation (maybe_grow)");
+    return 0;            /* afl-fuzz will very likely error out after this. */
+
+  }
 
   // Randomly select a command string to add as a header to the packet
   memcpy(mutated_out, commands[rand() % 3], 3);
@@ -94,6 +118,7 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t **buf, size_t buf_size,
 
   }
 
+  *out_buf = mutated_out;
   return mutated_size;
 
 }
@@ -109,28 +134,35 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t **buf, size_t buf_size,
  * @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. AFL++
- *     will release the memory after saving the test case.
- * @return Size of the output buffer after processing
+ *     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_pre_save(my_mutator_t *data, uint8_t *buf, size_t buf_size, uint8_t **out_buf) {
+size_t afl_custom_pre_save(my_mutator_t *data, uint8_t *buf, size_t buf_size,
+                           uint8_t **out_buf) {
+
+  uint8_t *pre_save_buf = maybe_grow(BUF_PARAMS(data, pre_save), buf_size + 5);
+  if (!pre_save_buf) {
 
-  size_t out_buf_size;
+    perror("custom mutator realloc failed.");
+    *out_buf = NULL;
+    return 0;
 
-  out_buf_size = buf_size;
+  }
 
-  // External mutator should allocate memory for `out_buf`
-  *out_buf = malloc(out_buf_size);
-  memcpy(*out_buf, buf, out_buf_size);
+  memcpy(pre_save_buf + 5, buf, buf_size);
+  pre_save_buf[0] = 'A';
+  pre_save_buf[1] = 'F';
+  pre_save_buf[2] = 'L';
+  pre_save_buf[3] = '+';
+  pre_save_buf[4] = '+';
 
-  return out_buf_size;
+  *out_buf = pre_save_buf;
 
-}
+  return buf_size + 5;
 
-static uint8_t *trim_buf;
-static size_t   trim_buf_size;
-static int      trimmming_steps;
-static int      cur_step;
+}
 
 /**
  * This method is called at the start of each trimming operation and receives
@@ -151,25 +183,36 @@ static int      cur_step;
  * @param data pointer returned in afl_custom_init for this fuzz case
  * @param buf Buffer containing the test case
  * @param buf_size Size of the test case
- * @return The amount of possible iteration steps to trim the input
+ * @return The amount of possible iteration steps to trim the input.
+ *        negative on error.
  */
-int afl_custom_init_trim(my_mutator_t *data, uint8_t *buf, size_t buf_size) {
+int32_t afl_custom_init_trim(my_mutator_t *data, uint8_t *buf,
+                             size_t buf_size) {
 
   // We simply trim once
-  trimmming_steps = 1;
+  data->trimmming_steps = 1;
 
-  cur_step = 0;
-  trim_buf = buf;
-  trim_buf_size = buf_size;
+  data->cur_step = 0;
 
-  return trimmming_steps;
+  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;
+
+  return data->trimmming_steps;
 
 }
 
 /**
  * This method is called for each trimming operation. It doesn't have any
  * arguments because we already have the initial buffer from init_trim and we
- * can memorize the current state in global variables. This can also save
+ * can memorize the current state in *data. This can also save
  * reparsing steps for each iteration. It should return the trimmed input
  * buffer, where the returned data must not exceed the initial input data in
  * length. Returning anything that is larger than the original data (passed
@@ -179,18 +222,18 @@ int afl_custom_init_trim(my_mutator_t *data, uint8_t *buf, size_t buf_size) {
  *
  * @param[in] data pointer returned in afl_custom_init for this fuzz case
  * @param[out] out_buf Pointer to the buffer containing the trimmed test case.
- *     External library should allocate memory for out_buf. AFL++ will release
- *     the memory after saving the test case.
- * @param[out] out_buf_size Pointer to the size of the trimmed test case
+ *     External library should allocate memory for out_buf.
+ *     AFL++ will not release the memory after saving the test case.
+ *     Keep a ref in *data.
+ *     *out_buf = NULL is treated as error.
+ * @return Pointer to the size of the trimmed test case
  */
-void afl_custom_trim(my_mutator_t *data, uint8_t **out_buf, size_t *out_buf_size) {
+size_t afl_custom_trim(my_mutator_t *data, uint8_t **out_buf) {
 
-  *out_buf_size = trim_buf_size - 1;
+  *out_buf = data->trim_buf;
 
-  // External mutator should allocate memory for `out_buf`
-  *out_buf = malloc(*out_buf_size);
   // Remove the last byte of the trimming input
-  memcpy(*out_buf, trim_buf, *out_buf_size);
+  return data->trim_size_current - 1;
 
 }
 
@@ -204,18 +247,18 @@ void afl_custom_trim(my_mutator_t *data, uint8_t **out_buf, size_t *out_buf_size
  * @param[in] data pointer returned in afl_custom_init for this fuzz case
  * @param success Indicates if the last trim operation was successful.
  * @return The next trim iteration index (from 0 to the maximum amount of
- *     steps returned in init_trim)
+ *     steps returned in init_trim). negative ret on failure.
  */
-int afl_custom_post_trim(my_mutator_t *data, int success) {
+int32_t afl_custom_post_trim(my_mutator_t *data, int success) {
 
   if (success) {
 
-    ++cur_step;
-    return cur_step;
+    ++data->cur_step;
+    return data->cur_step;
 
   }
 
-  return trimmming_steps;
+  return data->trimmming_steps;
 
 }
 
@@ -226,26 +269,40 @@ int afl_custom_post_trim(my_mutator_t *data, int success) {
  * (Optional)
  *
  * @param[in] data pointer returned in afl_custom_init for this fuzz case
- * @param[inout] buf Pointer to the input data to be mutated and the mutated
+ * @param[in] buf Pointer to the input data to be mutated and the mutated
  *     output
  * @param[in] buf_size Size of input data
+ * @param[out] out_buf The output buffer. buf can be reused, if the content
+ * fits. *out_buf = NULL is treated as error.
  * @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_havoc_mutation(my_mutator_t *data, uint8_t **buf, size_t buf_size,
-                                 size_t max_size) {
+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) {
 
-    *buf = realloc(*buf, 1);
-    **buf = rand() % 256;
+    *out_buf = maybe_grow(BUF_PARAMS(data, havoc), 1);
+    if (!*out_buf) {
+
+      perror("custom havoc: maybe_grow");
+      return 0;
+
+    }
+
+    **out_buf = rand() % 256;
     buf_size = 1;
 
+  } else {
+
+    // We reuse buf here. It's legal and faster.
+    *out_buf = buf;
+
   }
 
   size_t victim = rand() % buf_size;
-  (*buf)[victim] += rand() % 10;
+  (*out_buf)[victim] += rand() % 10;
 
   return buf_size;
 
@@ -292,7 +349,8 @@ uint8_t afl_custom_queue_get(my_mutator_t *data, const uint8_t *filename) {
  * @param filename_new_queue File name of the new queue entry
  * @param filename_orig_queue File name of the original queue entry
  */
-void afl_custom_queue_new_entry(my_mutator_t *data, const uint8_t *filename_new_queue,
+void afl_custom_queue_new_entry(my_mutator_t * data,
+                                const uint8_t *filename_new_queue,
                                 const uint8_t *filename_orig_queue) {
 
   /* Additional analysis on the original or new test case */
@@ -306,6 +364,11 @@ void afl_custom_queue_new_entry(my_mutator_t *data, const uint8_t *filename_new_
  */
 void afl_custom_deinit(my_mutator_t *data) {
 
+  free(data->pre_save_buf);
+  free(data->havoc_buf);
+  free(data->data_buf);
+  free(data->fuzz_buf);
+  free(data->trim_buf);
   free(data);
 
 }
diff --git a/examples/custom_mutators/example.py b/examples/custom_mutators/example.py
index 6bacfa05..9e95eed6 100644
--- a/examples/custom_mutators/example.py
+++ b/examples/custom_mutators/example.py
@@ -17,6 +17,13 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
 import random
 
 
+COMMANDS = [
+    b"GET",
+    b"PUT",
+    b"DEL",
+]
+
+
 def init(seed):
     '''
     Called once when AFLFuzz starts up. Used to seed our RNG.
@@ -27,6 +34,10 @@ def init(seed):
     random.seed(seed)
 
 
+def deinit():
+    pass
+
+
 def fuzz(buf, add_buf, max_size):
     '''
     Called per fuzzing iteration.
@@ -44,8 +55,9 @@ def fuzz(buf, add_buf, max_size):
     @rtype: bytearray
     @return: A new bytearray containing the mutated data
     '''
-    ret = bytearray(buf)
-    # Do something interesting with ret
+    ret = bytearray(100)
+
+    ret[:3] = random.choice(COMMANDS)
 
     return ret
 
@@ -164,11 +176,10 @@ def fuzz(buf, add_buf, max_size):
 #     '''
 #     Called after adding a new test case to the queue
 #
-#     @type filename_new_queue: str 
+#     @type filename_new_queue: str
 #     @param filename_new_queue: File name of the new queue entry
 #
 #     @type filename_orig_queue: str
 #     @param filename_orig_queue: File name of the original queue entry
 #     '''
 #     pass
-
diff --git a/examples/post_library/post_library.so.c b/examples/post_library/post_library.so.c
index 5d2685cd..0aa780cb 100644
--- a/examples/post_library/post_library.so.c
+++ b/examples/post_library/post_library.so.c
@@ -3,6 +3,7 @@
    --------------------------------------------------
 
    Originally written by Michal Zalewski
+   Edited by Dominik Maier, 2020
 
    Copyright 2015 Google Inc. All rights reserved.
 
@@ -41,22 +42,23 @@
    AFL will call the afl_postprocess() function for every mutated output buffer.
    From there, you have three choices:
 
-   1) If you don't want to modify the test case, simply return the original
-      buffer pointer ('in_buf').
+   1) If you don't want to modify the test case, simply set `*out_buf = in_buf`
+      and return the original `len`.
 
    2) If you want to skip this test case altogether and have AFL generate a
-      new one, return NULL. Use this sparingly - it's faster than running
-      the target program with patently useless inputs, but still wastes CPU
-      time.
+      new one, return 0 or set `*out_buf = NULL`.
+      Use this sparingly - it's faster than running the target program
+      with patently useless inputs, but still wastes CPU time.
 
    3) If you want to modify the test case, allocate an appropriately-sized
       buffer, move the data into that buffer, make the necessary changes, and
-      then return the new pointer. You can update *len if necessary, too.
+      then return the new pointer as out_buf. Return an appropriate len
+   afterwards.
 
       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).
 
-      *** DO NOT MODIFY THE ORIGINAL 'in_buf' BUFFER. ***
+      *** Feel free to reuse the original 'in_buf' BUFFER and return it. ***
 
     Aight. The example below shows a simple postprocessor that tries to make
     sure that all input files start with "GIF89a".
@@ -74,47 +76,84 @@
 
 #define HEADER "GIF89a"
 
-/* The actual postprocessor routine called by afl-fuzz: */
+typedef struct post_state {
+
+  unsigned char *buf;
+  size_t         size;
+
+} post_state_t;
+
+void *afl_postprocess_init(void *afl) {
+
+  post_state_t *state = malloc(sizeof(post_state_t));
+  if (!state) {
+
+    perror("malloc");
+    return NULL;
+
+  }
+
+  state->buf = calloc(sizeof(unsigned char), 4096);
+  if (!state->buf) { return NULL; }
+
+  return state;
+
+}
 
-const unsigned char *afl_postprocess(const unsigned char *in_buf,
-                                     unsigned int *       len) {
+/* The actual postprocessor routine called by afl-fuzz: */
 
-  static unsigned char *saved_buf;
-  unsigned char *       new_buf;
+size_t afl_postprocess(post_state_t *data, unsigned char *in_buf,
+                       unsigned int len, unsigned char **out_buf) {
 
   /* Skip execution altogether for buffers shorter than 6 bytes (just to
-     show how it's done). We can trust *len to be sane. */
+     show how it's done). We can trust len to be sane. */
 
-  if (*len < strlen(HEADER)) return NULL;
+  if (len < strlen(HEADER)) return 0;
 
   /* Do nothing for buffers that already start with the expected header. */
 
-  if (!memcmp(in_buf, HEADER, strlen(HEADER))) return in_buf;
+  if (!memcmp(in_buf, HEADER, strlen(HEADER))) {
+
+    *out_buf = in_buf;
+    return len;
+
+  }
 
   /* Allocate memory for new buffer, reusing previous allocation if
      possible. */
 
-  new_buf = realloc(saved_buf, *len);
+  *out_buf = realloc(data->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 (!new_buf) return in_buf;
-  saved_buf = new_buf;
+  if (!*out_buf) {
+
+    *out_buf = in_buf;
+    return len;
+
+  }
 
   /* Copy the original data to the new location. */
 
-  memcpy(new_buf, in_buf, *len);
+  memcpy(*out_buf, in_buf, len);
 
   /* Insert the new header. */
 
-  memcpy(new_buf, HEADER, strlen(HEADER));
+  memcpy(*out_buf, HEADER, strlen(HEADER));
+
+  /* Return the new len. It hasn't changed, so it's just len. */
+
+  return len;
+
+}
 
-  /* Return modified buffer. No need to update *len in this particular case,
-     as we're not changing it. */
+/* Gets called afterwards */
+void afl_postprocess_deinit(post_state_t *data) {
 
-  return new_buf;
+  free(data->buf);
+  free(data);
 
 }
 
diff --git a/examples/post_library/post_library_png.so.c b/examples/post_library/post_library_png.so.c
index 60ab318f..41ba4f5e 100644
--- a/examples/post_library/post_library_png.so.c
+++ b/examples/post_library/post_library_png.so.c
@@ -5,6 +5,7 @@
    Originally written by Michal Zalewski
 
    Copyright 2015 Google Inc. All rights reserved.
+   Adapted to the new API, 2020 by Dominik Maier
 
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
@@ -35,11 +36,32 @@
 
 #define UP4K(_i) ((((_i) >> 12) + 1) << 12)
 
-const unsigned char *afl_postprocess(const unsigned char *in_buf,
-                                     unsigned int *       len) {
+typedef struct post_state {
 
-  static unsigned char *saved_buf;
-  static unsigned int   saved_len;
+  unsigned char *buf;
+  size_t         size;
+
+} post_state_t;
+
+void *afl_postprocess_init(void *afl) {
+
+  post_state_t *state = malloc(sizeof(post_state_t));
+  if (!state) {
+
+    perror("malloc");
+    return NULL;
+
+  }
+
+  state->buf = calloc(sizeof(unsigned char), 4096);
+  if (!state->buf) { return NULL; }
+
+  return state;
+
+}
+
+size_t afl_postprocess(post_state_t *data, const unsigned char *in_buf,
+                       unsigned int len, const unsigned char **out_buf) {
 
   unsigned char *new_buf = (unsigned char *)in_buf;
   unsigned int   pos = 8;
@@ -47,12 +69,17 @@ const unsigned char *afl_postprocess(const unsigned char *in_buf,
   /* Don't do anything if there's not enough room for the PNG header
      (8 bytes). */
 
-  if (*len < 8) return in_buf;
+  if (len < 8) {
+
+    *out_buf = in_buf;
+    return len;
+
+  }
 
   /* Minimum size of a zero-length PNG chunk is 12 bytes; if we
      don't have that, we can bail out. */
 
-  while (pos + 12 <= *len) {
+  while (pos + 12 <= len) {
 
     unsigned int chunk_len, real_cksum, file_cksum;
 
@@ -62,7 +89,7 @@ const unsigned char *afl_postprocess(const unsigned char *in_buf,
 
     /* Bail out if chunk size is too big or goes past EOF. */
 
-    if (chunk_len > 1024 * 1024 || pos + 12 + chunk_len > *len) break;
+    if (chunk_len > 1024 * 1024 || pos + 12 + chunk_len > len) break;
 
     /* Chunk checksum is calculated for chunk ID (dword) and the actual
        payload. */
@@ -82,17 +109,23 @@ const unsigned char *afl_postprocess(const unsigned char *in_buf,
 
       if (new_buf == in_buf) {
 
-        if (*len <= saved_len) {
+        if (len <= data->size) {
 
-          new_buf = saved_buf;
+          new_buf = data->buf;
 
         } else {
 
-          new_buf = realloc(saved_buf, UP4K(*len));
-          if (!new_buf) return in_buf;
-          saved_buf = new_buf;
-          saved_len = UP4K(*len);
-          memcpy(new_buf, in_buf, *len);
+          new_buf = realloc(data->buf, UP4K(len));
+          if (!new_buf) {
+
+            *out_buf = in_buf;
+            return len;
+
+          }
+
+          data->buf = new_buf;
+          data->size = UP4K(len);
+          memcpy(new_buf, in_buf, len);
 
         }
 
@@ -108,7 +141,16 @@ const unsigned char *afl_postprocess(const unsigned char *in_buf,
 
   }
 
-  return new_buf;
+  *out_buf = new_buf;
+  return len;
+
+}
+
+/* Gets called afterwards */
+void afl_postprocess_deinit(post_state_t *data) {
+
+  free(data->buf);
+  free(data);
 
 }
 
diff --git a/examples/socket_fuzzing/GNUmakefile b/examples/socket_fuzzing/GNUmakefile
new file mode 100644
index 00000000..ad921664
--- /dev/null
+++ b/examples/socket_fuzzing/GNUmakefile
@@ -0,0 +1,48 @@
+#
+# american fuzzy lop++ - socket_fuzz
+# ----------------------------------
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+
+.PHONY: all install clean
+
+PREFIX     ?= /usr/local
+BIN_PATH    = $(PREFIX)/bin
+HELPER_PATH = $(PREFIX)/lib/afl
+
+CFLAGS = -fPIC -Wall -Wextra
+LDFLAGS = -shared
+
+ifneq "$(filter Linux GNU%,$(shell uname))" ""
+  LDFLAGS  += -ldl
+endif
+
+# on gcc for arm there is no -m32, but -mbe32
+M32FLAG = -m32
+M64FLAG = -m64
+ifeq "$(findstring clang, $(shell $(CC) --version 2>/dev/null))" ""
+ ifneq (,$(findstring arm, "$(shell $(CC) -v 2>&1 >/dev/null)"))
+  M32FLAG = -mbe32
+ endif
+endif
+
+all: socketfuzz32.so socketfuzz64.so
+
+socketfuzz32.so: socketfuzz.c
+	-$(CC) $(M32FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ || echo "socketfuzz32 build failure (that's fine)"
+
+socketfuzz64.so: socketfuzz.c
+	-$(CC) $(M64FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ || echo "socketfuzz64 build failure (that's fine)"
+
+install: socketfuzz32.so socketfuzz64.so
+	install -d -m 755 $(DESTDIR)$(HELPER_PATH)/
+	if [ -f socketfuzz32.so ]; then set -e; install -m 755 socketfuzz32.so $(DESTDIR)$(HELPER_PATH)/; fi
+	if [ -f socketfuzz64.so ]; then set -e; install -m 755 socketfuzz64.so $(DESTDIR)$(HELPER_PATH)/; fi
+
+clean:
+	rm -f socketfuzz32.so socketfuzz64.so
diff --git a/examples/socket_fuzzing/Makefile b/examples/socket_fuzzing/Makefile
index ad921664..0b306dde 100644
--- a/examples/socket_fuzzing/Makefile
+++ b/examples/socket_fuzzing/Makefile
@@ -1,48 +1,2 @@
-#
-# american fuzzy lop++ - socket_fuzz
-# ----------------------------------
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-
-.PHONY: all install clean
-
-PREFIX     ?= /usr/local
-BIN_PATH    = $(PREFIX)/bin
-HELPER_PATH = $(PREFIX)/lib/afl
-
-CFLAGS = -fPIC -Wall -Wextra
-LDFLAGS = -shared
-
-ifneq "$(filter Linux GNU%,$(shell uname))" ""
-  LDFLAGS  += -ldl
-endif
-
-# on gcc for arm there is no -m32, but -mbe32
-M32FLAG = -m32
-M64FLAG = -m64
-ifeq "$(findstring clang, $(shell $(CC) --version 2>/dev/null))" ""
- ifneq (,$(findstring arm, "$(shell $(CC) -v 2>&1 >/dev/null)"))
-  M32FLAG = -mbe32
- endif
-endif
-
-all: socketfuzz32.so socketfuzz64.so
-
-socketfuzz32.so: socketfuzz.c
-	-$(CC) $(M32FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ || echo "socketfuzz32 build failure (that's fine)"
-
-socketfuzz64.so: socketfuzz.c
-	-$(CC) $(M64FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ || echo "socketfuzz64 build failure (that's fine)"
-
-install: socketfuzz32.so socketfuzz64.so
-	install -d -m 755 $(DESTDIR)$(HELPER_PATH)/
-	if [ -f socketfuzz32.so ]; then set -e; install -m 755 socketfuzz32.so $(DESTDIR)$(HELPER_PATH)/; fi
-	if [ -f socketfuzz64.so ]; then set -e; install -m 755 socketfuzz64.so $(DESTDIR)$(HELPER_PATH)/; fi
-
-clean:
-	rm -f socketfuzz32.so socketfuzz64.so
+all:
+	@echo please use GNU make, thanks!
diff --git a/gcc_plugin/GNUmakefile b/gcc_plugin/GNUmakefile
new file mode 100644
index 00000000..4c7a0313
--- /dev/null
+++ b/gcc_plugin/GNUmakefile
@@ -0,0 +1,160 @@
+#
+# american fuzzy lop++ - GCC plugin instrumentation
+# -----------------------------------------------
+#
+# Written by Austin Seipp <aseipp@pobox.com> and
+#            Laszlo Szekeres <lszekeres@google.com> and
+#            Michal Zalewski and
+#            Heiko Eißfeldt  <heiko@hexco.de>
+#
+# GCC integration design is based on the LLVM design, which comes
+# from Laszlo Szekeres.
+#
+# Copyright 2015 Google Inc. All rights reserved.
+# Copyright 2019-2020 AFLplusplus Project. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+
+PREFIX      ?= /usr/local
+HELPER_PATH ?= $(PREFIX)/lib/afl
+BIN_PATH    ?= $(PREFIX)/bin
+DOC_PATH    ?= $(PREFIX)/share/doc/afl
+MAN_PATH    ?= $(PREFIX)/man/man8
+
+VERSION     = $(shell grep '^$(HASH)define VERSION ' ../config.h | cut -d '"' -f2)
+
+CFLAGS      ?= -O3 -g -funroll-loops -D_FORTIFY_SOURCE=2
+override CFLAGS = -Wall -I../include -Wno-pointer-sign \
+               -DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \
+               -DGCC_VERSION=\"$(GCCVER)\" -DGCC_BINDIR=\"$(GCCBINDIR)\" \
+               -Wno-unused-function
+
+CXXFLAGS    ?= -O3 -g -funroll-loops -D_FORTIFY_SOURCE=2
+CXXEFLAGS   := $(CXXFLAGS) -Wall
+
+CC          ?= gcc
+CXX         ?= g++
+
+ifeq "clang" "$(CC)"
+        CC  = gcc
+        CXX = g++
+endif
+
+ifeq "clang++" "$(CXX)"
+        CC  = gcc
+        CXX = g++
+endif
+
+PLUGIN_FLAGS = -fPIC -fno-rtti -I"$(shell $(CC) -print-file-name=plugin)/include"
+HASH=\#
+
+GCCVER    = $(shell $(CC) --version 2>/dev/null | awk 'NR == 1 {print $$NF}')
+GCCBINDIR = $(shell dirname `command -v $(CC)` 2>/dev/null )
+
+ifeq "$(shell echo '$(HASH)include <sys/ipc.h>@$(HASH)include <sys/shm.h>@int main() { int _id = shmget(IPC_PRIVATE, 65536, IPC_CREAT | IPC_EXCL | 0600); shmctl(_id, IPC_RMID, 0); return 0;}' | tr @ '\n' | $(CC) -x c - -o .test2 2>/dev/null && echo 1 || echo 0 ; rm -f .test2 )" "1"
+	SHMAT_OK=1
+else
+	SHMAT_OK=0
+	CFLAGS+=-DUSEMMAP=1
+	LDFLAGS += -lrt
+endif
+
+ifeq "$(TEST_MMAP)" "1"
+	SHMAT_OK=0
+	CFLAGS+=-DUSEMMAP=1
+	LDFLAGS += -lrt
+endif
+
+PROGS        = ../afl-gcc-fast ../afl-gcc-pass.so ../afl-gcc-rt.o
+
+
+all: test_shm test_deps $(PROGS) afl-gcc-fast.8 test_build all_done
+
+ifeq "$(SHMAT_OK)" "1"
+
+test_shm:
+	@echo "[+] shmat seems to be working."
+	@rm -f .test2
+
+else
+
+test_shm:
+	@echo "[-] shmat seems not to be working, switching to mmap implementation"
+
+endif
+
+
+test_deps:
+	@echo "[*] Checking for working '$(CC)'..."
+	@type $(CC) >/dev/null 2>&1 || ( echo "[-] Oops, can't find '$(CC)'. Make sure that it's in your \$$PATH (or set \$$CC and \$$CXX)."; exit 1 )
+#	@echo "[*] Checking for gcc for plugin support..."
+#	@$(CC) -v 2>&1 | grep -q -- --enable-plugin || ( echo "[-] Oops, this gcc has not been configured with plugin support."; exit 1 )
+	@echo "[*] Checking for gcc plugin development header files..."
+	@test -d `$(CC) -print-file-name=plugin`/include || ( echo "[-] Oops, can't find gcc header files. Be sure to install 'gcc-X-plugin-dev'."; exit 1 )
+	@echo "[*] Checking for '../afl-showmap'..."
+	@test -f ../afl-showmap || ( echo "[-] Oops, can't find '../afl-showmap'. Be sure to compile AFL first."; exit 1 )
+	@echo "[+] All set and ready to build."
+
+afl-common.o: ../src/afl-common.c
+	$(CC) $(CFLAGS) -c $< -o $@ $(LDFLAGS)
+
+../afl-gcc-fast: afl-gcc-fast.c afl-common.o | test_deps
+	$(CC) -DAFL_GCC_CC=\"$(CC)\" -DAFL_GCC_CXX=\"$(CXX)\" $(CFLAGS) $< afl-common.o -o $@ $(LDFLAGS)
+	ln -sf afl-gcc-fast ../afl-g++-fast
+
+../afl-gcc-pass.so: afl-gcc-pass.so.cc | test_deps
+	$(CXX) $(CXXEFLAGS) $(PLUGIN_FLAGS) -shared $< -o $@
+
+../afl-gcc-rt.o: afl-gcc-rt.o.c | test_deps
+	$(CC) $(CFLAGS) -fPIC -c $< -o $@
+
+test_build: $(PROGS)
+	@echo "[*] Testing the CC wrapper and instrumentation output..."
+	unset AFL_USE_ASAN AFL_USE_MSAN; AFL_QUIET=1 AFL_INST_RATIO=100 AFL_PATH=. AFL_CC=$(CC) ../afl-gcc-fast $(CFLAGS) ../test-instr.c -o test-instr $(LDFLAGS)
+#	unset AFL_USE_ASAN AFL_USE_MSAN;             AFL_INST_RATIO=100 AFL_PATH=. AFL_CC=$(CC) ../afl-gcc-fast $(CFLAGS) ../test-instr.c -o test-instr $(LDFLAGS)
+	ASAN_OPTIONS=detect_leaks=0 ../afl-showmap -m none -q -o .test-instr0 ./test-instr </dev/null
+	echo 1 | ASAN_OPTIONS=detect_leaks=0 ../afl-showmap -m none -q -o .test-instr1 ./test-instr
+	@rm -f test-instr
+	@cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation does not seem to be behaving correctly!"; echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue."; echo; exit 1; fi
+	@echo "[+] All right, the instrumentation seems to be working!"
+
+all_done: test_build
+	@echo "[+] All done! You can now use '../afl-gcc-fast' to compile programs."
+
+.NOTPARALLEL: clean
+
+vpath  % ..
+%.8: %
+	@echo .TH $* 8 `date "+%Y-%m-%d"` "afl++" > ../$@
+	@echo .SH NAME >> ../$@
+	@echo .B $* >> ../$@
+	@echo >> ../$@
+	@echo .SH SYNOPSIS >> ../$@
+	@../$* -h 2>&1 | head -n 3 | tail -n 1 | sed 's/^\.\///' >> ../$@
+	@echo >> ../$@
+	@echo .SH OPTIONS >> ../$@
+	@echo .nf >> ../$@
+	@../$* -h 2>&1 | tail -n +4 >> ../$@
+	@echo >> ../$@
+	@echo .SH AUTHOR >> ../$@
+	@echo "afl++ was written by Michal \"lcamtuf\" Zalewski and is maintained by Marc \"van Hauser\" Heuse <mh@mh-sec.de>, Heiko \"hexcoder-\" Eissfeldt <heiko.eissfeldt@hexco.de>, Andrea Fioraldi <andreafioraldi@gmail.com> and Dominik Maier <domenukk@gmail.com>" >> ../$@
+	@echo  The homepage of afl++ is: https://github.com/AFLplusplus/AFLplusplus >> ../$@
+	@echo >> ../$@
+	@echo .SH LICENSE >> ../$@
+	@echo Apache License Version 2.0, January 2004 >> ../$@
+	ln -sf afl-gcc-fast.8 ../afl-g++-fast.8
+
+install: all
+	install -m 755 ../afl-gcc-fast $${DESTDIR}$(BIN_PATH)
+	install -m 755 ../afl-gcc-pass.so ../afl-gcc-rt.o $${DESTDIR}$(HELPER_PATH)
+	install -m 644 -T README.md $${DESTDIR}$(DOC_PATH)/README.gcc_plugin.md
+	install -m 644 -T README.whitelist.md $${DESTDIR}$(DOC_PATH)/README.gcc_plugin.whitelist.md
+
+clean:
+	rm -f *.o *.so *~ a.out core core.[1-9][0-9]* test-instr .test-instr0 .test-instr1 .test2
+	rm -f $(PROGS) afl-common.o ../afl-g++-fast ../afl-g*-fast.8
diff --git a/gcc_plugin/Makefile b/gcc_plugin/Makefile
index 506d690d..0b306dde 100644
--- a/gcc_plugin/Makefile
+++ b/gcc_plugin/Makefile
@@ -1,150 +1,2 @@
-#
-# american fuzzy lop++ - GCC plugin instrumentation
-# -----------------------------------------------
-#
-# Written by Austin Seipp <aseipp@pobox.com> and
-#            Laszlo Szekeres <lszekeres@google.com> and
-#            Michal Zalewski and
-#            Heiko Eißfeldt  <heiko@hexco.de>
-#
-# GCC integration design is based on the LLVM design, which comes
-# from Laszlo Szekeres.
-#
-# Copyright 2015 Google Inc. All rights reserved.
-# Copyright 2019-2020 AFLplusplus Project. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-
-PREFIX      ?= /usr/local
-HELPER_PATH ?= $(PREFIX)/lib/afl
-BIN_PATH    ?= $(PREFIX)/bin
-DOC_PATH    ?= $(PREFIX)/share/doc/afl
-MAN_PATH    ?= $(PREFIX)/man/man8
-
-VERSION     = $(shell grep '^$(HASH)define VERSION ' ../config.h | cut -d '"' -f2)
-
-CFLAGS      ?= -O3 -g -funroll-loops
-CFLAGS      += -Wall -I../include -D_FORTIFY_SOURCE=2 -Wno-pointer-sign \
-               -DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \
-               -DGCC_VERSION=\"$(GCCVER)\" -DGCC_BINDIR=\"$(GCCBINDIR)\" \
-               -Wno-unused-function
-
-CXXFLAGS    ?= -O3 -g -funroll-loops
-CXXEFLAGS   := $(CXXFLAGS) -Wall -D_FORTIFY_SOURCE=2
-
-CC          ?= gcc
-CXX         ?= g++
-
-PLUGIN_FLAGS = -fPIC -fno-rtti -I"$(shell $(CC) -print-file-name=plugin)/include"
-HASH=\#
-
-GCCVER    = $(shell $(CC) --version 2>/dev/null | awk 'NR == 1 {print $$NF}')
-GCCBINDIR = $(shell dirname `command -v $(CC)` 2>/dev/null )
-
-ifeq "$(shell echo '$(HASH)include <sys/ipc.h>@$(HASH)include <sys/shm.h>@int main() { int _id = shmget(IPC_PRIVATE, 65536, IPC_CREAT | IPC_EXCL | 0600); shmctl(_id, IPC_RMID, 0); return 0;}' | tr @ '\n' | $(CC) -x c - -o .test2 2>/dev/null && echo 1 || echo 0 ; rm -f .test2 )" "1"
-	SHMAT_OK=1
-else
-	SHMAT_OK=0
-	CFLAGS+=-DUSEMMAP=1
-	LDFLAGS += -lrt
-endif
-
-ifeq "$(TEST_MMAP)" "1"
-	SHMAT_OK=0
-	CFLAGS+=-DUSEMMAP=1
-	LDFLAGS += -lrt
-endif
-
-PROGS        = ../afl-gcc-fast ../afl-gcc-pass.so ../afl-gcc-rt.o
-
-
-all: test_shm test_deps $(PROGS) afl-gcc-fast.8 test_build all_done
-
-ifeq "$(SHMAT_OK)" "1"
-
-test_shm:
-	@echo "[+] shmat seems to be working."
-	@rm -f .test2
-
-else
-
-test_shm:
-	@echo "[-] shmat seems not to be working, switching to mmap implementation"
-
-endif
-
-
-test_deps:
-	@echo "[*] Checking for working '$(CC)'..."
-	@type $(CC) >/dev/null 2>&1 || ( echo "[-] Oops, can't find '$(CC)'. Make sure that it's in your \$$PATH (or set \$$CC and \$$CXX)."; exit 1 )
-#	@echo "[*] Checking for gcc for plugin support..."
-#	@$(CC) -v 2>&1 | grep -q -- --enable-plugin || ( echo "[-] Oops, this gcc has not been configured with plugin support."; exit 1 )
-	@echo "[*] Checking for gcc plugin development header files..."
-	@test -d `$(CC) -print-file-name=plugin`/include || ( echo "[-] Oops, can't find gcc header files. Be sure to install 'gcc-X-plugin-dev'."; exit 1 )
-	@echo "[*] Checking for '../afl-showmap'..."
-	@test -f ../afl-showmap || ( echo "[-] Oops, can't find '../afl-showmap'. Be sure to compile AFL first."; exit 1 )
-	@echo "[+] All set and ready to build."
-
-afl-common.o: ../src/afl-common.c
-	$(CC) $(CFLAGS) -c $< -o $@ $(LDFLAGS)
-
-../afl-gcc-fast: afl-gcc-fast.c afl-common.o | test_deps
-	$(CC) -DAFL_GCC_CC=\"$(CC)\" -DAFL_GCC_CXX=\"$(CXX)\" $(CFLAGS) $< afl-common.o -o $@ $(LDFLAGS)
-	ln -sf afl-gcc-fast ../afl-g++-fast
-
-../afl-gcc-pass.so: afl-gcc-pass.so.cc | test_deps
-	$(CXX) $(CXXEFLAGS) $(PLUGIN_FLAGS) -shared $< -o $@
-
-../afl-gcc-rt.o: afl-gcc-rt.o.c | test_deps
-	$(CC) $(CFLAGS) -fPIC -c $< -o $@
-
-test_build: $(PROGS)
-	@echo "[*] Testing the CC wrapper and instrumentation output..."
-	unset AFL_USE_ASAN AFL_USE_MSAN; AFL_QUIET=1 AFL_INST_RATIO=100 AFL_PATH=. AFL_CC=$(CC) ../afl-gcc-fast $(CFLAGS) ../test-instr.c -o test-instr $(LDFLAGS)
-#	unset AFL_USE_ASAN AFL_USE_MSAN;             AFL_INST_RATIO=100 AFL_PATH=. AFL_CC=$(CC) ../afl-gcc-fast $(CFLAGS) ../test-instr.c -o test-instr $(LDFLAGS)
-	ASAN_OPTIONS=detect_leaks=0 ../afl-showmap -m none -q -o .test-instr0 ./test-instr </dev/null
-	echo 1 | ASAN_OPTIONS=detect_leaks=0 ../afl-showmap -m none -q -o .test-instr1 ./test-instr
-	@rm -f test-instr
-	@cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation does not seem to be behaving correctly!"; echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue."; echo; exit 1; fi
-	@echo "[+] All right, the instrumentation seems to be working!"
-
-all_done: test_build
-	@echo "[+] All done! You can now use '../afl-gcc-fast' to compile programs."
-
-.NOTPARALLEL: clean
-
-vpath  % ..
-%.8: %
-	@echo .TH $* 8 `date "+%Y-%m-%d"` "afl++" > ../$@
-	@echo .SH NAME >> ../$@
-	@echo .B $* >> ../$@
-	@echo >> ../$@
-	@echo .SH SYNOPSIS >> ../$@
-	@../$* -h 2>&1 | head -n 3 | tail -n 1 | sed 's/^\.\///' >> ../$@
-	@echo >> ../$@
-	@echo .SH OPTIONS >> ../$@
-	@echo .nf >> ../$@
-	@../$* -h 2>&1 | tail -n +4 >> ../$@
-	@echo >> ../$@
-	@echo .SH AUTHOR >> ../$@
-	@echo "afl++ was written by Michal \"lcamtuf\" Zalewski and is maintained by Marc \"van Hauser\" Heuse <mh@mh-sec.de>, Heiko \"hexcoder-\" Eissfeldt <heiko.eissfeldt@hexco.de>, Andrea Fioraldi <andreafioraldi@gmail.com> and Dominik Maier <domenukk@gmail.com>" >> ../$@
-	@echo  The homepage of afl++ is: https://github.com/AFLplusplus/AFLplusplus >> ../$@
-	@echo >> ../$@
-	@echo .SH LICENSE >> ../$@
-	@echo Apache License Version 2.0, January 2004 >> ../$@
-	ln -sf afl-gcc-fast.8 ../afl-g++-fast.8
-
-install: all
-	install -m 755 ../afl-gcc-fast $${DESTDIR}$(BIN_PATH)
-	install -m 755 ../afl-gcc-pass.so ../afl-gcc-rt.o $${DESTDIR}$(HELPER_PATH)
-	install -m 644 -T README.md $${DESTDIR}$(DOC_PATH)/README.gcc_plugin.md
-	install -m 644 -T README.whitelist.md $${DESTDIR}$(DOC_PATH)/README.gcc_plugin.whitelist.md
-
-clean:
-	rm -f *.o *.so *~ a.out core core.[1-9][0-9]* test-instr .test-instr0 .test-instr1 .test2
-	rm -f $(PROGS) afl-common.o ../afl-g++-fast ../afl-g*-fast.8
+all:
+	@echo please use GNU make, thanks!
diff --git a/gcc_plugin/afl-gcc-fast.c b/gcc_plugin/afl-gcc-fast.c
index 3583345e..fbda08b6 100644
--- a/gcc_plugin/afl-gcc-fast.c
+++ b/gcc_plugin/afl-gcc-fast.c
@@ -41,7 +41,6 @@ static u8 * obj_path;                  /* Path to runtime libraries         */
 static u8 **cc_params;                 /* Parameters passed to the real CC  */
 static u32  cc_par_cnt = 1;            /* Param count, including argv0      */
 u8          use_stdin = 0;                                         /* dummy */
-u8          be_quiet;
 
 /* Try to find the runtime libraries. If that fails, abort. */
 
diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h
index 7dddefb0..56135d0e 100644
--- a/include/afl-fuzz.h
+++ b/include/afl-fuzz.h
@@ -239,8 +239,6 @@ enum {
 
 };
 
-extern u8 *doc_path;                    /* gath to documentation dir        */
-
 /* Python stuff */
 #ifdef USE_PYTHON
 
@@ -290,8 +288,20 @@ typedef struct py_mutator {
 
   PyObject *py_module;
   PyObject *py_functions[PY_FUNC_COUNT];
-  void *afl_state;
-  void *py_data;
+  void *    afl_state;
+  void *    py_data;
+
+  u8 *   fuzz_buf;
+  size_t fuzz_size;
+
+  u8 *   pre_save_buf;
+  size_t pre_save_size;
+
+  u8 *   trim_buf;
+  size_t trim_size;
+
+  u8 *   havoc_buf;
+  size_t havoc_size;
 
 } py_mutator_t;
 
@@ -472,11 +482,6 @@ typedef struct afl_state {
       unique_tmouts,                    /* Timeouts with unique signatures  */
       unique_hangs,                     /* Hangs with unique signatures     */
       total_execs,                      /* Total execve() calls             */
-      slowest_exec_ms,                  /* Slowest testcase non hang in ms  */
-      start_time,                       /* Unix start time (ms)             */
-      last_path_time,                   /* Time for most recent path (ms)   */
-      last_crash_time,                  /* Time for most recent crash (ms)  */
-      last_hang_time,                   /* Time for most recent hang (ms)   */
       last_crash_execs,                 /* Exec counter at last crash       */
       queue_cycle,                      /* Queue round counter              */
       cycles_wo_finds,                  /* Cycles without any new paths     */
@@ -484,9 +489,14 @@ typedef struct afl_state {
       bytes_trim_in,                    /* Bytes coming into the trimmer    */
       bytes_trim_out,                   /* Bytes coming outa the trimmer    */
       blocks_eff_total,                 /* Blocks subject to effector maps  */
-      blocks_eff_select;                /* Blocks selected as fuzzable      */
+      blocks_eff_select,                /* Blocks selected as fuzzable      */
+      start_time,                       /* Unix start time (ms)             */
+      last_path_time,                   /* Time for most recent path (ms)   */
+      last_crash_time,                  /* Time for most recent crash (ms)  */
+      last_hang_time;                   /* Time for most recent hang (ms)   */
 
-  u32 subseq_tmouts;                    /* Number of timeouts in a row      */
+  u32 slowest_exec_ms,                  /* Slowest testcase non hang in ms  */
+      subseq_tmouts;                    /* Number of timeouts in a row      */
 
   u8 *stage_name,                       /* Name of the current fuzz stage   */
       *stage_short,                     /* Short stage name                 */
@@ -541,7 +551,11 @@ typedef struct afl_state {
   struct extra_data *a_extras;          /* Automatically selected extras    */
   u32                a_extras_cnt;      /* Total number of tokens available */
 
-  u8 *(*post_handler)(u8 *buf, u32 *len);
+  /* afl_postprocess API */
+  void *(*post_init)(struct afl_state *afl);
+  size_t (*post_handler)(void *data, u8 *buf, u32 len, u8 **out_buf);
+  void *(*post_deinit)(void *data);
+  void *post_data;
 
   /* CmpLog */
 
@@ -550,9 +564,6 @@ typedef struct afl_state {
 
   /* Custom mutators */
   struct custom_mutator *mutator;
-#ifdef USE_PYTHON
-  struct custom_mutator *py_mutator;
-#endif
 
   /* cmplog forkserver ids */
   s32 cmplog_fsrv_ctl_fd, cmplog_fsrv_st_fd;
@@ -580,6 +591,26 @@ typedef struct afl_state {
   u8 clean_trace_custom[MAP_SIZE];
   u8 first_trace[MAP_SIZE];
 
+  /*needed for afl_fuzz_one */
+  // TODO: see which we can reuse
+  u8 *   out_buf;
+  size_t out_size;
+
+  u8 *   out_scratch_buf;
+  size_t out_scratch_size;
+
+  u8 *   eff_buf;
+  size_t eff_size;
+
+  u8 *   in_buf;
+  size_t in_size;
+
+  u8 *   in_scratch_buf;
+  size_t in_scratch_size;
+
+  u8 *   ex_buf;
+  size_t ex_size;
+
 } afl_state_t;
 
 /* A global pointer to all instances is needed (for now) for signals to arrive
@@ -591,8 +622,10 @@ struct custom_mutator {
 
   const char *name;
   void *      dh;
+  u8 *        pre_save_buf;
+  size_t      pre_save_size;
 
-  void *data;    /* custom mutator data ptr */
+  void *data;                                    /* custom mutator data ptr */
 
   /* hooks for the custom mutator function */
 
@@ -611,16 +644,18 @@ struct custom_mutator {
    * (Optional for now. Required in the future)
    *
    * @param data pointer returned in afl_custom_init for this fuzz case
-   * @param[inout] buf Pointer to the input data to be mutated and the mutated
+   * @param[in] buf Pointer to the input data to be mutated and the mutated
    *     output
    * @param[in] buf_size Size of the input/output data
+   * @param[out] out_buf the new buffer. We may reuse *buf if large enough.
+   *             *out_buf = NULL is treated as FATAL.
    * @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)(void *data, u8 **buf, size_t buf_size,
+  size_t (*afl_custom_fuzz)(void *data, u8 *buf, size_t buf_size, u8 **out_buf,
                             u8 *add_buf, size_t add_buf_size, size_t max_size);
 
   /**
@@ -633,10 +668,10 @@ struct custom_mutator {
    * @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 of storing the test case after
-   *     processing. External library should allocate memory for out_buf. AFL++
-   *     will release the memory after saving the test case.
-   * @return Size of the output buffer after processing
+   * @param[out] out_buf Pointer to the buffer storing the test case after
+   *     processing. External library should allocate memory for out_buf.
+   *     It can chose to alter buf in-place, if the space is large enough.
+   * @return Size of the output buffer.
    */
   size_t (*afl_custom_pre_save)(void *data, u8 *buf, size_t buf_size,
                                 u8 **out_buf);
@@ -660,9 +695,10 @@ struct custom_mutator {
    * @param data pointer returned in afl_custom_init for this fuzz case
    * @param buf Buffer containing the test case
    * @param buf_size Size of the test case
-   * @return The amount of possible iteration steps to trim the input
+   * @return The amount of possible iteration steps to trim the input.
+   *        Negative on error.
    */
-  u32 (*afl_custom_init_trim)(void *data, u8 *buf, size_t buf_size);
+  s32 (*afl_custom_init_trim)(void *data, u8 *buf, size_t buf_size);
 
   /**
    * This method is called for each trimming operation. It doesn't have any
@@ -677,11 +713,11 @@ struct custom_mutator {
    *
    * @param data pointer returned in afl_custom_init for this fuzz case
    * @param[out] out_buf Pointer to the buffer containing the trimmed test case.
-   *     External library should allocate memory for out_buf. AFL++ will release
-   *     the memory after saving the test case.
-   * @param[out] out_buf_size Pointer to the size of the trimmed test case
+   *             The library can reuse a buffer for each call
+   *             and will have to free the buf (for example in deinit)
+   * @return the size of the trimmed test case
    */
-  void (*afl_custom_trim)(void *data, u8 **out_buf, size_t *out_buf_size);
+  size_t (*afl_custom_trim)(void *data, u8 **out_buf);
 
   /**
    * This method is called after each trim operation to inform you if your
@@ -693,9 +729,9 @@ struct custom_mutator {
    * @param data pointer returned in afl_custom_init for this fuzz case
    * @param success Indicates if the last trim operation was successful.
    * @return The next trim iteration index (from 0 to the maximum amount of
-   *     steps returned in init_trim)
+   *     steps returned in init_trim). Negative on error.
    */
-  u32 (*afl_custom_post_trim)(void *data, u8 success);
+  s32 (*afl_custom_post_trim)(void *data, u8 success);
 
   /**
    * Perform a single custom mutation on a given input.
@@ -703,16 +739,18 @@ struct custom_mutator {
    *
    * (Optional)
    *
-   * @param data pointer returned in afl_custom_init for this fuzz case
-   * @param[inout] buf Pointer to the input data to be mutated and the mutated
+   * @param[in] data pointer returned in afl_custom_init for this fuzz case
+   * @param[in] buf Pointer to the input data to be mutated and the mutated
    *     output
    * @param[in] buf_size Size of input data
+   * @param[out] out_buf The new buffer. It's legal to reuse *buf if it's <
+   * buf_size.
    * @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.
+   * @return Size of the mutated output (out_size).
    */
-  size_t (*afl_custom_havoc_mutation)(void *data, u8 **buf,
-                                      size_t buf_size, size_t max_size);
+  size_t (*afl_custom_havoc_mutation)(void *data, u8 *buf, size_t buf_size,
+                                      u8 **out_buf, size_t max_size);
 
   /**
    * Return the probability (in percentage) that afl_custom_havoc_mutation
@@ -748,9 +786,8 @@ struct custom_mutator {
    * @param filename_orig_queue File name of the original queue entry. This
    *     argument can be NULL while initializing the fuzzer
    */
-  void (*afl_custom_queue_new_entry)(void *data,
-                                     const u8 *   filename_new_queue,
-                                     const u8 *   filename_orig_queue);
+  void (*afl_custom_queue_new_entry)(void *data, const u8 *filename_new_queue,
+                                     const u8 *filename_orig_queue);
   /**
    * Deinitialize the custom mutator.
    *
@@ -777,10 +814,10 @@ u8   trim_case_custom(afl_state_t *, struct queue_entry *q, u8 *in_buf);
 void finalize_py_module(void *);
 
 size_t pre_save_py(void *, u8 *, size_t, u8 **);
-u32    init_trim_py(void *, u8 *, size_t);
-u32    post_trim_py(void *, u8);
-void   trim_py(void *, u8 **, size_t *);
-size_t havoc_mutation_py(void *, u8 **, size_t, size_t);
+s32    init_trim_py(void *, u8 *, size_t);
+s32    post_trim_py(void *, u8);
+size_t trim_py(void *, u8 **);
+size_t havoc_mutation_py(void *, u8 *, size_t, u8 **, size_t);
 u8     havoc_mutation_probability_py(void *);
 u8     queue_get_py(void *, const u8 *);
 void   queue_new_entry_py(void *, const u8 *, const u8 *);
@@ -898,13 +935,13 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len,
 static inline u32 rand_below(afl_state_t *afl, u32 limit) {
 
 #ifdef HAVE_ARC4RANDOM
-  if (afl->fixed_seed) { return random() % limit; }
+  if (unlikely(afl->fixed_seed)) { return random() % limit; }
 
   /* The boundary not being necessarily a power of 2,
      we need to ensure the result uniformity. */
   return arc4random_uniform(limit);
 #else
-  if (!afl->fixed_seed && unlikely(!afl->rand_cnt--)) {
+  if (unlikely(!afl->rand_cnt--) && likely(!afl->fixed_seed)) {
 
     ck_read(afl->fsrv.dev_urandom_fd, &afl->rand_seed, sizeof(afl->rand_seed),
             "/dev/urandom");
@@ -920,7 +957,7 @@ static inline u32 rand_below(afl_state_t *afl, u32 limit) {
 
 static inline u32 get_rand_seed(afl_state_t *afl) {
 
-  if (afl->fixed_seed) return (u32)afl->init_seed;
+  if (unlikely(afl->fixed_seed)) return (u32)afl->init_seed;
   return afl->rand_seed[0];
 
 }
@@ -928,7 +965,7 @@ static inline u32 get_rand_seed(afl_state_t *afl) {
 /* Find first power of two greater or equal to val (assuming val under
    2^63). */
 
-static u64 next_p2(u64 val) {
+static inline u64 next_p2(u64 val) {
 
   u64 ret = 1;
   while (val > ret)
diff --git a/include/afl-prealloc.h b/include/afl-prealloc.h
index ab86f0d7..66e6aadf 100644
--- a/include/afl-prealloc.h
+++ b/include/afl-prealloc.h
@@ -44,9 +44,8 @@ typedef enum prealloc_status {
 
 /* Adds the entry used for prealloc bookkeeping to this struct */
 
-#define PREALLOCABLE \
-  ;                  \
-  pre_status_t pre_status;              /* prealloc status of this instance */
+/* prealloc status of this instance */
+#define PREALLOCABLE pre_status_t pre_status
 
 /* allocate an element of type *el_ptr, to this variable.
     Uses (and reuses) the given prealloc_buf before hitting libc's malloc.
diff --git a/include/alloc-inl.h b/include/alloc-inl.h
index c8783d96..89889cc5 100644
--- a/include/alloc-inl.h
+++ b/include/alloc-inl.h
@@ -35,6 +35,9 @@
 #include "types.h"
 #include "debug.h"
 
+/* Initial size used for ck_maybe_grow */
+#define INITIAL_GROWTH_SIZE (64)
+
 // Be careful! _WANT_ORIGINAL_AFL_ALLOC is not compatible with custom mutators
 
 #ifndef _WANT_ORIGINAL_AFL_ALLOC
@@ -764,5 +767,99 @@ static inline void TRK_ck_free(void *ptr, const char *file, const char *func,
 
 #endif                                          /* _WANT_ORIGINAL_AFL_ALLOC */
 
+/* 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 and zero size_needed */
+  if (!next_size) { next_size = size_needed; }
+
+  /* alloc */
+  *buf = realloc(*buf, next_size);
+  *size = *buf ? next_size : 0;
+
+  return *buf;
+
+}
+
+/* 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 FATAL if size_needed is <1.
+ @return For convenience, this function returns *buf.
+ */
+static inline void *ck_maybe_grow(void **buf, size_t *size,
+                                  size_t size_needed) {
+
+  /* Oops. found a bug? */
+  if (unlikely(size_needed < 1)) FATAL("cannot grow to non-positive size");
+
+  /* No need to realloc */
+  if (likely(*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 = ck_realloc(*buf, next_size);
+  *size = next_size;
+
+  return *buf;
+
+}
+
+/* Swaps buf1 ptr and buf2 ptr, as well as their sizes */
+static inline void 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                                               /* ! _HAVE_ALLOC_INL_H */
 
diff --git a/include/common.h b/include/common.h
index 97076004..c9436e81 100644
--- a/include/common.h
+++ b/include/common.h
@@ -29,6 +29,7 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <unistd.h>
 #include <sys/time.h>
 #include "types.h"
 #include "stdbool.h"
@@ -47,349 +48,60 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv);
 char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv);
 char * get_afl_env(char *env);
 
-/* Get unix time in milliseconds */
-
-static u64 get_cur_time(void) {
-
-  struct timeval  tv;
-  struct timezone tz;
-
-  gettimeofday(&tv, &tz);
+extern u8  be_quiet;
+extern u8 *doc_path;                    /* path to documentation dir        */
 
-  return (tv.tv_sec * 1000ULL) + (tv.tv_usec / 1000);
+/* Get unix time in milliseconds */
 
-}
+u64 get_cur_time(void);
 
 /* Get unix time in microseconds */
 
-static u64 get_cur_time_us(void) {
-
-  struct timeval  tv;
-  struct timezone tz;
-
-  gettimeofday(&tv, &tz);
-
-  return (tv.tv_sec * 1000000ULL) + tv.tv_usec;
-
-}
+u64 get_cur_time_us(void);
 
 /* Describe integer. The buf should be
    at least 6 bytes to fit all ints we randomly see.
    Will return buf for convenience. */
 
-static u8 *stringify_int(u8 *buf, size_t len, u64 val) {
-
-#define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast)     \
-  do {                                                     \
-                                                           \
-    if (val < (_divisor) * (_limit_mult)) {                \
-                                                           \
-      snprintf(buf, len, _fmt, ((_cast)val) / (_divisor)); \
-      return buf;                                          \
-                                                           \
-    }                                                      \
-                                                           \
-  } while (0)
-
-  /* 0-9999 */
-  CHK_FORMAT(1, 10000, "%llu", u64);
-
-  /* 10.0k - 99.9k */
-  CHK_FORMAT(1000, 99.95, "%0.01fk", double);
-
-  /* 100k - 999k */
-  CHK_FORMAT(1000, 1000, "%lluk", u64);
-
-  /* 1.00M - 9.99M */
-  CHK_FORMAT(1000 * 1000, 9.995, "%0.02fM", double);
-
-  /* 10.0M - 99.9M */
-  CHK_FORMAT(1000 * 1000, 99.95, "%0.01fM", double);
-
-  /* 100M - 999M */
-  CHK_FORMAT(1000 * 1000, 1000, "%lluM", u64);
-
-  /* 1.00G - 9.99G */
-  CHK_FORMAT(1000LL * 1000 * 1000, 9.995, "%0.02fG", double);
-
-  /* 10.0G - 99.9G */
-  CHK_FORMAT(1000LL * 1000 * 1000, 99.95, "%0.01fG", double);
-
-  /* 100G - 999G */
-  CHK_FORMAT(1000LL * 1000 * 1000, 1000, "%lluG", u64);
-
-  /* 1.00T - 9.99G */
-  CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 9.995, "%0.02fT", double);
-
-  /* 10.0T - 99.9T */
-  CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 99.95, "%0.01fT", double);
-
-  /* 100T+ */
-  strncpy(buf, "infty", len);
-  buf[len - 1] = '\0';
-
-  return buf;
-
-}
+u8 *stringify_int(u8 *buf, size_t len, u64 val);
 
 /* Describe float. Similar as int. */
 
-static u8 *stringify_float(u8 *buf, size_t len, double val) {
-
-  if (val < 99.995) {
-
-    snprintf(buf, len, "%0.02f", val);
-
-  } else if (val < 999.95) {
-
-    snprintf(buf, len, "%0.01f", val);
-
-  } else {
-
-    stringify_int(buf, len, (u64)val);
-
-  }
-
-  return buf;
-
-}
+u8 *stringify_float(u8 *buf, size_t len, double val);
 
 /* Describe integer as memory size. */
 
-static u8 *stringify_mem_size(u8 *buf, size_t len, u64 val) {
-
-  /* 0-9999 */
-  CHK_FORMAT(1, 10000, "%llu B", u64);
-
-  /* 10.0k - 99.9k */
-  CHK_FORMAT(1024, 99.95, "%0.01f kB", double);
-
-  /* 100k - 999k */
-  CHK_FORMAT(1024, 1000, "%llu kB", u64);
-
-  /* 1.00M - 9.99M */
-  CHK_FORMAT(1024 * 1024, 9.995, "%0.02f MB", double);
-
-  /* 10.0M - 99.9M */
-  CHK_FORMAT(1024 * 1024, 99.95, "%0.01f MB", double);
-
-  /* 100M - 999M */
-  CHK_FORMAT(1024 * 1024, 1000, "%llu MB", u64);
-
-  /* 1.00G - 9.99G */
-  CHK_FORMAT(1024LL * 1024 * 1024, 9.995, "%0.02f GB", double);
-
-  /* 10.0G - 99.9G */
-  CHK_FORMAT(1024LL * 1024 * 1024, 99.95, "%0.01f GB", double);
-
-  /* 100G - 999G */
-  CHK_FORMAT(1024LL * 1024 * 1024, 1000, "%llu GB", u64);
-
-  /* 1.00T - 9.99G */
-  CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 9.995, "%0.02f TB", double);
-
-  /* 10.0T - 99.9T */
-  CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 99.95, "%0.01f TB", double);
-
-#undef CHK_FORMAT
-
-  /* 100T+ */
-  strncpy(buf, "infty", len - 1);
-  buf[len - 1] = '\0';
-
-  return buf;
-
-}
+u8 *stringify_mem_size(u8 *buf, size_t len, u64 val);
 
 /* Describe time delta as string.
    Returns a pointer to buf for convenience. */
 
-static u8 *stringify_time_diff(u8 *buf, size_t len, u64 cur_ms, u64 event_ms) {
-
-  u64 delta;
-  s32 t_d, t_h, t_m, t_s;
-  u8  val_buf[STRINGIFY_VAL_SIZE_MAX];
-
-  if (!event_ms) {
-
-    snprintf(buf, len, "none seen yet");
-
-  } else {
-
-    delta = cur_ms - event_ms;
-
-    t_d = delta / 1000 / 60 / 60 / 24;
-    t_h = (delta / 1000 / 60 / 60) % 24;
-    t_m = (delta / 1000 / 60) % 60;
-    t_s = (delta / 1000) % 60;
-
-    stringify_int(val_buf, sizeof(val_buf), t_d);
-    snprintf(buf, len, "%s days, %d hrs, %d min, %d sec", val_buf, t_h, t_m,
-             t_s);
-
-  }
-
-  return buf;
-
-}
-
+u8 *stringify_time_diff(u8 *buf, size_t len, u64 cur_ms, u64 event_ms);
 
 /* Unsafe Describe integer. The buf sizes are not checked.
    This is unsafe but fast.
    Will return buf for convenience. */
 
-static u8 *u_stringify_int(u8 *buf, u64 val) {
-
-#define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast)     \
-  do {                                                     \
-                                                           \
-    if (val < (_divisor) * (_limit_mult)) {                \
-                                                           \
-      sprintf(buf, _fmt, ((_cast)val) / (_divisor));       \
-      return buf;                                          \
-                                                           \
-    }                                                      \
-                                                           \
-  } while (0)
-
-  /* 0-9999 */
-  CHK_FORMAT(1, 10000, "%llu", u64);
-
-  /* 10.0k - 99.9k */
-  CHK_FORMAT(1000, 99.95, "%0.01fk", double);
-
-  /* 100k - 999k */
-  CHK_FORMAT(1000, 1000, "%lluk", u64);
-
-  /* 1.00M - 9.99M */
-  CHK_FORMAT(1000 * 1000, 9.995, "%0.02fM", double);
-
-  /* 10.0M - 99.9M */
-  CHK_FORMAT(1000 * 1000, 99.95, "%0.01fM", double);
-
-  /* 100M - 999M */
-  CHK_FORMAT(1000 * 1000, 1000, "%lluM", u64);
-
-  /* 1.00G - 9.99G */
-  CHK_FORMAT(1000LL * 1000 * 1000, 9.995, "%0.02fG", double);
-
-  /* 10.0G - 99.9G */
-  CHK_FORMAT(1000LL * 1000 * 1000, 99.95, "%0.01fG", double);
-
-  /* 100G - 999G */
-  CHK_FORMAT(1000LL * 1000 * 1000, 1000, "%lluG", u64);
-
-  /* 1.00T - 9.99G */
-  CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 9.995, "%0.02fT", double);
-
-  /* 10.0T - 99.9T */
-  CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 99.95, "%0.01fT", double);
-
-  /* 100T+ */
-  strcpy(buf, "infty");
-
-  return buf;
-
-}
+u8 *u_stringify_int(u8 *buf, u64 val);
 
 /* Unsafe describe float. Similar as unsafe int. */
 
-static u8 *u_stringify_float(u8 *buf, double val) {
-
-  if (val < 99.995) {
-
-    sprintf(buf, "%0.02f", val);
-
-  } else if (val < 999.95) {
-
-    sprintf(buf, "%0.01f", val);
-
-  } else {
-
-    return u_stringify_int(buf, (u64)val);
-
-  }
-
-  return buf;
-
-}
+u8 *u_stringify_float(u8 *buf, double val);
 
 /* Unsafe describe integer as memory size. */
 
-static u8 *u_stringify_mem_size(u8 *buf, u64 val) {
-
-  /* 0-9999 */
-  CHK_FORMAT(1, 10000, "%llu B", u64);
-
-  /* 10.0k - 99.9k */
-  CHK_FORMAT(1024, 99.95, "%0.01f kB", double);
-
-  /* 100k - 999k */
-  CHK_FORMAT(1024, 1000, "%llu kB", u64);
-
-  /* 1.00M - 9.99M */
-  CHK_FORMAT(1024 * 1024, 9.995, "%0.02f MB", double);
-
-  /* 10.0M - 99.9M */
-  CHK_FORMAT(1024 * 1024, 99.95, "%0.01f MB", double);
-
-  /* 100M - 999M */
-  CHK_FORMAT(1024 * 1024, 1000, "%llu MB", u64);
-
-  /* 1.00G - 9.99G */
-  CHK_FORMAT(1024LL * 1024 * 1024, 9.995, "%0.02f GB", double);
-
-  /* 10.0G - 99.9G */
-  CHK_FORMAT(1024LL * 1024 * 1024, 99.95, "%0.01f GB", double);
-
-  /* 100G - 999G */
-  CHK_FORMAT(1024LL * 1024 * 1024, 1000, "%llu GB", u64);
-
-  /* 1.00T - 9.99G */
-  CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 9.995, "%0.02f TB", double);
-
-  /* 10.0T - 99.9T */
-  CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 99.95, "%0.01f TB", double);
-
-#undef CHK_FORMAT
-
-  /* 100T+ */
-  strcpy(buf, "infty");
-
-  return buf;
-
-}
+u8 *u_stringify_mem_size(u8 *buf, u64 val);
 
 /* Unsafe describe time delta as string.
    Returns a pointer to buf for convenience. */
 
-static u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms) {
-
-  u64 delta;
-  s32 t_d, t_h, t_m, t_s;
-  u8  val_buf[STRINGIFY_VAL_SIZE_MAX];
-
-  if (!event_ms) {
-
-    sprintf(buf, "none seen yet");
-
-  } else {
-
-    delta = cur_ms - event_ms;
-
-    t_d = delta / 1000 / 60 / 60 / 24;
-    t_h = (delta / 1000 / 60 / 60) % 24;
-    t_m = (delta / 1000 / 60) % 60;
-    t_s = (delta / 1000) % 60;
-
-    u_stringify_int(val_buf, t_d);
-    sprintf(buf, "%s days, %d hrs, %d min, %d sec", val_buf, t_h, t_m, t_s);
-
-  }
-
-  return buf;
+u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms);
 
-}
+/* Wrapper for select() and read(), reading exactly len bytes.
+  Returns the time passed to read.
+  If the wait times out, returns timeout_ms + 1;
+  Returns 0 if an error occurred (fd closed, signal, ...); */
+u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms);
 
 #endif
 
diff --git a/include/list.h b/include/list.h
index 1190931f..e93b4e8f 100644
--- a/include/list.h
+++ b/include/list.h
@@ -34,8 +34,8 @@
 #include "debug.h"
 #include "afl-prealloc.h"
 
-#define LIST_PREALLOC_SIZE \
-  (64)             /* How many elements to allocate before malloc is needed */
+/* How many elements to allocate before malloc is needed */
+#define LIST_PREALLOC_SIZE (64)
 
 typedef struct list_element {
 
@@ -56,17 +56,18 @@ typedef struct list {
 
 static inline element_t *get_head(list_t *list) {
 
-  return &list->element_prealloc_buf[0];
+  /* The first element is the head */
+  return list->element_prealloc_buf;
 
 }
 
-static void list_free_el(list_t *list, element_t *el) {
+static inline void list_free_el(list_t *list, element_t *el) {
 
   PRE_FREE(el, list->element_prealloc_count);
 
 }
 
-static void list_append(list_t *list, void *el) {
+static inline void list_append(list_t *list, void *el) {
 
   element_t *head = get_head(list);
   if (!head->next) {
@@ -97,23 +98,23 @@ static void list_append(list_t *list, void *el) {
    A return from this block will return from calling func.
 */
 
-#define LIST_FOREACH(list, type, block)                    \
-  do {                                                     \
-                                                           \
-    list_t *   li = (list);                                \
-    element_t *head = get_head((li));                      \
-    element_t *el_box = (head)->next;                      \
-    if (!el_box) FATAL("foreach over uninitialized list"); \
-    while (el_box != head) {                               \
-                                                           \
-      type *el = (type *)((el_box)->data);                 \
-      /* get next so el_box can be unlinked */             \
-      element_t *next = el_box->next;                      \
-      {block};                                             \
-      el_box = next;                                       \
-                                                           \
-    }                                                      \
-                                                           \
+#define LIST_FOREACH(list, type, block)                            \
+  do {                                                             \
+                                                                   \
+    list_t *   li = (list);                                        \
+    element_t *head = get_head((li));                              \
+    element_t *el_box = (head)->next;                              \
+    if (!el_box) FATAL("foreach over uninitialized list");         \
+    while (el_box != head) {                                       \
+                                                                   \
+      __attribute__((unused)) type *el = (type *)((el_box)->data); \
+      /* get next so el_box can be unlinked */                     \
+      element_t *next = el_box->next;                              \
+      {block};                                                     \
+      el_box = next;                                               \
+                                                                   \
+    }                                                              \
+                                                                   \
   } while (0);
 
 /* In foreach: remove the current el from the list */
@@ -143,7 +144,7 @@ static void list_append(list_t *list, void *el) {
 
 /* remove an item from the list */
 
-static void list_remove(list_t *list, void *remove_me) {
+static inline void list_remove(list_t *list, void *remove_me) {
 
   LIST_FOREACH(list, void, {
 
@@ -165,7 +166,7 @@ static void list_remove(list_t *list, void *remove_me) {
 
 /* Returns true if el is in list */
 
-static bool list_contains(list_t *list, void *contains_me) {
+static inline bool list_contains(list_t *list, void *contains_me) {
 
   LIST_FOREACH(list, void, {
 
diff --git a/include/types.h b/include/types.h
index bd4bd05d..da95cb39 100644
--- a/include/types.h
+++ b/include/types.h
@@ -58,8 +58,22 @@ typedef int32_t s32;
 typedef int64_t s64;
 
 #ifndef MIN
-#define MIN(_a, _b) ((_a) > (_b) ? (_b) : (_a))
-#define MAX(_a, _b) ((_a) > (_b) ? (_a) : (_b))
+#define MIN(a, b)           \
+  ({                        \
+                            \
+    __typeof__(a) _a = (a); \
+    __typeof__(b) _b = (b); \
+    _a < _b ? _a : _b;      \
+                            \
+  })
+#define MAX(a, b)           \
+  ({                        \
+                            \
+    __typeof__(a) _a = (a); \
+    __typeof__(b) _b = (b); \
+    _a > _b ? _a : _b;      \
+                            \
+  })
 #endif                                                              /* !MIN */
 
 #define SWAP16(_x)                    \
@@ -120,9 +134,13 @@ typedef int64_t s64;
 #define likely(_x) (_x)
 #define unlikely(_x) (_x)
 #else
+#ifndef likely
 #define likely(_x) __builtin_expect(!!(_x), 1)
+#endif
+#ifndef unlikely
 #define unlikely(_x) __builtin_expect(!!(_x), 0)
 #endif
+#endif
 
 #endif                                                   /* ! _HAVE_TYPES_H */
 
diff --git a/libdislocator/GNUmakefile b/libdislocator/GNUmakefile
new file mode 100644
index 00000000..3ee37088
--- /dev/null
+++ b/libdislocator/GNUmakefile
@@ -0,0 +1,44 @@
+#
+# american fuzzy lop++ - libdislocator
+# ----------------------------------
+#
+# Originally written by Michal Zalewski
+#
+# Copyright 2016 Google Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+
+PREFIX      ?= /usr/local
+HELPER_PATH  = $(PREFIX)/lib/afl
+
+VERSION     = $(shell grep '^\#define VERSION ' ../config.h | cut -d '"' -f2)
+
+CFLAGS      ?= -O3 -funroll-loops
+override CFLAGS += -I ../include/ -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign
+
+ifdef USEHUGEPAGE
+	CFLAGS += -DUSEHUGEPAGE
+endif
+
+all: libdislocator.so
+
+VPATH = ..
+libdislocator.so: libdislocator.so.c ../config.h
+	$(CC) $(CFLAGS) -shared -fPIC $< -o ../$@ $(LDFLAGS)
+
+.NOTPARALLEL: clean
+
+clean:
+	rm -f *.o *.so *~ a.out core core.[1-9][0-9]*
+	rm -f ../libdislocator.so
+
+install: all
+	install -m 755 -d $${DESTDIR}$(HELPER_PATH)
+	install -m 755 ../libdislocator.so $${DESTDIR}$(HELPER_PATH)
+	install -m 644 README.dislocator.md $${DESTDIR}$(HELPER_PATH)
+
diff --git a/libdislocator/Makefile b/libdislocator/Makefile
index 07d98a0d..0b306dde 100644
--- a/libdislocator/Makefile
+++ b/libdislocator/Makefile
@@ -1,44 +1,2 @@
-#
-# american fuzzy lop++ - libdislocator
-# ----------------------------------
-#
-# Originally written by Michal Zalewski
-#
-# Copyright 2016 Google Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-
-PREFIX      ?= /usr/local
-HELPER_PATH  = $(PREFIX)/lib/afl
-
-VERSION     = $(shell grep '^\#define VERSION ' ../config.h | cut -d '"' -f2)
-
-CFLAGS      ?= -O3 -funroll-loops
-CFLAGS      += -I ../include/ -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign
-
-ifdef USEHUGEPAGE
-	CFLAGS += -DUSEHUGEPAGE
-endif
-
-all: libdislocator.so
-
-VPATH = ..
-libdislocator.so: libdislocator.so.c ../config.h
-	$(CC) $(CFLAGS) -shared -fPIC $< -o ../$@ $(LDFLAGS)
-
-.NOTPARALLEL: clean
-
-clean:
-	rm -f *.o *.so *~ a.out core core.[1-9][0-9]*
-	rm -f ../libdislocator.so
-
-install: all
-	install -m 755 -d $${DESTDIR}$(HELPER_PATH)
-	install -m 755 ../libdislocator.so $${DESTDIR}$(HELPER_PATH)
-	install -m 644 README.dislocator.md $${DESTDIR}$(HELPER_PATH)
-
+all:
+	@echo please use GNU make, thanks!
diff --git a/libtokencap/GNUmakefile b/libtokencap/GNUmakefile
new file mode 100644
index 00000000..5fcd7731
--- /dev/null
+++ b/libtokencap/GNUmakefile
@@ -0,0 +1,63 @@
+#
+# american fuzzy lop++ - libtokencap
+# --------------------------------
+#
+# Originally written by Michal Zalewski
+#
+# Copyright 2016 Google Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+
+PREFIX      ?= /usr/local
+HELPER_PATH  = $(PREFIX)/lib/afl
+DOC_PATH    ?= $(PREFIX)/share/doc/afl
+MAN_PATH    ?= $(PREFIX)/man/man8
+
+VERSION     = $(shell grep '^\#define VERSION ' ../config.h | cut -d '"' -f2)
+
+CFLAGS      ?= -O3 -funroll-loops
+override CFLAGS += -I ../include/ -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign
+
+ifeq "$(shell uname)" "Linux"
+  TARGETS = libtokencap.so
+  LDFLAGS     += -ldl
+endif
+ifeq "$(shell uname)" "Darwin"
+  TARGETS = libtokencap.so
+  LDFLAGS     += -ldl
+endif
+ifeq "$(shell uname)" "FreeBSD"
+  TARGETS = libtokencap.so
+endif
+ifeq "$(shell uname)" "OpenBSD"
+  TARGETS = libtokencap.so
+endif
+ifeq "$(shell uname)" "NetBSD"
+  TARGETS = libtokencap.so
+endif
+ifeq "$(shell uname)" "DragonFly"
+  TARGETS = libtokencap.so
+  LDFLAGS     += -ldl
+endif
+all: $(TARGETS)
+
+VPATH = ..
+libtokencap.so: libtokencap.so.c ../config.h
+	$(CC) $(CFLAGS) -shared -fPIC $< -o ../$@ $(LDFLAGS)
+
+.NOTPARALLEL: clean
+
+clean:
+	rm -f *.o *.so *~ a.out core core.[1-9][0-9]*
+	rm -f ../libtokencap.so
+
+install: all
+	install -m 755 -d $${DESTDIR}$(HELPER_PATH)
+	install -m 755 ../libtokencap.so $${DESTDIR}$(HELPER_PATH)
+	install -m 644 -T README.md $${DESTDIR}$(DOC_PATH)/README.tokencap.md
+
diff --git a/libtokencap/Makefile b/libtokencap/Makefile
index 4889479b..0b306dde 100644
--- a/libtokencap/Makefile
+++ b/libtokencap/Makefile
@@ -1,63 +1,2 @@
-#
-# american fuzzy lop++ - libtokencap
-# --------------------------------
-#
-# Originally written by Michal Zalewski
-#
-# Copyright 2016 Google Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-
-PREFIX      ?= /usr/local
-HELPER_PATH  = $(PREFIX)/lib/afl
-DOC_PATH    ?= $(PREFIX)/share/doc/afl
-MAN_PATH    ?= $(PREFIX)/man/man8
-
-VERSION     = $(shell grep '^\#define VERSION ' ../config.h | cut -d '"' -f2)
-
-CFLAGS      ?= -O3 -funroll-loops
-CFLAGS      += -I ../include/ -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign
-
-ifeq "$(shell uname)" "Linux"
-  TARGETS = libtokencap.so
-  LDFLAGS     += -ldl
-endif
-ifeq "$(shell uname)" "Darwin"
-  TARGETS = libtokencap.so
-  LDFLAGS     += -ldl
-endif
-ifeq "$(shell uname)" "FreeBSD"
-  TARGETS = libtokencap.so
-endif
-ifeq "$(shell uname)" "OpenBSD"
-  TARGETS = libtokencap.so
-endif
-ifeq "$(shell uname)" "NetBSD"
-  TARGETS = libtokencap.so
-endif
-ifeq "$(shell uname)" "DragonFly"
-  TARGETS = libtokencap.so
-  LDFLAGS     += -ldl
-endif
-all: $(TARGETS)
-
-VPATH = ..
-libtokencap.so: libtokencap.so.c ../config.h
-	$(CC) $(CFLAGS) -shared -fPIC $< -o ../$@ $(LDFLAGS)
-
-.NOTPARALLEL: clean
-
-clean:
-	rm -f *.o *.so *~ a.out core core.[1-9][0-9]*
-	rm -f ../libtokencap.so
-
-install: all
-	install -m 755 -d $${DESTDIR}$(HELPER_PATH)
-	install -m 755 ../libtokencap.so $${DESTDIR}$(HELPER_PATH)
-	install -m 644 -T README.md $${DESTDIR}$(DOC_PATH)/README.tokencap.md
-
+all:
+	@echo please use GNU make, thanks!
diff --git a/llvm_mode/GNUmakefile b/llvm_mode/GNUmakefile
new file mode 100644
index 00000000..006d115d
--- /dev/null
+++ b/llvm_mode/GNUmakefile
@@ -0,0 +1,375 @@
+#
+# american fuzzy lop++ - LLVM instrumentation
+# -----------------------------------------
+#
+# Written by Laszlo Szekeres <lszekeres@google.com> and
+#            Michal Zalewski
+#
+# LLVM integration design comes from Laszlo Szekeres.
+#
+# Copyright 2015, 2016 Google Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+
+# For Heiko:
+#TEST_MMAP=1
+HASH=\#
+
+PREFIX      ?= /usr/local
+HELPER_PATH ?= $(PREFIX)/lib/afl
+BIN_PATH    ?= $(PREFIX)/bin
+DOC_PATH    ?= $(PREFIX)/share/doc/afl
+MISC_PATH   ?= $(PREFIX)/share/afl
+MAN_PATH    ?= $(PREFIX)/man/man8
+
+VERSION     = $(shell grep '^$(HASH)define VERSION ' ../config.h | cut -d '"' -f2)
+
+ifeq "$(shell uname)" "OpenBSD"
+  LLVM_CONFIG ?= $(BIN_PATH)/llvm-config
+  HAS_OPT = $(shell test -x $(BIN_PATH)/opt && echo 0 || echo 1)
+  ifeq "$(HAS_OPT)" "1"
+    $(error llvm_mode needs a complete llvm installation (versions 3.8.0 up to 11) -> e.g. "pkg_add llvm-7.0.1p9")
+  endif
+else
+  LLVM_CONFIG ?= llvm-config
+endif
+
+LLVMVER  = $(shell $(LLVM_CONFIG) --version 2>/dev/null )
+LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^3\.[0-7]|^1[2-9]' && echo 1 || echo 0 )
+LLVM_NEW_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^1[0-9]' && echo 1 || echo 0 )
+LLVM_MAJOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/\..*//')
+LLVM_BINDIR = $(shell $(LLVM_CONFIG) --bindir 2>/dev/null)
+LLVM_STDCXX = gnu++11
+LLVM_APPLE = $(shell clang -v 2>&1 | grep -iq apple && echo 1 || echo 0)
+LLVM_LTO   = 0
+
+ifeq "$(LLVMVER)" ""
+  $(warning [!] llvm_mode needs llvm-config, which was not found)
+endif
+
+ifeq "$(LLVM_UNSUPPORTED)" "1"
+  $(warning llvm_mode only supports llvm versions 3.8.0 up to 11)
+endif
+
+ifeq "$(LLVM_MAJOR)" "9"
+  $(info [+] llvm_mode detected llvm 9, enabling neverZero implementation)
+  $(info [+] llvm_mode detected llvm 9, enabling afl-clang-lto LTO implementation)
+  LLVM_LTO = 1
+endif
+
+ifeq "$(LLVM_NEW_API)" "1"
+  $(info [+] llvm_mode detected llvm 10+, enabling neverZero implementation and c++14)
+  $(info [+] llvm_mode detected llvm 9, enabling afl-clang-lto LTO implementation)
+  LLVM_STDCXX = c++14
+  LLVM_LTO = 1
+endif
+
+ifeq "$(LLVM_LTO)" "0"
+  $(info [+] llvm_mode detected llvm < 9, afl-clang-lto LTO will not be build.)
+endif
+
+ifeq "$(LLVM_APPLE)" "1"
+  $(warning llvm_mode will not compile with Xcode clang...)
+endif
+
+# We were using llvm-config --bindir to get the location of clang, but
+# this seems to be busted on some distros, so using the one in $PATH is
+# probably better.
+
+CC         = $(LLVM_BINDIR)/clang
+CXX        = $(LLVM_BINDIR)/clang++
+
+ifeq "$(shell test -e $(CC) || echo 1 )" "1"
+  # llvm-config --bindir may not providing a valid path, so ...
+  ifeq "$(shell test -e '$(BIN_DIR)/clang' && echo 1)" "1"
+    # we found one in the local install directory, lets use these
+    CC         = $(BIN_DIR)/clang
+    CXX        = $(BIN_DIR)/clang++
+  else
+    # hope for the best
+    $(warning we have trouble finding clang/clang++ - llvm-config is not helping us)
+    CC         = clang
+    CXX        = clang++
+  endif
+endif
+
+# sanity check.
+# Are versions of clang --version and llvm-config --version equal?
+CLANGVER = $(shell $(CC) --version | sed -E -ne '/^.*version\ ([0-9]\.[0-9]\.[0-9]).*/s//\1/p')
+
+ifneq "$(CLANGVER)" "$(LLVMVER)"
+  CC = $(shell $(LLVM_CONFIG) --bindir)/clang
+  CXX = $(shell $(LLVM_CONFIG) --bindir)/clang++
+endif
+
+# After we set CC/CXX we can start makefile magic tests
+
+ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -march=native -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
+	CFLAGS_OPT = -march=native
+endif
+
+ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -flto=full -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
+        AFL_CLANG_FLTO ?= -flto=full
+else
+ ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -flto=thin -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
+        AFL_CLANG_FLTO ?= -flto=thin
+ else
+  ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -flto -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
+        AFL_CLANG_FLTO ?= -flto
+  endif
+ endif
+endif
+
+ifneq "$(AFL_CLANG_FLTO)" ""
+ifeq "$(AFL_REAL_LD)" ""
+  AFL_REAL_LD = $(shell readlink /bin/ld 2>/dev/null)
+  ifeq "$(AFL_REAL_LD)" ""
+    AFL_REAL_LD = $(shell readlink /usr/bin/ld 2>/dev/null)
+  endif
+endif
+endif
+
+CFLAGS          ?= -O3 -funroll-loops -D_FORTIFY_SOURCE=2
+override CFLAGS = -Wall \
+               -g -Wno-pointer-sign -I ../include/ \
+               -DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \
+               -DLLVM_BINDIR=\"$(LLVM_BINDIR)\" -DVERSION=\"$(VERSION)\" \
+               -DLLVM_VERSION=\"$(LLVMVER)\"  -DAFL_CLANG_FLTO=\"$(AFL_CLANG_FLTO)\" \
+               -DAFL_REAL_LD=\"$(AFL_REAL_LD)\" -Wno-unused-function
+ifdef AFL_TRACE_PC
+  CFLAGS    += -DUSE_TRACE_PC=1
+endif
+
+CXXFLAGS          ?= -O3 -funroll-loops -D_FORTIFY_SOURCE=2
+override CXXFLAGS += -Wall -g -I ../include/ \
+                     -DVERSION=\"$(VERSION)\" -Wno-variadic-macros
+
+CLANG_CFL    = `$(LLVM_CONFIG) --cxxflags` -Wl,-znodelete -fno-rtti -fpic $(CXXFLAGS)
+CLANG_LFL    = `$(LLVM_CONFIG) --ldflags` $(LDFLAGS)
+
+
+# User teor2345 reports that this is required to make things work on MacOS X.
+ifeq "$(shell uname)" "Darwin"
+  CLANG_LFL += -Wl,-flat_namespace -Wl,-undefined,suppress
+endif
+
+ifeq "$(shell uname)" "OpenBSD"
+  CLANG_LFL += `$(LLVM_CONFIG) --libdir`/libLLVM.so
+endif
+
+ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -fuse-ld=`command -v ld` -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
+  CFLAGS += -DAFL_CLANG_FUSELD=1
+endif
+
+ifeq "$(shell echo '$(HASH)include <sys/ipc.h>@$(HASH)include <sys/shm.h>@int main() { int _id = shmget(IPC_PRIVATE, 65536, IPC_CREAT | IPC_EXCL | 0600); shmctl(_id, IPC_RMID, 0); return 0;}' | tr @ '\n' | $(CC) -x c - -o .test2 2>/dev/null && echo 1 || echo 0 ; rm -f .test2 )" "1"
+        SHMAT_OK=1
+else
+        SHMAT_OK=0
+        CFLAGS+=-DUSEMMAP=1
+        LDFLAGS += -lrt
+endif
+
+ifeq "$(TEST_MMAP)" "1"
+        SHMAT_OK=0
+        CFLAGS+=-DUSEMMAP=1
+        LDFLAGS += -lrt
+endif
+
+ifndef AFL_TRACE_PC
+  PROGS      = ../afl-clang-fast ../afl-ld ../afl-llvm-pass.so ../afl-llvm-lto-whitelist.so ../afl-llvm-lto-instrumentation.so ../libLLVMInsTrim.so ../afl-llvm-rt.o ../afl-llvm-rt-32.o ../afl-llvm-rt-64.o ../compare-transform-pass.so ../split-compares-pass.so ../split-switches-pass.so ../cmplog-routines-pass.so ../cmplog-instructions-pass.so
+else
+  PROGS      = ../afl-clang-fast ../afl-llvm-rt.o ../afl-llvm-rt-32.o ../afl-llvm-rt-64.o ../compare-transform-pass.so ../split-compares-pass.so ../split-switches-pass.so ../cmplog-routines-pass.so ../cmplog-instructions-pass.so
+endif
+
+# If prerequisites are not given, warn, do not build anything, and exit with code 0
+ifeq "$(LLVMVER)" ""
+  NO_BUILD = 1
+endif
+
+ifneq "$(LLVM_UNSUPPORTED)$(LLVM_APPLE)" "00"
+  NO_BUILD = 1
+endif
+
+ifeq "$(NO_BUILD)" "1"
+  TARGETS = no_build
+else
+  TARGETS = test_shm test_deps $(PROGS) afl-clang-fast.8 test_build all_done
+endif
+
+LLVM_MIN_4_0_1 = $(shell awk 'function tonum(ver, a) {split(ver,a,"."); return a[1]*1000000+a[2]*1000+a[3]} BEGIN { exit tonum(ARGV[1]) >= tonum(ARGV[2]) }' $(LLVMVER) 4.0.1; echo $$?)
+
+all: $(TARGETS)
+
+ifeq "$(SHMAT_OK)" "1"
+
+test_shm:
+	@echo "[+] shmat seems to be working."
+	@rm -f .test2
+
+else
+
+test_shm:
+	@echo "[-] shmat seems not to be working, switching to mmap implementation"
+
+endif
+
+no_build:
+	@printf "%b\\n" "\\033[0;31mPrerequisites are not met, skipping build llvm_mode\\033[0m"
+
+test_deps:
+ifndef AFL_TRACE_PC
+	@echo "[*] Checking for working 'llvm-config'..."
+ ifneq "$(LLVM_APPLE)" "1"
+	@type $(LLVM_CONFIG) >/dev/null 2>&1 || ( echo "[-] Oops, can't find 'llvm-config'. Install clang or set \$$LLVM_CONFIG or \$$PATH beforehand."; echo "    (Sometimes, the binary will be named llvm-config-3.5 or something like that.)"; exit 1 )
+ endif
+else
+	@echo "[!] Note: using -fsanitize=trace-pc mode (this will fail with older LLVM)."
+endif
+	@echo "[*] Checking for working '$(CC)'..."
+	@type $(CC) >/dev/null 2>&1 || ( echo "[-] Oops, can't find '$(CC)'. Make sure that it's in your \$$PATH (or set \$$CC and \$$CXX)."; exit 1 )
+	@echo "[*] Checking for matching versions of '$(CC)' and '$(LLVM_CONFIG)'"
+ifneq "$(CLANGVER)" "$(LLVMVER)"
+	@echo "[!] WARNING: we have llvm-config version $(LLVMVER) and a clang version $(CLANGVER)"
+	@echo "[!] Retrying with the clang compiler from llvm: CC=`llvm-config --bindir`/clang"
+else
+	@echo "[*] We have llvm-config version $(LLVMVER) with a clang version $(CLANGVER), good."
+endif
+	@echo "[*] Checking for '../afl-showmap'..."
+	@test -f ../afl-showmap || ( echo "[-] Oops, can't find '../afl-showmap'. Be sure to compile AFL first."; exit 1 )
+	@echo "[+] All set and ready to build."
+
+afl-common.o: ../src/afl-common.c
+	$(CC) $(CFLAGS) -c $< -o $@ $(LDFLAGS)
+
+../afl-clang-fast: afl-clang-fast.c afl-common.o | test_deps
+	$(CC) $(CFLAGS) $< afl-common.o -o $@ $(LDFLAGS) -DCFLAGS_OPT=\"$(CFLAGS_OPT)\"
+	ln -sf afl-clang-fast ../afl-clang-fast++
+ifneq "$(AFL_CLANG_FLTO)" ""
+ifeq "$(LLVM_LTO)" "1"
+	ln -sf afl-clang-fast ../afl-clang-lto
+	ln -sf afl-clang-fast ../afl-clang-lto++
+endif
+endif
+
+../afl-ld: afl-ld.c
+ifneq "$(AFL_CLANG_FLTO)" ""
+ifeq "$(LLVM_LTO)" "1"
+	$(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
+	ln -sf afl-ld ../ld
+	@rm -f .test-instr
+	@-export AFL_QUIET=1 AFL_PATH=.. PATH="..:$(PATH)" ; ../afl-clang-lto -Wl,--afl -o .test-instr ../test-instr.c && echo "[+] afl-clang-lto and afl-ld seem to work fine :)" || echo "[!] WARNING: clang seems to have a hardcoded "'/bin/ld'" - check README.lto"
+	@rm -f .test-instr
+endif
+endif
+../libLLVMInsTrim.so: LLVMInsTrim.so.cc MarkNodes.cc | test_deps
+	-$(CXX) $(CLANG_CFL) -DLLVMInsTrim_EXPORTS -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< MarkNodes.cc -o $@ $(CLANG_LFL)
+
+../afl-llvm-pass.so: afl-llvm-pass.so.cc | test_deps
+ifeq "$(LLVM_MIN_4_0_1)" "0"
+	$(info [!] N-gram branch coverage instrumentation is not available for llvm version $(LLVMVER))
+endif
+	$(CXX) $(CLANG_CFL) -DLLVMInsTrim_EXPORTS -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL)
+
+../afl-llvm-lto-whitelist.so: afl-llvm-lto-whitelist.so.cc
+ifeq "$(LLVM_LTO)" "1"
+	$(CXX) $(CLANG_CFL) -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL)
+endif
+
+../afl-llvm-lto-instrumentation.so: afl-llvm-lto-instrumentation.so.cc MarkNodes.cc
+ifeq "$(LLVM_LTO)" "1"
+	$(CXX) $(CLANG_CFL) -Wno-writable-strings -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< MarkNodes.cc -o $@ $(CLANG_LFL)
+endif
+
+# laf
+../split-switches-pass.so:	split-switches-pass.so.cc | test_deps
+	$(CXX) $(CLANG_CFL) -shared $< -o $@ $(CLANG_LFL)
+../compare-transform-pass.so:	compare-transform-pass.so.cc | test_deps
+	$(CXX) $(CLANG_CFL) -shared $< -o $@ $(CLANG_LFL)
+../split-compares-pass.so:	split-compares-pass.so.cc | test_deps
+	$(CXX) $(CLANG_CFL) -shared $< -o $@ $(CLANG_LFL)
+# /laf
+
+../cmplog-routines-pass.so:	cmplog-routines-pass.cc | test_deps
+	$(CXX) $(CLANG_CFL) -shared $< -o $@ $(CLANG_LFL)
+
+../cmplog-instructions-pass.so:	cmplog-instructions-pass.cc | test_deps
+	$(CXX) $(CLANG_CFL) -shared $< -o $@ $(CLANG_LFL)
+
+../afl-llvm-rt.o: afl-llvm-rt.o.c | test_deps
+	$(CC) $(CFLAGS) -fPIC -c $< -o $@
+
+../afl-llvm-rt-32.o: afl-llvm-rt.o.c | test_deps
+	@printf "[*] Building 32-bit variant of the runtime (-m32)... "
+	@$(CC) $(CFLAGS) -m32 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
+
+../afl-llvm-rt-64.o: afl-llvm-rt.o.c | test_deps
+	@printf "[*] Building 64-bit variant of the runtime (-m64)... "
+	@$(CC) $(CFLAGS) -m64 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
+
+test_build: $(PROGS)
+	@echo "[*] Testing the CC wrapper and instrumentation output..."
+	unset AFL_USE_ASAN AFL_USE_MSAN AFL_INST_RATIO; AFL_QUIET=1 AFL_PATH=. AFL_CC=$(CC) AFL_LLVM_LAF_SPLIT_SWITCHES=1 AFL_LLVM_LAF_TRANSFORM_COMPARES=1 AFL_LLVM_LAF_SPLIT_COMPARES=1 ../afl-clang-fast $(CFLAGS) ../test-instr.c -o test-instr $(LDFLAGS)
+	ASAN_OPTIONS=detect_leaks=0 ../afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null
+	echo 1 | ASAN_OPTIONS=detect_leaks=0 ../afl-showmap -m none -q -o .test-instr1 ./test-instr
+	@rm -f test-instr
+	@cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation does not seem to be behaving correctly!"; echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue."; echo; exit 1; fi
+	@echo "[+] All right, the instrumentation seems to be working!"
+
+all_done: test_build
+	@echo "[+] All done! You can now use '../afl-clang-fast' to compile programs."
+
+.NOTPARALLEL: clean
+
+install: all
+	install -d -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) $${DESTDIR}$(DOC_PATH) $${DESTDIR}$(MISC_PATH)
+ifndef AFL_TRACE_PC
+	if [ -f ../afl-clang-fast -a -f ../libLLVMInsTrim.so -a -f ../afl-llvm-rt.o ]; then set -e; install -m 755 ../afl-clang-fast $${DESTDIR}$(BIN_PATH); ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-fast++; install -m 755 ../libLLVMInsTrim.so ../afl-llvm-pass.so ../afl-llvm-rt.o $${DESTDIR}$(HELPER_PATH); fi
+	if [ -f afl-clang-lto -a -f afl-ld ]; then set -e; install -m 755 afl-clang-lto $${DESTDIR}$(BIN_PATH); ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-lto++; install -m 755 afl-ld $${DESTDIR}$(HELPER_PATH); ln -sf afl-ld $${DESTDIR}$(HELPER_PATH)/ld; install -m 755 afl-llvm-lto-instrumentation.so $${DESTDIR}$(HELPER_PATH); install -m 755 afl-llvm-lto-whitelist.so $${DESTDIR}$(HELPER_PATH); fi
+else
+	if [ -f ../afl-clang-fast -a -f ../afl-llvm-rt.o ]; then set -e; install -m 755 ../afl-clang-fast $${DESTDIR}$(BIN_PATH); ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-fast++; install -m 755 ../afl-llvm-rt.o $${DESTDIR}$(HELPER_PATH); fi
+endif
+	if [ -f ../afl-llvm-rt-32.o ]; then set -e; install -m 755 ../afl-llvm-rt-32.o $${DESTDIR}$(HELPER_PATH); fi
+	if [ -f ../afl-llvm-rt-64.o ]; then set -e; install -m 755 ../afl-llvm-rt-64.o $${DESTDIR}$(HELPER_PATH); fi
+	if [ -f ../compare-transform-pass.so ]; then set -e; install -m 755 ../compare-transform-pass.so $${DESTDIR}$(HELPER_PATH); fi
+	if [ -f ../split-compares-pass.so ]; then set -e; install -m 755 ../split-compares-pass.so $${DESTDIR}$(HELPER_PATH); fi
+	if [ -f ../split-switches-pass.so ]; then set -e; install -m 755 ../split-switches-pass.so $${DESTDIR}$(HELPER_PATH); fi
+	if [ -f ../cmplog-instructions-pass.so ]; then set -e; install -m 755 ../cmplog-*-pass.so $${DESTDIR}$(HELPER_PATH); fi
+	set -e; if [ -f ../afl-clang-fast ] ; then ln -sf ../afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf ../afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang++ ; else ln -sf ../afl-gcc $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf ../afl-gcc $${DESTDIR}$(BIN_PATH)/afl-clang++; fi
+	install -m 644 README.*.md $${DESTDIR}$(DOC_PATH)/
+	install -m 644 -T README.md $${DESTDIR}$(DOC_PATH)/README.llvm_mode.md
+
+vpath  % ..
+%.8: %
+	@echo .TH $* 8 `date "+%Y-%m-%d"` "afl++" > ../$@
+	@echo .SH NAME >> ../$@
+	@echo .B $* >> ../$@
+	@echo >> ../$@
+	@echo .SH SYNOPSIS >> ../$@
+	@../$* -h 2>&1 | head -n 3 | tail -n 1 | sed 's/^\.\///' >> ../$@
+	@echo >> ../$@
+	@echo .SH OPTIONS >> ../$@
+	@echo .nf >> ../$@
+	@../$* -h 2>&1 | tail -n +4 >> ../$@
+	@echo >> ../$@
+	@echo .SH AUTHOR >> ../$@
+	@echo "afl++ was written by Michal \"lcamtuf\" Zalewski and is maintained by Marc \"van Hauser\" Heuse <mh@mh-sec.de>, Heiko \"hexcoder-\" Eissfeldt <heiko.eissfeldt@hexco.de>, Andrea Fioraldi <andreafioraldi@gmail.com> and Dominik Maier <domenukk@gmail.com>" >> ../$@
+	@echo  The homepage of afl++ is: https://github.com/AFLplusplus/AFLplusplus >> ../$@
+	@echo >> ../$@
+	@echo .SH LICENSE >> ../$@
+	@echo Apache License Version 2.0, January 2004 >> ../$@
+	ln -sf afl-clang-fast.8 ../afl-clang-fast++.8
+ifneq "$(AFL_CLANG_FLTO)" ""
+ifeq "$(LLVM_LTO)" "1"
+	ln -sf afl-clang-fast.8 ../afl-clang-lto.8
+	ln -sf afl-clang-fast.8 ../afl-clang-lto++.8
+endif
+endif
+
+clean:
+	rm -f *.o *.so *~ a.out core core.[1-9][0-9]* .test2 test-instr .test-instr0 .test-instr1 *.dwo
+	rm -f $(PROGS) afl-common.o ../afl-clang-fast++ ../afl-clang-lto ../afl-clang-lto++ ../afl-clang*.8 ../ld
diff --git a/llvm_mode/LLVMInsTrim.so.cc b/llvm_mode/LLVMInsTrim.so.cc
index a94eb907..8b23942c 100644
--- a/llvm_mode/LLVMInsTrim.so.cc
+++ b/llvm_mode/LLVMInsTrim.so.cc
@@ -509,10 +509,11 @@ struct InsTrim : public ModulePass {
     if (!be_quiet) {
 
       char modeline[100];
-      snprintf(modeline, sizeof(modeline), "%s%s%s%s",
+      snprintf(modeline, sizeof(modeline), "%s%s%s%s%s",
                getenv("AFL_HARDEN") ? "hardened" : "non-hardened",
                getenv("AFL_USE_ASAN") ? ", ASAN" : "",
                getenv("AFL_USE_MSAN") ? ", MSAN" : "",
+               getenv("AFL_USE_CFISAN") ? ", CFISAN" : "",
                getenv("AFL_USE_UBSAN") ? ", UBSAN" : "");
 
       OKF("Instrumented %u locations (%llu, %llu) (%s mode)\n", total_instr,
diff --git a/llvm_mode/Makefile b/llvm_mode/Makefile
index 9626665c..0b306dde 100644
--- a/llvm_mode/Makefile
+++ b/llvm_mode/Makefile
@@ -1,370 +1,2 @@
-#
-# american fuzzy lop++ - LLVM instrumentation
-# -----------------------------------------
-#
-# Written by Laszlo Szekeres <lszekeres@google.com> and
-#            Michal Zalewski
-#
-# LLVM integration design comes from Laszlo Szekeres.
-#
-# Copyright 2015, 2016 Google Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-
-# For Heiko:
-#TEST_MMAP=1
-HASH=\#
-
-PREFIX      ?= /usr/local
-HELPER_PATH ?= $(PREFIX)/lib/afl
-BIN_PATH    ?= $(PREFIX)/bin
-DOC_PATH    ?= $(PREFIX)/share/doc/afl
-MISC_PATH   ?= $(PREFIX)/share/afl
-MAN_PATH    ?= $(PREFIX)/man/man8
-
-VERSION     = $(shell grep '^$(HASH)define VERSION ' ../config.h | cut -d '"' -f2)
-
-ifeq "$(shell uname)" "OpenBSD"
-  LLVM_CONFIG ?= $(BIN_PATH)/llvm-config
-  HAS_OPT = $(shell test -x $(BIN_PATH)/opt && echo 0 || echo 1)
-  ifeq "$(HAS_OPT)" "1"
-    $(error llvm_mode needs a complete llvm installation (versions 3.8.0 up to 11) -> e.g. "pkg_add llvm-7.0.1p9")
-  endif
-else
-  LLVM_CONFIG ?= llvm-config
-endif
-
-LLVMVER  = $(shell $(LLVM_CONFIG) --version 2>/dev/null )
-LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^3\.[0-7]|^1[2-9]' && echo 1 || echo 0 )
-LLVM_NEW_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^1[0-9]' && echo 1 || echo 0 )
-LLVM_MAJOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/\..*//')
-LLVM_BINDIR = $(shell $(LLVM_CONFIG) --bindir 2>/dev/null)
-LLVM_STDCXX = gnu++11
-LLVM_APPLE = $(shell clang -v 2>&1 | grep -iq apple && echo 1 || echo 0)
-LLVM_LTO   = 0
-
-ifeq "$(LLVMVER)" ""
-  $(warning [!] llvm_mode needs llvm-config, which was not found)
-endif
-
-ifeq "$(LLVM_UNSUPPORTED)" "1"
-  $(warning llvm_mode only supports llvm versions 3.8.0 up to 11)
-endif
-
-ifeq "$(LLVM_MAJOR)" "9"
-  $(info [+] llvm_mode detected llvm 9, enabling neverZero implementation)
-  $(info [+] llvm_mode detected llvm 9, enabling afl-clang-lto LTO implementation)
-  LLVM_LTO = 1
-endif
-
-ifeq "$(LLVM_NEW_API)" "1"
-  $(info [+] llvm_mode detected llvm 10+, enabling neverZero implementation and c++14)
-  $(info [+] llvm_mode detected llvm 9, enabling afl-clang-lto LTO implementation)
-  LLVM_STDCXX = c++14
-  LLVM_LTO = 1
-endif
-
-ifeq "$(LLVM_LTO)" "0"
-  $(info [+] llvm_mode detected llvm < 9, afl-clang-lto LTO will not be build.)
-endif
-
-ifeq "$(LLVM_APPLE)" "1"
-  $(warning llvm_mode will not compile with Xcode clang...)
-endif
-
-# We were using llvm-config --bindir to get the location of clang, but
-# this seems to be busted on some distros, so using the one in $PATH is
-# probably better.
-
-CC         = $(LLVM_BINDIR)/clang
-CXX        = $(LLVM_BINDIR)/clang++
-
-ifeq "$(shell test -e $(CC) || echo 1 )" "1"
-  # llvm-config --bindir may not providing a valid path, so ...
-  ifeq "$(shell test -e '$(BIN_DIR)/clang' && echo 1)" "1"
-    # we found one in the local install directory, lets use these
-    CC         = $(BIN_DIR)/clang
-    CXX        = $(BIN_DIR)/clang++
-  else
-    # hope for the best
-    $(warning we have trouble finding clang/clang++ - llvm-config is not helping us)
-    CC         = clang
-    CXX        = clang++
-  endif
-endif
-
-# sanity check.
-# Are versions of clang --version and llvm-config --version equal?
-CLANGVER = $(shell $(CC) --version | sed -E -ne '/^.*version\ ([0-9]\.[0-9]\.[0-9]).*/s//\1/p')
-
-ifneq "$(CLANGVER)" "$(LLVMVER)"
-  CC = $(shell $(LLVM_CONFIG) --bindir)/clang
-  CXX = $(shell $(LLVM_CONFIG) --bindir)/clang++
-endif
-
-# After we set CC/CXX we can start makefile magic tests
-
-ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -march=native -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
-	CFLAGS_OPT = -march=native
-endif
-
-ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -flto=full -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
-        AFL_CLANG_FLTO ?= -flto=full
-else
- ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -flto=thin -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
-        AFL_CLANG_FLTO ?= -flto=thin
- else
-  ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -flto -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
-        AFL_CLANG_FLTO ?= -flto
-  endif
- endif
-endif
-
-ifneq "$(AFL_CLANG_FLTO)" ""
-ifeq "$(AFL_REAL_LD)" ""
-  AFL_REAL_LD = $(shell readlink /bin/ld 2>/dev/null)
-  ifeq "$(AFL_REAL_LD)" ""
-    AFL_REAL_LD = $(shell readlink /usr/bin/ld 2>/dev/null)
-  endif
-endif
-endif
-
-CFLAGS          ?= -O3 -funroll-loops
-override CFLAGS = -Wall \
-               -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign -I ../include/ \
-               -DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \
-               -DLLVM_BINDIR=\"$(LLVM_BINDIR)\" -DVERSION=\"$(VERSION)\" \
-               -DLLVM_VERSION=\"$(LLVMVER)\"  -DAFL_CLANG_FLTO=\"$(AFL_CLANG_FLTO)\" \
-               -DAFL_REAL_LD=\"$(AFL_REAL_LD)\" -Wno-unused-function
-ifdef AFL_TRACE_PC
-  CFLAGS    += -DUSE_TRACE_PC=1
-endif
-
-CXXFLAGS          ?= -O3 -funroll-loops
-override CXXFLAGS += -Wall -D_FORTIFY_SOURCE=2 -g -I ../include/ \
-                     -DVERSION=\"$(VERSION)\" -Wno-variadic-macros
-
-CLANG_CFL    = `$(LLVM_CONFIG) --cxxflags` -Wl,-znodelete -fno-rtti -fpic $(CXXFLAGS)
-CLANG_LFL    = `$(LLVM_CONFIG) --ldflags` $(LDFLAGS)
-
-
-# User teor2345 reports that this is required to make things work on MacOS X.
-ifeq "$(shell uname)" "Darwin"
-  CLANG_LFL += -Wl,-flat_namespace -Wl,-undefined,suppress
-endif
-
-ifeq "$(shell uname)" "OpenBSD"
-  CLANG_LFL += `$(LLVM_CONFIG) --libdir`/libLLVM.so
-endif
-
-ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -fuse-ld=`command -v ld` -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
-  CFLAGS += -DAFL_CLANG_FUSELD=1
-endif
-
-ifeq "$(shell echo '$(HASH)include <sys/ipc.h>@$(HASH)include <sys/shm.h>@int main() { int _id = shmget(IPC_PRIVATE, 65536, IPC_CREAT | IPC_EXCL | 0600); shmctl(_id, IPC_RMID, 0); return 0;}' | tr @ '\n' | $(CC) -x c - -o .test2 2>/dev/null && echo 1 || echo 0 ; rm -f .test2 )" "1"
-        SHMAT_OK=1
-else
-        SHMAT_OK=0
-        CFLAGS+=-DUSEMMAP=1
-        LDFLAGS += -lrt
-endif
-
-ifeq "$(TEST_MMAP)" "1"
-        SHMAT_OK=0
-        CFLAGS+=-DUSEMMAP=1
-        LDFLAGS += -lrt
-endif
-
-ifndef AFL_TRACE_PC
-  PROGS      = ../afl-clang-fast ../afl-ld ../afl-llvm-pass.so ../afl-llvm-lto-whitelist.so ../afl-llvm-lto-instrumentation.so ../libLLVMInsTrim.so ../afl-llvm-rt.o ../afl-llvm-rt-32.o ../afl-llvm-rt-64.o ../compare-transform-pass.so ../split-compares-pass.so ../split-switches-pass.so ../cmplog-routines-pass.so ../cmplog-instructions-pass.so
-else
-  PROGS      = ../afl-clang-fast ../afl-llvm-rt.o ../afl-llvm-rt-32.o ../afl-llvm-rt-64.o ../compare-transform-pass.so ../split-compares-pass.so ../split-switches-pass.so ../cmplog-routines-pass.so ../cmplog-instructions-pass.so
-endif
-
-# If prerequisites are not given, warn, do not build anything, and exit with code 0
-ifeq "$(LLVMVER)" ""
-  NO_BUILD = 1
-endif
-
-ifneq "$(LLVM_UNSUPPORTED)$(LLVM_APPLE)" "00"
-  NO_BUILD = 1
-endif
-
-ifeq "$(NO_BUILD)" "1"
-  TARGETS = no_build
-else
-  TARGETS = test_shm test_deps $(PROGS) afl-clang-fast.8 test_build all_done
-endif
-
-all: $(TARGETS)
-
-ifeq "$(SHMAT_OK)" "1"
-
-test_shm:
-	@echo "[+] shmat seems to be working."
-	@rm -f .test2
-
-else
-
-test_shm:
-	@echo "[-] shmat seems not to be working, switching to mmap implementation"
-
-endif
-
-no_build:
-	@printf "%b\\n" "\\033[0;31mPrerequisites are not met, skipping build llvm_mode\\033[0m"
-
-test_deps:
-ifndef AFL_TRACE_PC
-	@echo "[*] Checking for working 'llvm-config'..."
- ifneq "$(LLVM_APPLE)" "1"
-	@type $(LLVM_CONFIG) >/dev/null 2>&1 || ( echo "[-] Oops, can't find 'llvm-config'. Install clang or set \$$LLVM_CONFIG or \$$PATH beforehand."; echo "    (Sometimes, the binary will be named llvm-config-3.5 or something like that.)"; exit 1 )
- endif
-else
-	@echo "[!] Note: using -fsanitize=trace-pc mode (this will fail with older LLVM)."
-endif
-	@echo "[*] Checking for working '$(CC)'..."
-	@type $(CC) >/dev/null 2>&1 || ( echo "[-] Oops, can't find '$(CC)'. Make sure that it's in your \$$PATH (or set \$$CC and \$$CXX)."; exit 1 )
-	@echo "[*] Checking for matching versions of '$(CC)' and '$(LLVM_CONFIG)'"
-ifneq "$(CLANGVER)" "$(LLVMVER)"
-	@echo "[!] WARNING: we have llvm-config version $(LLVMVER) and a clang version $(CLANGVER)"
-	@echo "[!] Retrying with the clang compiler from llvm: CC=`llvm-config --bindir`/clang"
-else
-	@echo "[*] We have llvm-config version $(LLVMVER) with a clang version $(CLANGVER), good."
-endif
-	@echo "[*] Checking for '../afl-showmap'..."
-	@test -f ../afl-showmap || ( echo "[-] Oops, can't find '../afl-showmap'. Be sure to compile AFL first."; exit 1 )
-	@echo "[+] All set and ready to build."
-
-afl-common.o: ../src/afl-common.c
-	$(CC) $(CFLAGS) -c $< -o $@ $(LDFLAGS)
-
-../afl-clang-fast: afl-clang-fast.c afl-common.o | test_deps
-	$(CC) $(CFLAGS) $< afl-common.o -o $@ $(LDFLAGS) -DCFLAGS_OPT=\"$(CFLAGS_OPT)\"
-	ln -sf afl-clang-fast ../afl-clang-fast++
-ifneq "$(AFL_CLANG_FLTO)" ""
-ifeq "$(LLVM_LTO)" "1"
-	ln -sf afl-clang-fast ../afl-clang-lto
-	ln -sf afl-clang-fast ../afl-clang-lto++
-endif
-endif
-
-../afl-ld: afl-ld.c
-ifneq "$(AFL_CLANG_FLTO)" ""
-ifeq "$(LLVM_LTO)" "1"
-	$(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
-	ln -sf afl-ld ../ld
-	@rm -f .test-instr
-	@-export AFL_QUIET=1 AFL_PATH=.. PATH="..:$(PATH)" ; ../afl-clang-lto -Wl,--afl -o .test-instr ../test-instr.c && echo "[+] afl-clang-lto and afl-ld seem to work fine :)" || echo "[!] WARNING: clang seems to have a hardcoded "'/bin/ld'" - check README.lto"
-	@rm -f .test-instr
-endif
-endif
-../libLLVMInsTrim.so: LLVMInsTrim.so.cc MarkNodes.cc | test_deps
-	-$(CXX) $(CLANG_CFL) -DLLVMInsTrim_EXPORTS -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< MarkNodes.cc -o $@ $(CLANG_LFL)
-
-../afl-llvm-pass.so: afl-llvm-pass.so.cc | test_deps
-	$(CXX) $(CLANG_CFL) -DLLVMInsTrim_EXPORTS -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL)
-
-../afl-llvm-lto-whitelist.so: afl-llvm-lto-whitelist.so.cc
-ifeq "$(LLVM_LTO)" "1"
-	$(CXX) $(CLANG_CFL) -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL)
-endif
-
-../afl-llvm-lto-instrumentation.so: afl-llvm-lto-instrumentation.so.cc MarkNodes.cc
-ifeq "$(LLVM_LTO)" "1"
-	$(CXX) $(CLANG_CFL) -Wno-writable-strings -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< MarkNodes.cc -o $@ $(CLANG_LFL)
-endif
-
-# laf
-../split-switches-pass.so:	split-switches-pass.so.cc | test_deps
-	$(CXX) $(CLANG_CFL) -shared $< -o $@ $(CLANG_LFL)
-../compare-transform-pass.so:	compare-transform-pass.so.cc | test_deps
-	$(CXX) $(CLANG_CFL) -shared $< -o $@ $(CLANG_LFL)
-../split-compares-pass.so:	split-compares-pass.so.cc | test_deps
-	$(CXX) $(CLANG_CFL) -shared $< -o $@ $(CLANG_LFL)
-# /laf
-
-../cmplog-routines-pass.so:	cmplog-routines-pass.cc | test_deps
-	$(CXX) $(CLANG_CFL) -shared $< -o $@ $(CLANG_LFL)
-
-../cmplog-instructions-pass.so:	cmplog-instructions-pass.cc | test_deps
-	$(CXX) $(CLANG_CFL) -shared $< -o $@ $(CLANG_LFL)
-
-../afl-llvm-rt.o: afl-llvm-rt.o.c | test_deps
-	$(CC) $(CFLAGS) -fPIC -c $< -o $@
-
-../afl-llvm-rt-32.o: afl-llvm-rt.o.c | test_deps
-	@printf "[*] Building 32-bit variant of the runtime (-m32)... "
-	@$(CC) $(CFLAGS) -m32 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
-
-../afl-llvm-rt-64.o: afl-llvm-rt.o.c | test_deps
-	@printf "[*] Building 64-bit variant of the runtime (-m64)... "
-	@$(CC) $(CFLAGS) -m64 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
-
-test_build: $(PROGS)
-	@echo "[*] Testing the CC wrapper and instrumentation output..."
-	unset AFL_USE_ASAN AFL_USE_MSAN AFL_INST_RATIO; AFL_QUIET=1 AFL_PATH=. AFL_CC=$(CC) AFL_LLVM_LAF_SPLIT_SWITCHES=1 AFL_LLVM_LAF_TRANSFORM_COMPARES=1 AFL_LLVM_LAF_SPLIT_COMPARES=1 ../afl-clang-fast $(CFLAGS) ../test-instr.c -o test-instr $(LDFLAGS)
-	ASAN_OPTIONS=detect_leaks=0 ../afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null
-	echo 1 | ASAN_OPTIONS=detect_leaks=0 ../afl-showmap -m none -q -o .test-instr1 ./test-instr
-	@rm -f test-instr
-	@cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation does not seem to be behaving correctly!"; echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue."; echo; exit 1; fi
-	@echo "[+] All right, the instrumentation seems to be working!"
-
-all_done: test_build
-	@echo "[+] All done! You can now use '../afl-clang-fast' to compile programs."
-
-.NOTPARALLEL: clean
-
-install: all
-	install -d -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) $${DESTDIR}$(DOC_PATH) $${DESTDIR}$(MISC_PATH)
-ifndef AFL_TRACE_PC
-	if [ -f ../afl-clang-fast -a -f ../libLLVMInsTrim.so -a -f ../afl-llvm-rt.o ]; then set -e; install -m 755 ../afl-clang-fast $${DESTDIR}$(BIN_PATH); ln -sf ../afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-fast++; install -m 755 ../libLLVMInsTrim.so ../afl-llvm-pass.so ../afl-llvm-rt.o $${DESTDIR}$(HELPER_PATH); fi
-	if [ -f afl-clang-lto -a -f afl-ld ]; then set -e; install -m 755 afl-clang-lto $${DESTDIR}$(BIN_PATH); ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-lto++; install -m 755 afl-ld $${DESTDIR}$(HELPER_PATH); ln -sf afl-ld $${DESTDIR}$(HELPER_PATH)/ld; install -m 755 afl-llvm-lto-instrumentation.so $${DESTDIR}$(HELPER_PATH); install -m 755 afl-llvm-lto-whitelist.so $${DESTDIR}$(HELPER_PATH); fi
-else
-	if [ -f afl-clang-fast -a -f afl-llvm-rt.o ]; then set -e; install -m 755 afl-clang-fast $${DESTDIR}$(BIN_PATH); ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-fast++; install -m 755 afl-llvm-rt.o $${DESTDIR}$(HELPER_PATH); fi
-endif
-	if [ -f ../afl-llvm-rt-32.o ]; then set -e; install -m 755 ../afl-llvm-rt-32.o $${DESTDIR}$(HELPER_PATH); fi
-	if [ -f ../afl-llvm-rt-64.o ]; then set -e; install -m 755 ../afl-llvm-rt-64.o $${DESTDIR}$(HELPER_PATH); fi
-	if [ -f ../compare-transform-pass.so ]; then set -e; install -m 755 ../compare-transform-pass.so $${DESTDIR}$(HELPER_PATH); fi
-	if [ -f ../split-compares-pass.so ]; then set -e; install -m 755 ../split-compares-pass.so $${DESTDIR}$(HELPER_PATH); fi
-	if [ -f ../split-switches-pass.so ]; then set -e; install -m 755 ../split-switches-pass.so $${DESTDIR}$(HELPER_PATH); fi
-	if [ -f ../cmplog-instructions-pass.so ]; then set -e; install -m 755 ../cmplog-*-pass.so $${DESTDIR}$(HELPER_PATH); fi
-	set -e; if [ -f ../afl-clang-fast ] ; then ln -sf ../afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf ../afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang++ ; else ln -sf ../afl-gcc $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf ../afl-gcc $${DESTDIR}$(BIN_PATH)/afl-clang++; fi
-	install -m 644 README.*.md $${DESTDIR}$(DOC_PATH)/
-	install -m 644 -T README.md $${DESTDIR}$(DOC_PATH)/README.llvm_mode.md
-
-vpath  % ..
-%.8: %
-	@echo .TH $* 8 `date "+%Y-%m-%d"` "afl++" > ../$@
-	@echo .SH NAME >> ../$@
-	@echo .B $* >> ../$@
-	@echo >> ../$@
-	@echo .SH SYNOPSIS >> ../$@
-	@../$* -h 2>&1 | head -n 3 | tail -n 1 | sed 's/^\.\///' >> ../$@
-	@echo >> ../$@
-	@echo .SH OPTIONS >> ../$@
-	@echo .nf >> ../$@
-	@../$* -h 2>&1 | tail -n +4 >> ../$@
-	@echo >> ../$@
-	@echo .SH AUTHOR >> ../$@
-	@echo "afl++ was written by Michal \"lcamtuf\" Zalewski and is maintained by Marc \"van Hauser\" Heuse <mh@mh-sec.de>, Heiko \"hexcoder-\" Eissfeldt <heiko.eissfeldt@hexco.de>, Andrea Fioraldi <andreafioraldi@gmail.com> and Dominik Maier <domenukk@gmail.com>" >> ../$@
-	@echo  The homepage of afl++ is: https://github.com/AFLplusplus/AFLplusplus >> ../$@
-	@echo >> ../$@
-	@echo .SH LICENSE >> ../$@
-	@echo Apache License Version 2.0, January 2004 >> ../$@
-	ln -sf afl-clang-fast.8 ../afl-clang-fast++.8
-ifneq "$(AFL_CLANG_FLTO)" ""
-ifeq "$(LLVM_LTO)" "1"
-	ln -sf afl-clang-fast.8 ../afl-clang-lto.8
-	ln -sf afl-clang-fast.8 ../afl-clang-lto++.8
-endif
-endif
-
-clean:
-	rm -f *.o *.so *~ a.out core core.[1-9][0-9]* .test2 test-instr .test-instr0 .test-instr1 *.dwo
-	rm -f $(PROGS) afl-common.o ../afl-clang-fast++ ../afl-clang-lto ../afl-clang-lto++ ../afl-clang*.8 ../ld
+all:
+	@echo please use GNU make, thanks!
diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c
index 34df5671..5fc09252 100644
--- a/llvm_mode/afl-clang-fast.c
+++ b/llvm_mode/afl-clang-fast.c
@@ -48,7 +48,6 @@ static u8   debug;
 static u8   cwd[4096];
 static u8   cmplog_mode;
 u8          use_stdin = 0;                                         /* dummy */
-u8          be_quiet = 0;
 
 u8 *getthecwd() {
 
@@ -135,9 +134,9 @@ static void find_obj(u8 *argv0) {
 
 /* Copy argv to cc_params, making the necessary edits. */
 
-static void edit_params(u32 argc, char **argv) {
+static void edit_params(u32 argc, char **argv, char **envp) {
 
-  u8  fortify_set = 0, asan_set = 0, x_set = 0, maybe_linking = 1, bit_mode = 0;
+  u8  fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0;
   u8  has_llvm_config = 0;
   u8 *name;
 
@@ -324,8 +323,6 @@ static void edit_params(u32 argc, char **argv) {
 
   /* Detect stray -v calls from ./configure scripts. */
 
-  if (argc == 1 && !strcmp(argv[1], "-v")) maybe_linking = 0;
-
   while (--argc) {
 
     u8 *cur = *(++argv);
@@ -336,16 +333,11 @@ static void edit_params(u32 argc, char **argv) {
 
     if (!strcmp(cur, "-x")) x_set = 1;
 
-    if (!strcmp(cur, "-c") || !strcmp(cur, "-S") || !strcmp(cur, "-E"))
-      maybe_linking = 0;
-
     if (!strcmp(cur, "-fsanitize=address") || !strcmp(cur, "-fsanitize=memory"))
       asan_set = 1;
 
     if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1;
 
-    if (!strcmp(cur, "-shared")) maybe_linking = 0;
-
     if (!strcmp(cur, "-Wl,-z,defs") || !strcmp(cur, "-Wl,--no-undefined"))
       continue;
 
@@ -395,6 +387,22 @@ static void edit_params(u32 argc, char **argv) {
 
   }
 
+  if (getenv("AFL_USE_CFISAN")) {
+
+    if (!lto_mode) {
+
+      uint32_t i = 0, found = 0;
+      while (envp[i] != NULL && !found)
+        if (strncmp("-flto", envp[i++], 5) == 0) found = 1;
+      if (!found) cc_params[cc_par_cnt++] = "-flto";
+
+    }
+
+    cc_params[cc_par_cnt++] = "-fsanitize=cfi";
+    cc_params[cc_par_cnt++] = "-fvisibility=hidden";
+
+  }
+
 #ifdef USE_TRACE_PC
 
   if (getenv("USE_TRACE_PC") || getenv("AFL_USE_TRACE_PC") ||
@@ -483,44 +491,40 @@ static void edit_params(u32 argc, char **argv) {
 #endif                                                        /* ^__APPLE__ */
       "_I(); } while (0)";
 
-  // if (maybe_linking) {
+  if (x_set) {
 
-    if (x_set) {
+    cc_params[cc_par_cnt++] = "-x";
+    cc_params[cc_par_cnt++] = "none";
 
-      cc_params[cc_par_cnt++] = "-x";
-      cc_params[cc_par_cnt++] = "none";
-
-    }
+  }
 
 #ifndef __ANDROID__
-    switch (bit_mode) {
+  switch (bit_mode) {
 
-      case 0:
-        cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-rt.o", obj_path);
-        break;
+    case 0:
+      cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-rt.o", obj_path);
+      break;
 
-      case 32:
-        cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-rt-32.o", obj_path);
+    case 32:
+      cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-rt-32.o", obj_path);
 
-        if (access(cc_params[cc_par_cnt - 1], R_OK))
-          FATAL("-m32 is not supported by your compiler");
+      if (access(cc_params[cc_par_cnt - 1], R_OK))
+        FATAL("-m32 is not supported by your compiler");
 
-        break;
+      break;
 
-      case 64:
-        cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-rt-64.o", obj_path);
+    case 64:
+      cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-rt-64.o", obj_path);
 
-        if (access(cc_params[cc_par_cnt - 1], R_OK))
-          FATAL("-m64 is not supported by your compiler");
+      if (access(cc_params[cc_par_cnt - 1], R_OK))
+        FATAL("-m64 is not supported by your compiler");
 
-        break;
+      break;
 
-    }
+  }
 
 #endif
 
-  // }
-
   cc_params[cc_par_cnt] = NULL;
 
 }
@@ -596,6 +600,7 @@ int main(int argc, char **argv, char **envp) {
             "AFL_USE_ASAN: activate address sanitizer\n"
             "AFL_USE_MSAN: activate memory sanitizer\n"
             "AFL_USE_UBSAN: activate undefined behaviour sanitizer\n"
+            "AFL_USE_CFISAN: activate control flow sanitizer\n"
             "AFL_LLVM_WHITELIST: enable whitelisting (selective "
             "instrumentation)\n"
             "AFL_LLVM_NOT_ZERO: use cycling trace counters that skip zero\n"
@@ -685,7 +690,7 @@ int main(int argc, char **argv, char **envp) {
   find_obj(argv[0]);
 #endif
 
-  edit_params(argc, argv);
+  edit_params(argc, argv, envp);
 
   if (debug) {
 
diff --git a/llvm_mode/afl-llvm-lto-instrumentation.so.cc b/llvm_mode/afl-llvm-lto-instrumentation.so.cc
index febb8950..4bc16f17 100644
--- a/llvm_mode/afl-llvm-lto-instrumentation.so.cc
+++ b/llvm_mode/afl-llvm-lto-instrumentation.so.cc
@@ -392,10 +392,11 @@ bool AFLLTOPass::runOnModule(Module &M) {
     else {
 
       char modeline[100];
-      snprintf(modeline, sizeof(modeline), "%s%s%s%s",
+      snprintf(modeline, sizeof(modeline), "%s%s%s%s%s",
                getenv("AFL_HARDEN") ? "hardened" : "non-hardened",
                getenv("AFL_USE_ASAN") ? ", ASAN" : "",
                getenv("AFL_USE_MSAN") ? ", MSAN" : "",
+               getenv("AFL_USE_CFISAN") ? ", CFISAN" : "",
                getenv("AFL_USE_UBSAN") ? ", UBSAN" : "");
       OKF("Instrumented %u locations with no collisions (on average %llu "
           "collisions would be in afl-gcc/afl-clang-fast) (%s mode).",
diff --git a/llvm_mode/afl-llvm-pass.so.cc b/llvm_mode/afl-llvm-pass.so.cc
index fefd9edd..5fe98d8b 100644
--- a/llvm_mode/afl-llvm-pass.so.cc
+++ b/llvm_mode/afl-llvm-pass.so.cc
@@ -131,14 +131,40 @@ class AFLCoverage : public ModulePass {
 
 char AFLCoverage::ID = 0;
 
+/* needed up to 3.9.0 */
+#if LLVM_VERSION_MAJOR == 3 && \
+    (LLVM_VERSION_MINOR < 9 || \
+     (LLVM_VERSION_MINOR == 9 && LLVM_VERSION_PATCH < 1))
+uint64_t PowerOf2Ceil(unsigned in) {
+
+  uint64_t in64 = in - 1;
+  in64 |= (in64 >> 1);
+  in64 |= (in64 >> 2);
+  in64 |= (in64 >> 4);
+  in64 |= (in64 >> 8);
+  in64 |= (in64 >> 16);
+  in64 |= (in64 >> 32);
+  return in64 + 1;
+
+}
+
+#endif
+
+/* #if LLVM_VERSION_STRING >= "4.0.1" */
+#if LLVM_VERSION_MAJOR >= 4 || \
+    (LLVM_VERSION_MAJOR == 4 && LLVM_VERSION_PATCH >= 1)
+#define AFL_HAVE_VECTOR_INTRINSICS 1
+#endif
 bool AFLCoverage::runOnModule(Module &M) {
 
   LLVMContext &C = M.getContext();
 
   IntegerType *Int8Ty = IntegerType::getInt8Ty(C);
   IntegerType *Int32Ty = IntegerType::getInt32Ty(C);
+#ifdef AFL_HAVE_VECTOR_INTRINSICS
   IntegerType *IntLocTy =
       IntegerType::getIntNTy(C, sizeof(PREV_LOC_T) * CHAR_BIT);
+#endif
   struct timeval  tv;
   struct timezone tz;
   u32             rand_seed;
@@ -179,27 +205,39 @@ bool AFLCoverage::runOnModule(Module &M) {
   char *neverZero_counters_str = getenv("AFL_LLVM_NOT_ZERO");
 #endif
 
-  /* Decide previous location vector size (must be a power of two) */
+  unsigned PrevLocSize;
 
   char *ngram_size_str = getenv("AFL_LLVM_NGRAM_SIZE");
   if (!ngram_size_str) ngram_size_str = getenv("AFL_NGRAM_SIZE");
 
+#ifdef AFL_HAVE_VECTOR_INTRINSICS
+  /* Decide previous location vector size (must be a power of two) */
+  VectorType *PrevLocTy;
+
   if (ngram_size_str)
     if (sscanf(ngram_size_str, "%u", &ngram_size) != 1 || ngram_size < 2 ||
         ngram_size > MAX_NGRAM_SIZE)
       FATAL(
-          "Bad value of AFL_NGRAM_SIZE (must be between 2 and MAX_NGRAM_SIZE)");
+          "Bad value of AFL_NGRAM_SIZE (must be between 2 and MAX_NGRAM_SIZE "
+          "(%u))",
+          MAX_NGRAM_SIZE);
 
-  unsigned PrevLocSize;
   if (ngram_size == 1) ngram_size = 0;
   if (ngram_size)
     PrevLocSize = ngram_size - 1;
   else
+#else
+  if (ngram_size_str)
+    FATAL(
+        "Sorry, n-gram branch coverage is not supported with llvm version %s!",
+        LLVM_VERSION_STRING);
+#endif
     PrevLocSize = 1;
-  uint64_t    PrevLocVecSize = PowerOf2Ceil(PrevLocSize);
-  VectorType *PrevLocTy;
 
+#ifdef AFL_HAVE_VECTOR_INTRINSICS
+  uint64_t PrevLocVecSize = PowerOf2Ceil(PrevLocSize);
   if (ngram_size) PrevLocTy = VectorType::get(IntLocTy, PrevLocVecSize);
+#endif
 
   /* Get globals for the SHM region and the previous location. Note that
      __afl_prev_loc is thread-local. */
@@ -209,6 +247,7 @@ bool AFLCoverage::runOnModule(Module &M) {
                          GlobalValue::ExternalLinkage, 0, "__afl_area_ptr");
   GlobalVariable *AFLPrevLoc;
 
+#ifdef AFL_HAVE_VECTOR_INTRINSICS
   if (ngram_size)
 #ifdef __ANDROID__
     AFLPrevLoc = new GlobalVariable(
@@ -222,15 +261,17 @@ bool AFLCoverage::runOnModule(Module &M) {
         /* AddressSpace */ 0, /* IsExternallyInitialized */ false);
 #endif
   else
+#endif
 #ifdef __ANDROID__
     AFLPrevLoc = new GlobalVariable(
         M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc");
 #else
-    AFLPrevLoc = new GlobalVariable(
-        M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc", 0,
-        GlobalVariable::GeneralDynamicTLSModel, 0, false);
+  AFLPrevLoc = new GlobalVariable(
+      M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc", 0,
+      GlobalVariable::GeneralDynamicTLSModel, 0, false);
 #endif
 
+#ifdef AFL_HAVE_VECTOR_INTRINSICS
   /* Create the vector shuffle mask for updating the previous block history.
      Note that the first element of the vector will store cur_loc, so just set
      it to undef to allow the optimizer to do its thing. */
@@ -244,6 +285,7 @@ bool AFLCoverage::runOnModule(Module &M) {
     PrevLocShuffle.push_back(ConstantInt::get(Int32Ty, PrevLocSize));
 
   Constant *PrevLocShuffleMask = ConstantVector::get(PrevLocShuffle);
+#endif
 
   // other constants we need
   ConstantInt *Zero = ConstantInt::get(Int8Ty, 0);
@@ -420,9 +462,11 @@ bool AFLCoverage::runOnModule(Module &M) {
 
       ConstantInt *CurLoc;
 
+#ifdef AFL_HAVE_VECTOR_INTRINSICS
       if (ngram_size)
         CurLoc = ConstantInt::get(IntLocTy, cur_loc);
       else
+#endif
         CurLoc = ConstantInt::get(Int32Ty, cur_loc);
 
       /* Load prev_loc */
@@ -431,6 +475,7 @@ bool AFLCoverage::runOnModule(Module &M) {
       PrevLoc->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
       Value *PrevLocTrans;
 
+#ifdef AFL_HAVE_VECTOR_INTRINSICS
       /* "For efficiency, we propose to hash the tuple as a key into the
          hit_count map as (prev_block_trans << 1) ^ curr_block_trans, where
          prev_block_trans = (block_trans_1 ^ ... ^ block_trans_(n-1)" */
@@ -438,6 +483,7 @@ bool AFLCoverage::runOnModule(Module &M) {
       if (ngram_size)
         PrevLocTrans = IRB.CreateXorReduce(PrevLoc);
       else
+#endif
         PrevLocTrans = IRB.CreateZExt(PrevLoc, IRB.getInt32Ty());
 
       /* Load SHM pointer */
@@ -446,11 +492,13 @@ bool AFLCoverage::runOnModule(Module &M) {
       MapPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
 
       Value *MapPtrIdx;
+#ifdef AFL_HAVE_VECTOR_INTRINSICS
       if (ngram_size)
         MapPtrIdx = IRB.CreateGEP(
             MapPtr,
             IRB.CreateZExt(IRB.CreateXor(PrevLocTrans, CurLoc), Int32Ty));
       else
+#endif
         MapPtrIdx = IRB.CreateGEP(MapPtr, IRB.CreateXor(PrevLocTrans, CurLoc));
 
       /* Update bitmap */
@@ -536,6 +584,7 @@ bool AFLCoverage::runOnModule(Module &M) {
 
       StoreInst *Store;
 
+#ifdef AFL_HAVE_VECTOR_INTRINSICS
       if (ngram_size) {
 
         Value *ShuffledPrevLoc = IRB.CreateShuffleVector(
@@ -546,7 +595,10 @@ bool AFLCoverage::runOnModule(Module &M) {
         Store = IRB.CreateStore(UpdatedPrevLoc, AFLPrevLoc);
         Store->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
 
-      } else {
+      } else
+
+#endif
+      {
 
         Store = IRB.CreateStore(ConstantInt::get(Int32Ty, cur_loc >> 1),
                                 AFLPrevLoc);
@@ -568,10 +620,11 @@ bool AFLCoverage::runOnModule(Module &M) {
     else {
 
       char modeline[100];
-      snprintf(modeline, sizeof(modeline), "%s%s%s%s",
+      snprintf(modeline, sizeof(modeline), "%s%s%s%s%s",
                getenv("AFL_HARDEN") ? "hardened" : "non-hardened",
                getenv("AFL_USE_ASAN") ? ", ASAN" : "",
                getenv("AFL_USE_MSAN") ? ", MSAN" : "",
+               getenv("AFL_USE_CFISAN") ? ", CFISAN" : "",
                getenv("AFL_USE_UBSAN") ? ", UBSAN" : "");
       OKF("Instrumented %u locations (%s mode, ratio %u%%).", inst_blocks,
           modeline, inst_ratio);
diff --git a/llvm_mode/llvm-ngram-coverage.h b/llvm_mode/llvm-ngram-coverage.h
index 4459bcd7..488b4fe7 100644
--- a/llvm_mode/llvm-ngram-coverage.h
+++ b/llvm_mode/llvm-ngram-coverage.h
@@ -12,7 +12,7 @@ typedef u64 PREV_LOC_T;
 #endif
 
 /* Maximum ngram size */
-#define MAX_NGRAM_SIZE 128
+#define MAX_NGRAM_SIZE 128U
 
 #endif
 
diff --git a/qbdi_mode/build.sh b/qbdi_mode/build.sh
index c2912e94..e3786f40 100755
--- a/qbdi_mode/build.sh
+++ b/qbdi_mode/build.sh
@@ -52,6 +52,6 @@ ${compiler_prefix}${CC} -shared -o libdemo.so demo-so.c -w -g
 echo "[+] Building afl-fuzz for Android"
 # build afl-fuzz
 cd ..
-${compiler_prefix}${CC} -DANDROID_DISABLE_FANCY=1 -O3 -funroll-loops -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign -I include/ -DAFL_PATH=\"/usr/local/lib/afl\" -DBIN_PATH=\"/usr/local/bin\" -DDOC_PATH=\"/usr/local/share/doc/afl\" -Wno-unused-function src/afl-fuzz-misc.c src/afl-fuzz-extras.c src/afl-fuzz-queue.c src/afl-fuzz-one.c src/afl-fuzz-python.c src/afl-fuzz-stats.c src/afl-fuzz-init.c src/afl-fuzz.c src/afl-fuzz-bitmap.c src/afl-fuzz-run.c src/afl-fuzz-globals.c src/afl-common.c src/afl-sharedmem.c src/afl-forkserver.c -o qbdi_mode/afl-fuzz  -ldl -w
+${compiler_prefix}${CC} -DANDROID_DISABLE_FANCY=1 -O3 -funroll-loops -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign -I include/ -DAFL_PATH=\"/usr/local/lib/afl\" -DBIN_PATH=\"/usr/local/bin\" -DDOC_PATH=\"/usr/local/share/doc/afl\" -Wno-unused-function src/afl-fuzz-misc.c src/afl-fuzz-extras.c src/afl-fuzz-queue.c src/afl-fuzz-one.c src/afl-fuzz-python.c src/afl-fuzz-stats.c src/afl-fuzz-init.c src/afl-fuzz.c src/afl-fuzz-bitmap.c src/afl-fuzz-run.c src/afl-fuzz-state.c src/afl-common.c src/afl-sharedmem.c src/afl-forkserver.c -o qbdi_mode/afl-fuzz  -ldl -w
 
 echo "[+] All done. Enjoy!"
diff --git a/qemu_mode/build_qemu_support.sh b/qemu_mode/build_qemu_support.sh
index bd42c58e..118f6ebd 100755
--- a/qemu_mode/build_qemu_support.sh
+++ b/qemu_mode/build_qemu_support.sh
@@ -174,6 +174,8 @@ patch -p1 <../patches/configure.diff || exit 1
 patch -p1 <../patches/tcg-runtime.diff || exit 1
 patch -p1 <../patches/tcg-runtime-head.diff || exit 1
 patch -p1 <../patches/translator.diff || exit 1
+patch -p1 <../patches/__init__.py.diff || exit 1
+patch -p1 <../patches/make_strncpy_safe.diff || exit 1
 
 echo "[+] Patching done."
 
diff --git a/qemu_mode/patches/__init__.py.diff b/qemu_mode/patches/__init__.py.diff
new file mode 100644
index 00000000..7e189b99
--- /dev/null
+++ b/qemu_mode/patches/__init__.py.diff
@@ -0,0 +1,17 @@
+--- a/scripts/tracetool/__init__.py	2020-03-28 13:42:21.937700726 +0100
++++ b/scripts/tracetool/__init__.py	2020-03-28 13:41:50.991034257 +0100
+@@ -447,12 +447,12 @@
+     import tracetool
+ 
+     format = str(format)
+-    if len(format) is 0:
++    if len(format) == 0:
+         raise TracetoolError("format not set")
+     if not tracetool.format.exists(format):
+         raise TracetoolError("unknown format: %s" % format)
+ 
+-    if len(backends) is 0:
++    if len(backends) == 0:
+         raise TracetoolError("no backends specified")
+     for backend in backends:
+         if not tracetool.backend.exists(backend):
diff --git a/qemu_mode/patches/afl-qemu-cpu-inl.h b/qemu_mode/patches/afl-qemu-cpu-inl.h
index 9fdc23ea..3bd107d7 100644
--- a/qemu_mode/patches/afl-qemu-cpu-inl.h
+++ b/qemu_mode/patches/afl-qemu-cpu-inl.h
@@ -413,7 +413,7 @@ void afl_forkserver(CPUState *cpu) {
 void afl_persistent_loop(void) {
 
   static u32            cycle_cnt;
-  static struct afl_tsl exit_cmd_tsl = {{-1, 0, 0, 0}, NULL};
+  static struct afl_tsl exit_cmd_tsl = {{-1, 0, 0, 0}, '\0'};
 
   if (!afl_fork_child) return;
 
diff --git a/qemu_mode/patches/afl-qemu-tcg-inl.h b/qemu_mode/patches/afl-qemu-tcg-inl.h
index 430574e5..f7c662db 100644
--- a/qemu_mode/patches/afl-qemu-tcg-inl.h
+++ b/qemu_mode/patches/afl-qemu-tcg-inl.h
@@ -30,6 +30,7 @@
    have a look at afl-showmap.c.
 
  */
+void afl_gen_tcg_plain_call(void *func);
 
 void afl_gen_tcg_plain_call(void *func) {
 
diff --git a/qemu_mode/patches/make_strncpy_safe.diff b/qemu_mode/patches/make_strncpy_safe.diff
new file mode 100644
index 00000000..38c7d248
--- /dev/null
+++ b/qemu_mode/patches/make_strncpy_safe.diff
@@ -0,0 +1,31 @@
+--- a/util/qemu-sockets.c	2020-03-28 13:55:09.511029429 +0100
++++ b/util/qemu-sockets.c	2020-03-28 14:01:12.147693937 +0100
+@@ -877,7 +877,7 @@
+ 
+     memset(&un, 0, sizeof(un));
+     un.sun_family = AF_UNIX;
+-    strncpy(un.sun_path, path, sizeof(un.sun_path));
++    strncpy(un.sun_path, path, sizeof(un.sun_path) - 1);
+ 
+     if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) {
+         error_setg_errno(errp, errno, "Failed to bind socket to %s", path);
+@@ -922,7 +922,7 @@
+ 
+     memset(&un, 0, sizeof(un));
+     un.sun_family = AF_UNIX;
+-    strncpy(un.sun_path, saddr->path, sizeof(un.sun_path));
++    strncpy(un.sun_path, saddr->path, sizeof(un.sun_path) - 1);
+ 
+     /* connect to peer */
+     do {
+--- a/block/sheepdog.c	2020-03-28 14:01:57.164360270 +0100
++++ b/block/sheepdog.c	2020-03-28 14:02:52.781026597 +0100
+@@ -1236,7 +1236,7 @@
+      * don't want the send_req to read uninitialized data.
+      */
+     strncpy(buf, filename, SD_MAX_VDI_LEN);
+-    strncpy(buf + SD_MAX_VDI_LEN, tag, SD_MAX_VDI_TAG_LEN);
++    strncpy(buf + SD_MAX_VDI_LEN, tag, SD_MAX_VDI_TAG_LEN - 1);
+ 
+     memset(&hdr, 0, sizeof(hdr));
+     if (lock) {
diff --git a/qemu_mode/unsigaction/GNUmakefile b/qemu_mode/unsigaction/GNUmakefile
new file mode 100644
index 00000000..31fa8c55
--- /dev/null
+++ b/qemu_mode/unsigaction/GNUmakefile
@@ -0,0 +1,34 @@
+#
+# american fuzzy lop++ - unsigaction
+# --------------------------------
+#
+# Written by Andrea Fioraldi <andreafioraldi@gmail.com>
+#
+# Copyright 2019-2020 Andrea Fioraldi. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+
+ifndef AFL_NO_X86
+
+all: lib_i386 lib_amd64
+
+lib_i386:
+	@$(CC) -m32 -fPIC -shared unsigaction.c -o unsigaction32.so 2>/dev/null ; if [ "$$?" = "0" ]; then echo "unsigaction32 build success"; else echo "unsigaction32 build failure (that's fine)"; fi
+
+lib_amd64:
+	$(CC) -fPIC -shared unsigaction.c -o unsigaction64.so
+
+clean:
+	rm -f unsigaction32.so unsigaction64.so
+
+else
+
+all:
+	@echo "[!] Note: skipping compilation of unsigaction (AFL_NO_X86 set)."
+
+endif
diff --git a/qemu_mode/unsigaction/Makefile b/qemu_mode/unsigaction/Makefile
index 31fa8c55..0b306dde 100644
--- a/qemu_mode/unsigaction/Makefile
+++ b/qemu_mode/unsigaction/Makefile
@@ -1,34 +1,2 @@
-#
-# american fuzzy lop++ - unsigaction
-# --------------------------------
-#
-# Written by Andrea Fioraldi <andreafioraldi@gmail.com>
-#
-# Copyright 2019-2020 Andrea Fioraldi. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-
-ifndef AFL_NO_X86
-
-all: lib_i386 lib_amd64
-
-lib_i386:
-	@$(CC) -m32 -fPIC -shared unsigaction.c -o unsigaction32.so 2>/dev/null ; if [ "$$?" = "0" ]; then echo "unsigaction32 build success"; else echo "unsigaction32 build failure (that's fine)"; fi
-
-lib_amd64:
-	$(CC) -fPIC -shared unsigaction.c -o unsigaction64.so
-
-clean:
-	rm -f unsigaction32.so unsigaction64.so
-
-else
-
 all:
-	@echo "[!] Note: skipping compilation of unsigaction (AFL_NO_X86 set)."
-
-endif
+	@echo please use GNU make, thanks!
diff --git a/src/README.md b/src/README.md
new file mode 100644
index 00000000..6da534c3
--- /dev/null
+++ b/src/README.md
@@ -0,0 +1,24 @@
+# Source Folder
+
+Quick explanation about the files here:
+
+- `afl-analyze.c`		- afl-analyze binary tool
+- `afl-as.c`		- afl-as binary tool
+- `afl-gotcpu.c`		- afl-gotcpu binary tool
+- `afl-showmap.c`		- afl-showmap binary tool
+- `afl-tmin.c`		- afl-tmin binary tool
+- `afl-fuzz.c`		- afl-fuzz binary tool (just main() and usage())
+- `afl-fuzz-bitmap.c`	- afl-fuzz bitmap handling
+- `afl-fuzz-extras.c`	- afl-fuzz the *extra* function calls
+- `afl-fuzz-state.c`	- afl-fuzz state and globals
+- `afl-fuzz-init.c`		- afl-fuzz initialization
+- `afl-fuzz-misc.c`		- afl-fuzz misc functions
+- `afl-fuzz-one.c`          - afl-fuzz fuzzer_one big loop, this is where the mutation is happening
+- `afl-fuzz-python.c`	- afl-fuzz the python mutator extension
+- `afl-fuzz-queue.c`	- afl-fuzz handling the queue
+- `afl-fuzz-run.c`		- afl-fuzz running the target
+- `afl-fuzz-stats.c`	- afl-fuzz writing the statistics file
+- `afl-gcc.c`		- afl-gcc binary tool (deprecated)
+- `afl-common.c`		- common functions, used by afl-analyze, afl-fuzz, afl-showmap and afl-tmin
+- `afl-forkserver.c`	- forkserver implementation, used by afl-fuzz and afl-tmin
+afl-sharedmem.c		- sharedmem implementation, used by afl-fuzz and afl-tmin
diff --git a/src/README.src b/src/README.src
deleted file mode 100644
index 244f5ddd..00000000
--- a/src/README.src
+++ /dev/null
@@ -1,22 +0,0 @@
-Quick explanation about the files here:
-
-afl-analyze.c		- afl-analyze binary tool
-afl-as.c		- afl-as binary tool
-afl-gotcpu.c		- afl-gotcpu binary tool
-afl-showmap.c		- afl-showmap binary tool
-afl-tmin.c		- afl-tmin binary tool
-afl-fuzz.c		- afl-fuzz binary tool (just main() and usage())
-afl-fuzz-bitmap.c	- afl-fuzz bitmap handling
-afl-fuzz-extras.c	- afl-fuzz the *extra* function calls
-afl-fuzz-globals.c	- afl-fuzz global variables
-afl-fuzz-init.c		- afl-fuzz initialization
-afl-fuzz-misc.c		- afl-fuzz misc functions
-afl-fuzz-one.c          - afl-fuzz fuzzer_one big loop, this is where the mutation is happening
-afl-fuzz-python.c	- afl-fuzz the python mutator extension
-afl-fuzz-queue.c	- afl-fuzz handling the queue
-afl-fuzz-run.c		- afl-fuzz running the target
-afl-fuzz-stats.c	- afl-fuzz writing the statistics file
-afl-gcc.c		- afl-gcc binary tool (deprecated)
-afl-common.c		- common functions, used by afl-analyze, afl-fuzz, afl-showmap and afl-tmin
-afl-forkserver.c	- forkserver implementation, used by afl-fuzz and afl-tmin
-afl-sharedmem.c		- sharedmem implementation, used by afl-fuzz and afl-tmin
diff --git a/src/afl-analyze.c b/src/afl-analyze.c
index d509c43e..427fbe6d 100644
--- a/src/afl-analyze.c
+++ b/src/afl-analyze.c
@@ -60,8 +60,7 @@ static s32 child_pid;                  /* PID of the tested program         */
 u8 *trace_bits;                        /* SHM with instrumentation bitmap   */
 
 static u8 *in_file,                    /* Analyzer input test case          */
-    *prog_in,                          /* Targeted program input file       */
-    *doc_path;                         /* Path to docs                      */
+    *prog_in;                          /* Targeted program input file       */
 
 static u8 *in_data;                    /* Input data for analysis           */
 
@@ -77,7 +76,7 @@ static s32 dev_null_fd = -1;           /* FD to /dev/null                   */
 
 u8 edges_only,                         /* Ignore hit counts?                */
     use_hex_offsets,                   /* Show hex offsets?                 */
-    be_quiet, use_stdin = 1;           /* Use stdin for program input?      */
+    use_stdin = 1;                     /* Use stdin for program input?      */
 
 static volatile u8 stop_soon,          /* Ctrl-C pressed?                   */
     child_timed_out;                   /* Child timed out?                  */
diff --git a/src/afl-common.c b/src/afl-common.c
index 8c4d53e8..920c7dfd 100644
--- a/src/afl-common.c
+++ b/src/afl-common.c
@@ -30,6 +30,7 @@
 #include "debug.h"
 #include "alloc-inl.h"
 #include "envs.h"
+#include "common.h"
 
 /* Detect @@ in args. */
 #ifndef __glibc__
@@ -37,8 +38,10 @@
 #endif
 #include <limits.h>
 
-extern u8 be_quiet;
-char *    afl_environment_variables[] = {
+u8  be_quiet = 0;
+u8 *doc_path = "";
+
+char *afl_environment_variables[] = {
 
     "AFL_ALIGNED_ALLOC", "AFL_ALLOW_TMP", "AFL_ANALYZE_HEX", "AFL_AS",
     "AFL_AUTORESUME", "AFL_AS_FORCE_INSTRUMENT", "AFL_BENCH_JUST_ONE",
@@ -73,7 +76,7 @@ char *    afl_environment_variables[] = {
     "AFL_SHUFFLE_QUEUE", "AFL_SKIP_BIN_CHECK", "AFL_SKIP_CPUFREQ",
     "AFL_SKIP_CRASHES", "AFL_TMIN_EXACT", "AFL_TMPDIR", "AFL_TOKEN_FILE",
     "AFL_TRACE_PC", "AFL_USE_ASAN", "AFL_USE_MSAN", "AFL_USE_TRACE_PC",
-    "AFL_USE_UBSAN", "AFL_WINE_PATH", NULL};
+    "AFL_USE_UBSAN", "AFL_USE_CFISAN", "AFL_WINE_PATH", NULL};
 
 void detect_file_args(char **argv, u8 *prog_in, u8 *use_stdin) {
 
@@ -393,3 +396,393 @@ char *get_afl_env(char *env) {
 
 }
 
+u64 get_cur_time(void) {
+
+  struct timeval  tv;
+  struct timezone tz;
+
+  gettimeofday(&tv, &tz);
+
+  return (tv.tv_sec * 1000ULL) + (tv.tv_usec / 1000);
+
+}
+
+/* Get unix time in microseconds */
+
+u64 get_cur_time_us(void) {
+
+  struct timeval  tv;
+  struct timezone tz;
+
+  gettimeofday(&tv, &tz);
+
+  return (tv.tv_sec * 1000000ULL) + tv.tv_usec;
+
+}
+
+/* Describe integer. The buf should be
+   at least 6 bytes to fit all ints we randomly see.
+   Will return buf for convenience. */
+
+u8 *stringify_int(u8 *buf, size_t len, u64 val) {
+\
+#define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast)     \
+  do {                                                     \
+                                                           \
+    if (val < (_divisor) * (_limit_mult)) {                \
+                                                           \
+      snprintf(buf, len, _fmt, ((_cast)val) / (_divisor)); \
+      return buf;                                          \
+                                                           \
+    }                                                      \
+                                                           \
+  } while (0)
+
+  /* 0-9999 */
+  CHK_FORMAT(1, 10000, "%llu", u64);
+
+  /* 10.0k - 99.9k */
+  CHK_FORMAT(1000, 99.95, "%0.01fk", double);
+
+  /* 100k - 999k */
+  CHK_FORMAT(1000, 1000, "%lluk", u64);
+
+  /* 1.00M - 9.99M */
+  CHK_FORMAT(1000 * 1000, 9.995, "%0.02fM", double);
+
+  /* 10.0M - 99.9M */
+  CHK_FORMAT(1000 * 1000, 99.95, "%0.01fM", double);
+
+  /* 100M - 999M */
+  CHK_FORMAT(1000 * 1000, 1000, "%lluM", u64);
+
+  /* 1.00G - 9.99G */
+  CHK_FORMAT(1000LL * 1000 * 1000, 9.995, "%0.02fG", double);
+
+  /* 10.0G - 99.9G */
+  CHK_FORMAT(1000LL * 1000 * 1000, 99.95, "%0.01fG", double);
+
+  /* 100G - 999G */
+  CHK_FORMAT(1000LL * 1000 * 1000, 1000, "%lluG", u64);
+
+  /* 1.00T - 9.99G */
+  CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 9.995, "%0.02fT", double);
+
+  /* 10.0T - 99.9T */
+  CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 99.95, "%0.01fT", double);
+
+  /* 100T+ */
+  strncpy(buf, "infty", len);
+  buf[len - 1] = '\0';
+
+  return buf;
+
+}
+
+/* Describe float. Similar as int. */
+
+u8 *stringify_float(u8 *buf, size_t len, double val) {
+
+  if (val < 99.995) {
+
+    snprintf(buf, len, "%0.02f", val);
+
+  } else if (val < 999.95) {
+
+    snprintf(buf, len, "%0.01f", val);
+
+  } else {
+
+    stringify_int(buf, len, (u64)val);
+
+  }
+
+  return buf;
+
+}
+
+/* Describe integer as memory size. */
+
+u8 *stringify_mem_size(u8 *buf, size_t len, u64 val) {
+
+  /* 0-9999 */
+  CHK_FORMAT(1, 10000, "%llu B", u64);
+
+  /* 10.0k - 99.9k */
+  CHK_FORMAT(1024, 99.95, "%0.01f kB", double);
+
+  /* 100k - 999k */
+  CHK_FORMAT(1024, 1000, "%llu kB", u64);
+
+  /* 1.00M - 9.99M */
+  CHK_FORMAT(1024 * 1024, 9.995, "%0.02f MB", double);
+
+  /* 10.0M - 99.9M */
+  CHK_FORMAT(1024 * 1024, 99.95, "%0.01f MB", double);
+
+  /* 100M - 999M */
+  CHK_FORMAT(1024 * 1024, 1000, "%llu MB", u64);
+
+  /* 1.00G - 9.99G */
+  CHK_FORMAT(1024LL * 1024 * 1024, 9.995, "%0.02f GB", double);
+
+  /* 10.0G - 99.9G */
+  CHK_FORMAT(1024LL * 1024 * 1024, 99.95, "%0.01f GB", double);
+
+  /* 100G - 999G */
+  CHK_FORMAT(1024LL * 1024 * 1024, 1000, "%llu GB", u64);
+
+  /* 1.00T - 9.99G */
+  CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 9.995, "%0.02f TB", double);
+
+  /* 10.0T - 99.9T */
+  CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 99.95, "%0.01f TB", double);
+
+#undef CHK_FORMAT
+
+  /* 100T+ */
+  strncpy(buf, "infty", len - 1);
+  buf[len - 1] = '\0';
+
+  return buf;
+
+}
+
+/* Describe time delta as string.
+   Returns a pointer to buf for convenience. */
+
+u8 *stringify_time_diff(u8 *buf, size_t len, u64 cur_ms, u64 event_ms) {
+
+  u64 delta;
+  s32 t_d, t_h, t_m, t_s;
+  u8  val_buf[STRINGIFY_VAL_SIZE_MAX];
+
+  if (!event_ms) {
+
+    snprintf(buf, len, "none seen yet");
+
+  } else {
+
+    delta = cur_ms - event_ms;
+
+    t_d = delta / 1000 / 60 / 60 / 24;
+    t_h = (delta / 1000 / 60 / 60) % 24;
+    t_m = (delta / 1000 / 60) % 60;
+    t_s = (delta / 1000) % 60;
+
+    stringify_int(val_buf, sizeof(val_buf), t_d);
+    snprintf(buf, len, "%s days, %d hrs, %d min, %d sec", val_buf, t_h, t_m,
+             t_s);
+
+  }
+
+  return buf;
+
+}
+
+/* Unsafe Describe integer. The buf sizes are not checked.
+   This is unsafe but fast.
+   Will return buf for convenience. */
+
+u8 *u_stringify_int(u8 *buf, u64 val) {
+\
+#define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast) \
+  do {                                                 \
+                                                       \
+    if (val < (_divisor) * (_limit_mult)) {            \
+                                                       \
+      sprintf(buf, _fmt, ((_cast)val) / (_divisor));   \
+      return buf;                                      \
+                                                       \
+    }                                                  \
+                                                       \
+  } while (0)
+
+  /* 0-9999 */
+  CHK_FORMAT(1, 10000, "%llu", u64);
+
+  /* 10.0k - 99.9k */
+  CHK_FORMAT(1000, 99.95, "%0.01fk", double);
+
+  /* 100k - 999k */
+  CHK_FORMAT(1000, 1000, "%lluk", u64);
+
+  /* 1.00M - 9.99M */
+  CHK_FORMAT(1000 * 1000, 9.995, "%0.02fM", double);
+
+  /* 10.0M - 99.9M */
+  CHK_FORMAT(1000 * 1000, 99.95, "%0.01fM", double);
+
+  /* 100M - 999M */
+  CHK_FORMAT(1000 * 1000, 1000, "%lluM", u64);
+
+  /* 1.00G - 9.99G */
+  CHK_FORMAT(1000LL * 1000 * 1000, 9.995, "%0.02fG", double);
+
+  /* 10.0G - 99.9G */
+  CHK_FORMAT(1000LL * 1000 * 1000, 99.95, "%0.01fG", double);
+
+  /* 100G - 999G */
+  CHK_FORMAT(1000LL * 1000 * 1000, 1000, "%lluG", u64);
+
+  /* 1.00T - 9.99G */
+  CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 9.995, "%0.02fT", double);
+
+  /* 10.0T - 99.9T */
+  CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 99.95, "%0.01fT", double);
+
+  /* 100T+ */
+  strcpy(buf, "infty");
+
+  return buf;
+
+}
+
+/* Unsafe describe float. Similar as unsafe int. */
+
+u8 *u_stringify_float(u8 *buf, double val) {
+
+  if (val < 99.995) {
+
+    sprintf(buf, "%0.02f", val);
+
+  } else if (val < 999.95) {
+
+    sprintf(buf, "%0.01f", val);
+
+  } else {
+
+    return u_stringify_int(buf, (u64)val);
+
+  }
+
+  return buf;
+
+}
+
+/* Unsafe describe integer as memory size. */
+
+u8 *u_stringify_mem_size(u8 *buf, u64 val) {
+
+  /* 0-9999 */
+  CHK_FORMAT(1, 10000, "%llu B", u64);
+
+  /* 10.0k - 99.9k */
+  CHK_FORMAT(1024, 99.95, "%0.01f kB", double);
+
+  /* 100k - 999k */
+  CHK_FORMAT(1024, 1000, "%llu kB", u64);
+
+  /* 1.00M - 9.99M */
+  CHK_FORMAT(1024 * 1024, 9.995, "%0.02f MB", double);
+
+  /* 10.0M - 99.9M */
+  CHK_FORMAT(1024 * 1024, 99.95, "%0.01f MB", double);
+
+  /* 100M - 999M */
+  CHK_FORMAT(1024 * 1024, 1000, "%llu MB", u64);
+
+  /* 1.00G - 9.99G */
+  CHK_FORMAT(1024LL * 1024 * 1024, 9.995, "%0.02f GB", double);
+
+  /* 10.0G - 99.9G */
+  CHK_FORMAT(1024LL * 1024 * 1024, 99.95, "%0.01f GB", double);
+
+  /* 100G - 999G */
+  CHK_FORMAT(1024LL * 1024 * 1024, 1000, "%llu GB", u64);
+
+  /* 1.00T - 9.99G */
+  CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 9.995, "%0.02f TB", double);
+
+  /* 10.0T - 99.9T */
+  CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 99.95, "%0.01f TB", double);
+
+#undef CHK_FORMAT
+
+  /* 100T+ */
+  strcpy(buf, "infty");
+
+  return buf;
+
+}
+
+/* Unsafe describe time delta as string.
+   Returns a pointer to buf for convenience. */
+
+u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms) {
+
+  u64 delta;
+  s32 t_d, t_h, t_m, t_s;
+  u8  val_buf[STRINGIFY_VAL_SIZE_MAX];
+
+  if (!event_ms) {
+
+    sprintf(buf, "none seen yet");
+
+  } else {
+
+    delta = cur_ms - event_ms;
+
+    t_d = delta / 1000 / 60 / 60 / 24;
+    t_h = (delta / 1000 / 60 / 60) % 24;
+    t_m = (delta / 1000 / 60) % 60;
+    t_s = (delta / 1000) % 60;
+
+    u_stringify_int(val_buf, t_d);
+    sprintf(buf, "%s days, %d hrs, %d min, %d sec", val_buf, t_h, t_m, t_s);
+
+  }
+
+  return buf;
+
+}
+
+/* Wrapper for select() and read(), reading exactly len bytes.
+  Returns the time passed to read.
+  If the wait times out, returns timeout_ms + 1;
+  Returns 0 if an error occurred (fd closed, signal, ...); */
+u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms) {
+
+  struct timeval timeout;
+  fd_set         readfds;
+  FD_ZERO(&readfds);
+  FD_SET(fd, &readfds);
+
+  timeout.tv_sec = (timeout_ms / 1000);
+  timeout.tv_usec = (timeout_ms % 1000) * 1000;
+
+  size_t read_total = 0;
+  size_t len_read = 0;
+
+  while (len_read < len) {
+
+    /* set exceptfds as well to return when a child exited/closed the pipe. */
+    int sret = select(fd + 1, &readfds, NULL, NULL, &timeout);
+
+    if (!sret) {
+
+      // printf("Timeout in sret.");
+      return timeout_ms + 1;
+
+    } else if (sret < 0) {
+
+      // perror("sret malloc");
+      // TODO: catch other (errno == EINTR) than ctrl+c?
+      return 0;
+
+    }
+
+    len_read = read(fd, ((u8 *)buf) + len_read, len - len_read);
+    if (!len_read) { return 0; }
+    read_total += len_read;
+
+  }
+
+  s32 exec_ms =
+      MIN(timeout_ms,
+          ((u64)timeout_ms - (timeout.tv_sec * 1000 + timeout.tv_usec / 1000)));
+  return exec_ms > 0 ? exec_ms
+                     : 1;  // at least 1 milli must have passed (0 is an error)
+
+}
+
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index 2dd7a9f0..11b359da 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -49,8 +49,6 @@
 
 /* Describe integer as memory size. */
 
-extern u8 *doc_path;
-
 list_t fsrv_list = {.element_prealloc_count = 0};
 
 /* Initializes the struct */
@@ -164,10 +162,9 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) {
 
 void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv) {
 
-  struct timeval timeout;
-  int            st_pipe[2], ctl_pipe[2];
-  int            status;
-  s32            rlen;
+  int st_pipe[2], ctl_pipe[2];
+  int status;
+  s32 rlen;
 
   if (fsrv->use_fauxsrv) ACTF("Using Fauxserver:");
 
@@ -318,26 +315,19 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv) {
   rlen = 0;
   if (fsrv->exec_tmout) {
 
-    fd_set readfds;
-
-    FD_ZERO(&readfds);
-    FD_SET(fsrv->fsrv_st_fd, &readfds);
-    timeout.tv_sec = ((fsrv->exec_tmout * FORK_WAIT_MULT) / 1000);
-    timeout.tv_usec = ((fsrv->exec_tmout * FORK_WAIT_MULT) % 1000) * 1000;
+    rlen = 4;
+    u32 time = read_timed(fsrv->fsrv_st_fd, &status, rlen,
+                          fsrv->exec_tmout * FORK_WAIT_MULT);
 
-    int sret = select(fsrv->fsrv_st_fd + 1, &readfds, NULL, NULL, &timeout);
-
-    if (sret == 0) {
+    if (time > fsrv->exec_tmout * FORK_WAIT_MULT) {
 
       fsrv->child_timed_out = 1;
-      kill(fsrv->child_pid, SIGKILL);
-
-    } else {
-
-      rlen = read(fsrv->fsrv_st_fd, &status, 4);
+      kill(fsrv->fsrv_pid, SIGKILL);
 
     }
 
+    if (!time) { kill(fsrv->fsrv_pid, SIGKILL); }
+
   } else {
 
     rlen = read(fsrv->fsrv_st_fd, &status, 4);
diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c
index 0d5b542d..8ca286b2 100644
--- a/src/afl-fuzz-bitmap.c
+++ b/src/afl-fuzz-bitmap.c
@@ -31,13 +31,13 @@
 
 void write_bitmap(afl_state_t *afl) {
 
-  u8 *fname;
+  u8  fname[PATH_MAX];
   s32 fd;
 
   if (!afl->bitmap_changed) return;
   afl->bitmap_changed = 0;
 
-  fname = alloc_printf("%s/fuzz_bitmap", afl->out_dir);
+  snprintf(fname, PATH_MAX, "%s/fuzz_bitmap", afl->out_dir);
   fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC, 0600);
 
   if (fd < 0) PFATAL("Unable to open '%s'", fname);
@@ -45,7 +45,6 @@ void write_bitmap(afl_state_t *afl) {
   ck_write(fd, afl->virgin_bits, MAP_SIZE, fname);
 
   close(fd);
-  ck_free(fname);
 
 }
 
@@ -462,14 +461,15 @@ u8 *describe_op(afl_state_t *afl, u8 hnb) {
 
 static void write_crash_readme(afl_state_t *afl) {
 
-  u8 *  fn = alloc_printf("%s/crashes/README.txt", afl->out_dir);
+  u8    fn[PATH_MAX];
   s32   fd;
   FILE *f;
 
   u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
 
+  sprintf(fn, "%s/crashes/README.txt", afl->out_dir);
+
   fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
-  ck_free(fn);
 
   /* Do not die on errors here - that would be impolite. */
 
@@ -520,11 +520,13 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
 
   if (unlikely(len == 0)) return 0;
 
-  u8 *fn = "";
+  u8 *queue_fn = "";
   u8  hnb;
   s32 fd;
   u8  keeping = 0, res;
 
+  u8 fn[PATH_MAX];
+
   /* Update path frequency. */
   u32 cksum = hash32(afl->fsrv.trace_bits, MAP_SIZE, HASH_CONST);
 
@@ -556,16 +558,17 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
 
 #ifndef SIMPLE_FILES
 
-    fn = alloc_printf("%s/queue/id:%06u,%s", afl->out_dir, afl->queued_paths,
-                      describe_op(afl, hnb));
+    queue_fn = alloc_printf("%s/queue/id:%06u,%s", afl->out_dir,
+                            afl->queued_paths, describe_op(afl, hnb));
 
 #else
 
-    fn = alloc_printf("%s/queue/id_%06u", afl->out_dir, afl->queued_paths);
+    queue_fn =
+        alloc_printf("%s/queue/id_%06u", afl->out_dir, afl->queued_paths);
 
 #endif                                                    /* ^!SIMPLE_FILES */
 
-    add_to_queue(afl, fn, len, 0);
+    add_to_queue(afl, queue_fn, len, 0);
 
     if (hnb == 2) {
 
@@ -584,9 +587,9 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
     if (unlikely(res == FAULT_ERROR))
       FATAL("Unable to execute target application");
 
-    fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
-    if (unlikely(fd < 0)) PFATAL("Unable to create '%s'", fn);
-    ck_write(fd, mem, len, fn);
+    fd = open(queue_fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
+    if (unlikely(fd < 0)) PFATAL("Unable to create '%s'", queue_fn);
+    ck_write(fd, mem, len, queue_fn);
     close(fd);
 
     keeping = 1;
@@ -642,12 +645,13 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
 
 #ifndef SIMPLE_FILES
 
-      fn = alloc_printf("%s/hangs/id:%06llu,%s", afl->out_dir,
-                        afl->unique_hangs, describe_op(afl, 0));
+      snprintf(fn, PATH_MAX, "%s/hangs/id:%06llu,%s", afl->out_dir,
+               afl->unique_hangs, describe_op(afl, 0));
 
 #else
 
-      fn = alloc_printf("%s/hangs/id_%06llu", afl->out_dir, afl->unique_hangs);
+      snprintf(fn, PATH_MAX, "%s/hangs/id_%06llu", afl->out_dir,
+               afl->unique_hangs);
 
 #endif                                                    /* ^!SIMPLE_FILES */
 
@@ -685,14 +689,13 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
 
 #ifndef SIMPLE_FILES
 
-      fn = alloc_printf("%s/crashes/id:%06llu,sig:%02u,%s", afl->out_dir,
-                        afl->unique_crashes, afl->kill_signal,
-                        describe_op(afl, 0));
+      snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s", afl->out_dir,
+               afl->unique_crashes, afl->kill_signal, describe_op(afl, 0));
 
 #else
 
-      fn = alloc_printf("%s/crashes/id_%06llu_%02u", afl->out_dir,
-                        afl->unique_crashes, afl->kill_signal);
+      snprintf(fn, PATH_MAX, "%s/crashes/id_%06llu_%02u", afl->out_dir,
+               afl->unique_crashes, afl->kill_signal);
 
 #endif                                                    /* ^!SIMPLE_FILES */
 
@@ -729,8 +732,6 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
   ck_write(fd, mem, len, fn);
   close(fd);
 
-  ck_free(fn);
-
   return keeping;
 
 }
diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c
index 6c6f05ac..f932f33b 100644
--- a/src/afl-fuzz-cmplog.c
+++ b/src/afl-fuzz-cmplog.c
@@ -31,10 +31,9 @@
 
 void init_cmplog_forkserver(afl_state_t *afl) {
 
-  struct timeval timeout;
-  int            st_pipe[2], ctl_pipe[2];
-  int            status;
-  s32            rlen;
+  int st_pipe[2], ctl_pipe[2];
+  int status;
+  s32 rlen;
 
   ACTF("Spinning up the cmplog fork server...");
 
@@ -185,21 +184,19 @@ void init_cmplog_forkserver(afl_state_t *afl) {
   rlen = 0;
   if (afl->fsrv.exec_tmout) {
 
-    fd_set readfds;
-    FD_ZERO(&readfds);
-    FD_SET(afl->cmplog_fsrv_st_fd, &readfds);
-    timeout.tv_sec = ((afl->fsrv.exec_tmout * FORK_WAIT_MULT) / 1000);
-    timeout.tv_usec = ((afl->fsrv.exec_tmout * FORK_WAIT_MULT) % 1000) * 1000;
+    rlen = 4;
+    u32 timeout_ms = afl->fsrv.exec_tmout * FORK_WAIT_MULT;
+    /* Reuse readfds as exceptfds to see when the child closed the pipe */
+    u32 exec_ms = read_timed(afl->cmplog_fsrv_st_fd, &status, rlen, timeout_ms);
 
-    int sret =
-        select(afl->cmplog_fsrv_st_fd + 1, &readfds, NULL, NULL, &timeout);
+    if (!exec_ms) {
 
-    if (sret == 0) {
+      PFATAL("Error in timed read");
 
-      kill(afl->cmplog_fsrv_pid, SIGKILL);
-
-    } else {
+    } else if (exec_ms > timeout_ms) {
 
+      afl->fsrv.child_timed_out = 1;
+      kill(afl->cmplog_fsrv_pid, SIGKILL);
       rlen = read(afl->cmplog_fsrv_st_fd, &status, 4);
 
     }
@@ -213,6 +210,11 @@ void init_cmplog_forkserver(afl_state_t *afl) {
   /* If we have a four-byte "hello" message from the server, we're all set.
      Otherwise, try to figure out what went wrong. */
 
+  if (afl->fsrv.child_timed_out)
+    FATAL(
+        "Timeout while initializing cmplog fork server (adjusting -t may "
+        "help)");
+
   if (rlen == 4) {
 
     OKF("All right - fork server is up.");
@@ -220,11 +222,6 @@ void init_cmplog_forkserver(afl_state_t *afl) {
 
   }
 
-  if (afl->fsrv.child_timed_out)
-    FATAL(
-        "Timeout while initializing cmplog fork server (adjusting -t may "
-        "help)");
-
   if (waitpid(afl->cmplog_fsrv_pid, &status, 0) <= 0)
     PFATAL("waitpid() failed");
 
@@ -379,16 +376,12 @@ void init_cmplog_forkserver(afl_state_t *afl) {
 
 u8 run_cmplog_target(afl_state_t *afl, u32 timeout) {
 
-  struct timeval it;
-  int            status = 0;
-  int            sret;
-  u64            exec_ms;
+  int status = 0;
+  u32 exec_ms;
 
   u32 tb4;
   s32 res;
 
-  fd_set readfds;
-
   afl->fsrv.child_timed_out = 0;
 
   /* After this memset, afl->fsrv.trace_bits[] are effectively volatile, so we
@@ -423,18 +416,9 @@ u8 run_cmplog_target(afl_state_t *afl, u32 timeout) {
 
   /* Configure timeout, as requested by user, then wait for child to terminate.
    */
+  exec_ms = read_timed(afl->cmplog_fsrv_st_fd, &status, 4, timeout);
 
-  it.tv_sec = (timeout / 1000);
-  it.tv_usec = (timeout % 1000) * 1000;
-
-  FD_ZERO(&readfds);
-  FD_SET(afl->cmplog_fsrv_st_fd, &readfds);
-  it.tv_sec = ((timeout) / 1000);
-  it.tv_usec = ((timeout) % 1000) * 1000;
-
-  sret = select(afl->cmplog_fsrv_st_fd + 1, &readfds, NULL, NULL, &it);
-
-  if (sret == 0) {
+  if (exec_ms > timeout) {
 
     /* If there was no response from forkserver after timeout seconds,
     we kill the child. The forkserver should inform us afterwards */
@@ -442,9 +426,12 @@ u8 run_cmplog_target(afl_state_t *afl, u32 timeout) {
     kill(afl->cmplog_child_pid, SIGKILL);
     afl->fsrv.child_timed_out = 1;
 
+    /* After killing the child, the forkserver should tell us */
+    if (!read(afl->cmplog_fsrv_st_fd, &status, 4)) exec_ms = 0;
+
   }
 
-  if ((res = read(afl->cmplog_fsrv_st_fd, &status, 4)) != 4) {
+  if (!exec_ms) {  // Something went wrong.
 
     if (afl->stop_soon) return 0;
     SAYF("\n" cLRD "[-] " cRST
@@ -467,12 +454,8 @@ u8 run_cmplog_target(afl_state_t *afl, u32 timeout) {
 
   if (!WIFSTOPPED(status)) afl->cmplog_child_pid = 0;
 
-  exec_ms = (u64)timeout - (it.tv_sec * 1000 + it.tv_usec / 1000);
   if (afl->slowest_exec_ms < exec_ms) afl->slowest_exec_ms = exec_ms;
 
-  it.tv_sec = 0;
-  it.tv_usec = 0;
-
   ++afl->total_execs;
 
   /* Any subsequent operations on afl->fsrv.trace_bits must not be moved by the
@@ -527,8 +510,13 @@ u8 common_fuzz_cmplog_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
 
   if (afl->post_handler) {
 
-    out_buf = afl->post_handler(out_buf, &len);
-    if (!out_buf || !len) return 0;
+    u8 *post_buf = NULL;
+
+    size_t post_len =
+        afl->post_handler(afl->post_data, out_buf, len, &post_buf);
+    if (!post_buf || !post_len) return 0;
+    out_buf = post_buf;
+    len = post_len;
 
   }
 
diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c
index 038c4393..e2495524 100644
--- a/src/afl-fuzz-init.c
+++ b/src/afl-fuzz-init.c
@@ -76,21 +76,16 @@ void bind_to_free_cpu(afl_state_t *afl) {
 
   while ((de = readdir(d))) {
 
-    u8 *  fn;
+    u8    fn[PATH_MAX];
     FILE *f;
     u8    tmp[MAX_LINE];
     u8    has_vmsize = 0;
 
     if (!isdigit(de->d_name[0])) continue;
 
-    fn = alloc_printf("/proc/%s/status", de->d_name);
+    snprintf(fn, PATH_MAX, "/proc/%s/status", de->d_name);
 
-    if (!(f = fopen(fn, "r"))) {
-
-      ck_free(fn);
-      continue;
-
-    }
+    if (!(f = fopen(fn, "r"))) { continue; }
 
     while (fgets(tmp, MAX_LINE, f)) {
 
@@ -111,7 +106,6 @@ void bind_to_free_cpu(afl_state_t *afl) {
 
     }
 
-    ck_free(fn);
     fclose(f);
 
   }
@@ -276,7 +270,9 @@ void setup_post(afl_state_t *afl) {
 
   void *dh;
   u8 *  fn = afl->afl_env.afl_post_library;
+  u8    tbuf[6];
   u32   tlen = 6;
+  strncpy(tbuf, "hello", tlen);
 
   if (!fn) return;
 
@@ -287,10 +283,20 @@ void setup_post(afl_state_t *afl) {
 
   afl->post_handler = dlsym(dh, "afl_postprocess");
   if (!afl->post_handler) FATAL("Symbol 'afl_postprocess' not found.");
+  afl->post_init = dlsym(dh, "afl_postprocess_init");
+  if (!afl->post_init) FATAL("Symbol 'afl_postprocess_init' not found.");
+  afl->post_deinit = dlsym(dh, "afl_postprocess_deinit");
+  if (!afl->post_deinit) FATAL("Symbol 'afl_postprocess_deinit' not found.");
 
   /* Do a quick test. It's better to segfault now than later =) */
 
-  afl->post_handler("hello", &tlen);
+  u8 *post_buf = NULL;
+  afl->post_data = afl->post_init(afl);
+  if (!afl->post_data) FATAL("Could not initialize post handler.");
+
+  size_t post_len = afl->post_handler(afl->post_data, tbuf, tlen, &post_buf);
+  if (!post_len || !post_buf)
+    SAYF("Empty return in test post handler for buf=\"hello\\0\".");
 
   OKF("Postprocessor installed successfully.");
 
@@ -369,9 +375,10 @@ void read_testcases(afl_state_t *afl) {
 
     struct stat st;
 
+    u8 dfn[PATH_MAX];
+    snprintf(dfn, PATH_MAX, "%s/.state/deterministic_done/%s", afl->in_dir,
+             nl[i]->d_name);
     u8 *fn2 = alloc_printf("%s/%s", afl->in_dir, nl[i]->d_name);
-    u8 *dfn = alloc_printf("%s/.state/deterministic_done/%s", afl->in_dir,
-                           nl[i]->d_name);
 
     u8 passed_det = 0;
 
@@ -385,7 +392,6 @@ void read_testcases(afl_state_t *afl) {
     if (!S_ISREG(st.st_mode) || !st.st_size || strstr(fn2, "/README.txt")) {
 
       ck_free(fn2);
-      ck_free(dfn);
       continue;
 
     }
@@ -401,7 +407,6 @@ void read_testcases(afl_state_t *afl) {
        and probably very time-consuming. */
 
     if (!access(dfn, F_OK)) passed_det = 1;
-    ck_free(dfn);
 
     add_to_queue(afl, fn2, st.st_size, passed_det);
 
diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c
index 0ded4ba1..754b2190 100644
--- a/src/afl-fuzz-mutators.c
+++ b/src/afl-fuzz-mutators.c
@@ -7,6 +7,7 @@
    Now maintained by  Marc Heuse <mh@mh-sec.de>,
                         Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
                         Andrea Fioraldi <andreafioraldi@gmail.com>
+                        Dominik Maier <mail@dmnk.co>
 
    Copyright 2016, 2017 Google Inc. All rights reserved.
    Copyright 2019-2020 AFLplusplus Project. All rights reserved.
@@ -78,8 +79,15 @@ void destroy_custom_mutator(afl_state_t *afl) {
 
     afl->mutator->afl_custom_deinit(afl->mutator->data);
 
-    if (afl->mutator->dh)
-      dlclose(afl->mutator->dh);
+    if (afl->mutator->dh) dlclose(afl->mutator->dh);
+
+    if (afl->mutator->pre_save_buf) {
+
+      ck_free(afl->mutator->pre_save_buf);
+      afl->mutator->pre_save_buf = NULL;
+      afl->mutator->pre_save_size = 0;
+
+    }
 
     ck_free(afl->mutator);
     afl->mutator = NULL;
@@ -92,6 +100,8 @@ void load_custom_mutator(afl_state_t *afl, const char *fn) {
 
   void *dh;
   afl->mutator = ck_alloc(sizeof(struct custom_mutator));
+  afl->mutator->pre_save_buf = NULL;
+  afl->mutator->pre_save_size = 0;
 
   afl->mutator->name = fn;
   ACTF("Loading custom mutator library from '%s'...", fn);
@@ -103,11 +113,13 @@ void load_custom_mutator(afl_state_t *afl, const char *fn) {
   /* Mutator */
   /* "afl_custom_init", required */
   afl->mutator->afl_custom_init = dlsym(dh, "afl_custom_init");
-  if (!afl->mutator->afl_custom_init) FATAL("Symbol 'afl_custom_init' not found.");
+  if (!afl->mutator->afl_custom_init)
+    FATAL("Symbol 'afl_custom_init' not found.");
 
   /* "afl_custom_deinit", required */
   afl->mutator->afl_custom_deinit = dlsym(dh, "afl_custom_deinit");
-  if (!afl->mutator->afl_custom_deinit) FATAL("Symbol 'afl_custom_deinit' not found.");
+  if (!afl->mutator->afl_custom_deinit)
+    FATAL("Symbol 'afl_custom_deinit' not found.");
 
   /* "afl_custom_fuzz" or "afl_custom_mutator", required */
   afl->mutator->afl_custom_fuzz = dlsym(dh, "afl_custom_fuzz");
@@ -181,7 +193,8 @@ void load_custom_mutator(afl_state_t *afl, const char *fn) {
 
   /* Initialize the custom mutator */
   if (afl->mutator->afl_custom_init)
-    afl->mutator->afl_custom_init(afl, rand_below(afl, 0xFFFFFFFF));
+    afl->mutator->data =
+        afl->mutator->afl_custom_init(afl, rand_below(afl, 0xFFFFFFFF));
 
 }
 
@@ -198,24 +211,28 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
 
   /* Initialize trimming in the custom mutator */
   afl->stage_cur = 0;
-  afl->stage_max = afl->mutator->afl_custom_init_trim(afl->mutator->data, in_buf, q->len);
-
+  afl->stage_max =
+      afl->mutator->afl_custom_init_trim(afl->mutator->data, in_buf, q->len);
+  if (unlikely(afl->stage_max) < 0)
+    FATAL("custom_init_trim error ret: %d", afl->stage_max);
   if (afl->not_on_tty && afl->debug)
     SAYF("[Custom Trimming] START: Max %d iterations, %u bytes", afl->stage_max,
          q->len);
 
   while (afl->stage_cur < afl->stage_max) {
 
-    sprintf(afl->stage_name_buf, "ptrim %s", u_stringify_int(val_buf, trim_exec));
+    u8 *retbuf = NULL;
 
-    u32 cksum;
+    sprintf(afl->stage_name_buf, "ptrim %s",
+            u_stringify_int(val_buf, trim_exec));
 
-    u8 *   retbuf = NULL;
-    size_t retlen = 0;
+    u32 cksum;
 
-    afl->mutator->afl_custom_trim(afl, &retbuf, &retlen);
+    size_t retlen = afl->mutator->afl_custom_trim(afl->mutator->data, &retbuf);
 
-    if (retlen > orig_len)
+    if (unlikely(!retbuf))
+      FATAL("custom_trim failed (ret %zd)", retlen);
+    else if (unlikely(retlen > orig_len))
       FATAL(
           "Trimmed data returned by custom mutator is larger than original "
           "data");
@@ -225,12 +242,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
     fault = run_target(afl, afl->fsrv.exec_tmout);
     ++afl->trim_execs;
 
-    if (afl->stop_soon || fault == FAULT_ERROR) {
-
-      ck_free(retbuf);
-      goto abort_trimming;
-
-    }
+    if (afl->stop_soon || fault == FAULT_ERROR) { goto abort_trimming; }
 
     cksum = hash32(afl->fsrv.trace_bits, MAP_SIZE, HASH_CONST);
 
@@ -250,7 +262,8 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
       }
 
       /* Tell the custom mutator that the trimming was successful */
-      afl->stage_cur = afl->mutator->afl_custom_post_trim(afl, 1);
+      afl->stage_cur =
+          afl->mutator->afl_custom_post_trim(afl->mutator->data, 1);
 
       if (afl->not_on_tty && afl->debug)
         SAYF("[Custom Trimming] SUCCESS: %d/%d iterations (now at %u bytes)",
@@ -259,15 +272,16 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
     } else {
 
       /* Tell the custom mutator that the trimming was unsuccessful */
-      afl->stage_cur = afl->mutator->afl_custom_post_trim(afl, 0);
+      afl->stage_cur =
+          afl->mutator->afl_custom_post_trim(afl->mutator->data, 0);
+      if (unlikely(afl->stage_cur < 0))
+        FATAL("Error ret in custom_post_trim: %d", afl->stage_cur);
       if (afl->not_on_tty && afl->debug)
         SAYF("[Custom Trimming] FAILURE: %d/%d iterations", afl->stage_cur,
              afl->stage_max);
 
     }
 
-    ck_free(retbuf);
-
     /* Since this can be slow, update the screen every now and then. */
 
     if (!(trim_exec++ % afl->stats_update_freq)) show_stats(afl);
@@ -304,3 +318,4 @@ abort_trimming:
   return fault;
 
 }
+
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index cc150cfe..b20bde90 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -347,6 +347,9 @@ u8 fuzz_one_original(afl_state_t *afl) {
   u8  a_collect[MAX_AUTO_EXTRA];
   u32 a_len = 0;
 
+/* Not pretty, but saves a lot of writing */
+#define BUF_PARAMS(name) (void **)&afl->name##_buf, &afl->name##_size
+
 #ifdef IGNORE_FINDS
 
   /* In IGNORE_FINDS mode, skip any entries that weren't in the
@@ -360,7 +363,8 @@ u8 fuzz_one_original(afl_state_t *afl) {
 
     /* The custom mutator will decide to skip this test case or not. */
 
-    if (!afl->mutator->afl_custom_queue_get(afl, afl->queue_cur->fname))
+    if (!afl->mutator->afl_custom_queue_get(afl->mutator->data,
+                                            afl->queue_cur->fname))
       return 1;
 
   }
@@ -426,7 +430,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
      single byte anyway, so it wouldn't give us any performance or memory usage
      benefits. */
 
-  out_buf = ck_alloc_nozero(len);
+  out_buf = ck_maybe_grow(BUF_PARAMS(out), len);
 
   afl->subseq_tmouts = 0;
 
@@ -718,7 +722,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
   /* Initialize effector map for the next step (see comments below). Always
      flag first and last byte as doing something. */
 
-  eff_map = ck_alloc(EFF_ALEN(len));
+  eff_map = ck_maybe_grow(BUF_PARAMS(eff), EFF_ALEN(len));
   eff_map[0] = 1;
 
   if (EFF_APOS(len - 1) != 0) {
@@ -1442,7 +1446,7 @@ skip_interest:
 
   orig_hit_cnt = new_hit_cnt;
 
-  ex_tmp = ck_alloc(len + MAX_DICT_FILE);
+  ex_tmp = ck_maybe_grow(BUF_PARAMS(ex), len + MAX_DICT_FILE);
 
   for (i = 0; i <= len; ++i) {
 
@@ -1465,7 +1469,6 @@ skip_interest:
 
       if (common_fuzz_stuff(afl, ex_tmp, len + afl->extras[j].len)) {
 
-        ck_free(ex_tmp);
         goto abandon_entry;
 
       }
@@ -1479,8 +1482,6 @@ skip_interest:
 
   }
 
-  ck_free(ex_tmp);
-
   new_hit_cnt = afl->queued_paths + afl->unique_crashes;
 
   afl->stage_finds[STAGE_EXTRAS_UI] += new_hit_cnt - orig_hit_cnt;
@@ -1606,18 +1607,23 @@ custom_mutator_stage:
     /* Read the additional testcase into a new buffer. */
     fd = open(target->fname, O_RDONLY);
     if (unlikely(fd < 0)) PFATAL("Unable to open '%s'", target->fname);
-    new_buf = ck_alloc_nozero(target->len);
+
+    new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), target->len);
     ck_read(fd, new_buf, target->len, target->fname);
     close(fd);
 
+    u8 *mutated_buf = NULL;
+
     size_t mutated_size = afl->mutator->afl_custom_fuzz(
-        afl, &out_buf, len, new_buf, target->len, max_seed_size);
+        afl->mutator->data, out_buf, len, &mutated_buf, new_buf, target->len,
+        max_seed_size);
 
-    ck_free(new_buf);
+    if (unlikely(!mutated_buf))
+      FATAL("Error in custom_fuzz. Size returned: %zd", mutated_size);
 
     if (mutated_size > 0) {
 
-      if (common_fuzz_stuff(afl, out_buf, (u32)mutated_size)) {
+      if (common_fuzz_stuff(afl, mutated_buf, (u32)mutated_size)) {
 
         goto abandon_entry;
 
@@ -1641,7 +1647,8 @@ custom_mutator_stage:
 
     }
 
-    if (mutated_size < len) out_buf = ck_realloc(out_buf, len);
+    /* `(afl->)out_buf` may have been changed by the call to custom_fuzz */
+    /* TODO: Only do this when `mutated_buf` == `out_buf`? Branch vs Memcpy. */
     memcpy(out_buf, in_buf, len);
 
   }
@@ -1702,7 +1709,7 @@ havoc_stage:
   if (stacked_custom && afl->mutator->afl_custom_havoc_mutation_probability) {
 
     stacked_custom_prob =
-        afl->mutator->afl_custom_havoc_mutation_probability(afl);
+        afl->mutator->afl_custom_havoc_mutation_probability(afl->mutator->data);
     if (stacked_custom_prob > 100)
       FATAL(
           "The probability returned by afl_custom_havoc_mutation_propability "
@@ -1723,8 +1730,22 @@ havoc_stage:
 
       if (stacked_custom && rand_below(afl, 100) < stacked_custom_prob) {
 
-        temp_len = afl->mutator->afl_custom_havoc_mutation(afl, &out_buf,
-                                                           temp_len, MAX_FILE);
+        u8 *   custom_havoc_buf = NULL;
+        size_t new_len = afl->mutator->afl_custom_havoc_mutation(
+            afl->mutator->data, out_buf, temp_len, &custom_havoc_buf, MAX_FILE);
+        if (unlikely(!custom_havoc_buf))
+          FATAL("Error in custom_havoc (return %zd)", new_len);
+        if (likely(new_len > 0 && custom_havoc_buf)) {
+
+          temp_len = new_len;
+          if (out_buf != custom_havoc_buf) {
+
+            ck_maybe_grow(BUF_PARAMS(out), temp_len);
+            memcpy(out_buf, custom_havoc_buf, temp_len);
+
+          }
+
+        }
 
       }
 
@@ -1954,7 +1975,8 @@ havoc_stage:
 
             clone_to = rand_below(afl, temp_len);
 
-            new_buf = ck_alloc_nozero(temp_len + clone_len);
+            new_buf =
+                ck_maybe_grow(BUF_PARAMS(out_scratch), temp_len + clone_len);
 
             /* Head */
 
@@ -1974,8 +1996,9 @@ havoc_stage:
             memcpy(new_buf + clone_to + clone_len, out_buf + clone_to,
                    temp_len - clone_to);
 
-            ck_free(out_buf);
+            swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch));
             out_buf = new_buf;
+            new_buf = NULL;
             temp_len += clone_len;
 
           }
@@ -2068,7 +2091,8 @@ havoc_stage:
 
             if (temp_len + extra_len >= MAX_FILE) break;
 
-            new_buf = ck_alloc_nozero(temp_len + extra_len);
+            new_buf =
+                ck_maybe_grow(BUF_PARAMS(out_scratch), temp_len + extra_len);
 
             /* Head */
             memcpy(new_buf, out_buf, insert_at);
@@ -2084,7 +2108,8 @@ havoc_stage:
 
             if (temp_len + extra_len >= MAX_FILE) break;
 
-            new_buf = ck_alloc_nozero(temp_len + extra_len);
+            new_buf =
+                ck_maybe_grow(BUF_PARAMS(out_scratch), temp_len + extra_len);
 
             /* Head */
             memcpy(new_buf, out_buf, insert_at);
@@ -2098,8 +2123,9 @@ havoc_stage:
           memcpy(new_buf + insert_at + extra_len, out_buf + insert_at,
                  temp_len - insert_at);
 
-          ck_free(out_buf);
+          swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch));
           out_buf = new_buf;
+          new_buf = NULL;
           temp_len += extra_len;
 
           break;
@@ -2115,7 +2141,7 @@ havoc_stage:
     /* out_buf might have been mangled a bit, so let's restore it to its
        original size and shape. */
 
-    if (temp_len < len) out_buf = ck_realloc(out_buf, len);
+    out_buf = ck_maybe_grow(BUF_PARAMS(out), len);
     temp_len = len;
     memcpy(out_buf, in_buf, len);
 
@@ -2177,7 +2203,6 @@ retry_splicing:
 
     if (in_buf != orig_in) {
 
-      ck_free(in_buf);
       in_buf = orig_in;
       len = afl->queue_cur->len;
 
@@ -2221,7 +2246,7 @@ retry_splicing:
 
     if (unlikely(fd < 0)) PFATAL("Unable to open '%s'", target->fname);
 
-    new_buf = ck_alloc_nozero(target->len);
+    new_buf = ck_maybe_grow(BUF_PARAMS(in_scratch), target->len);
 
     ck_read(fd, new_buf, target->len, target->fname);
 
@@ -2233,12 +2258,7 @@ retry_splicing:
 
     locate_diffs(in_buf, new_buf, MIN(len, target->len), &f_diff, &l_diff);
 
-    if (f_diff < 0 || l_diff < 2 || f_diff == l_diff) {
-
-      ck_free(new_buf);
-      goto retry_splicing;
-
-    }
+    if (f_diff < 0 || l_diff < 2 || f_diff == l_diff) { goto retry_splicing; }
 
     /* Split somewhere between the first and last differing byte. */
 
@@ -2248,10 +2268,10 @@ retry_splicing:
 
     len = target->len;
     memcpy(new_buf, in_buf, split_at);
+    swap_bufs(BUF_PARAMS(in), BUF_PARAMS(in_scratch));
     in_buf = new_buf;
 
-    ck_free(out_buf);
-    out_buf = ck_alloc_nozero(len);
+    out_buf = ck_maybe_grow(BUF_PARAMS(out), len);
     memcpy(out_buf, in_buf, len);
 
     goto custom_mutator_stage;
@@ -2279,12 +2299,14 @@ radamsa_stage:
 
   orig_hit_cnt = afl->queued_paths + afl->unique_crashes;
 
-  /* Read the additional testcase into a new buffer. */
-  u8 *save_buf = ck_alloc_nozero(len);
+  /* Read the additional testcase.
+  We'll reuse in_scratch, as it is free at this point.
+  */
+  u8 *save_buf = ck_maybe_grow(BUF_PARAMS(in_scratch), len);
   memcpy(save_buf, out_buf, len);
 
   u32 max_len = len + choose_block_len(afl, HAVOC_BLK_XL);
-  u8 *new_buf = ck_alloc_nozero(max_len);
+  u8 *new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), max_len);
   u8 *tmp_buf;
 
   for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) {
@@ -2304,19 +2326,10 @@ radamsa_stage:
 
     }
 
-    if (common_fuzz_stuff(afl, tmp_buf, temp_len)) {
-
-      ck_free(save_buf);
-      ck_free(new_buf);
-      goto abandon_entry;
-
-    }
+    if (common_fuzz_stuff(afl, tmp_buf, temp_len)) { goto abandon_entry; }
 
   }
 
-  ck_free(save_buf);
-  ck_free(new_buf);
-
   new_hit_cnt = afl->queued_paths + afl->unique_crashes;
 
   afl->stage_finds[STAGE_RADAMSA] += new_hit_cnt - orig_hit_cnt;
@@ -2346,10 +2359,6 @@ abandon_entry:
 
   munmap(orig_in, afl->queue_cur->len);
 
-  if (in_buf != orig_in) ck_free(in_buf);
-  ck_free(out_buf);
-  ck_free(eff_map);
-
   return ret_val;
 
 #undef FLIP_BIT
@@ -2448,7 +2457,7 @@ u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
      single byte anyway, so it wouldn't give us any performance or memory usage
      benefits. */
 
-  out_buf = ck_alloc_nozero(len);
+  out_buf = ck_maybe_grow(BUF_PARAMS(out), len);
 
   afl->subseq_tmouts = 0;
 
@@ -2727,7 +2736,7 @@ u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
   /* Initialize effector map for the next step (see comments below). Always
          flag first and last byte as doing something. */
 
-  eff_map = ck_alloc(EFF_ALEN(len));
+  eff_map = ck_maybe_grow(BUF_PARAMS(eff), EFF_ALEN(len));
   eff_map[0] = 1;
 
   if (EFF_APOS(len - 1) != 0) {
@@ -3451,7 +3460,7 @@ skip_interest:
 
   orig_hit_cnt = new_hit_cnt;
 
-  ex_tmp = ck_alloc(len + MAX_DICT_FILE);
+  ex_tmp = ck_maybe_grow(BUF_PARAMS(ex), len + MAX_DICT_FILE);
 
   for (i = 0; i <= len; ++i) {
 
@@ -3474,7 +3483,6 @@ skip_interest:
 
       if (common_fuzz_stuff(afl, ex_tmp, len + afl->extras[j].len)) {
 
-        ck_free(ex_tmp);
         goto abandon_entry;
 
       }
@@ -3488,8 +3496,6 @@ skip_interest:
 
   }                                                  /* for i = 0; i <= len */
 
-  ck_free(ex_tmp);
-
   new_hit_cnt = afl->queued_paths + afl->unique_crashes;
 
   afl->stage_finds[STAGE_EXTRAS_UI] += new_hit_cnt - orig_hit_cnt;
@@ -3893,7 +3899,8 @@ pacemaker_fuzzing:
 
                 clone_to = rand_below(afl, temp_len);
 
-                new_buf = ck_alloc_nozero(temp_len + clone_len);
+                new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch),
+                                        temp_len + clone_len);
 
                 /* Head */
 
@@ -3914,7 +3921,7 @@ pacemaker_fuzzing:
                 memcpy(new_buf + clone_to + clone_len, out_buf + clone_to,
                        temp_len - clone_to);
 
-                ck_free(out_buf);
+                swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch));
                 out_buf = new_buf;
                 temp_len += clone_len;
                 MOpt_globals.cycles_v2[STAGE_Clone75] += 1;
@@ -3967,7 +3974,7 @@ pacemaker_fuzzing:
         /* out_buf might have been mangled a bit, so let's restore it to its
            original size and shape. */
 
-        if (temp_len < len) out_buf = ck_realloc(out_buf, len);
+        out_buf = ck_maybe_grow(BUF_PARAMS(out), len);
         temp_len = len;
         memcpy(out_buf, in_buf, len);
 
@@ -4045,7 +4052,6 @@ pacemaker_fuzzing:
 
         if (in_buf != orig_in) {
 
-          ck_free(in_buf);
           in_buf = orig_in;
           len = afl->queue_cur->len;
 
@@ -4090,7 +4096,7 @@ pacemaker_fuzzing:
 
         if (fd < 0) PFATAL("Unable to open '%s'", target->fname);
 
-        new_buf = ck_alloc_nozero(target->len);
+        new_buf = ck_maybe_grow(BUF_PARAMS(in_scratch), target->len);
 
         ck_read(fd, new_buf, target->len, target->fname);
 
@@ -4104,7 +4110,6 @@ pacemaker_fuzzing:
 
         if (f_diff < 0 || l_diff < 2 || f_diff == l_diff) {
 
-          ck_free(new_buf);
           goto retry_splicing_puppet;
 
         }
@@ -4117,9 +4122,9 @@ pacemaker_fuzzing:
 
         len = target->len;
         memcpy(new_buf, in_buf, split_at);
+        swap_bufs(BUF_PARAMS(in), BUF_PARAMS(in_scratch));
         in_buf = new_buf;
-        ck_free(out_buf);
-        out_buf = ck_alloc_nozero(len);
+        out_buf = ck_maybe_grow(BUF_PARAMS(out), len);
         memcpy(out_buf, in_buf, len);
 
         goto havoc_stage_puppet;
@@ -4154,10 +4159,6 @@ pacemaker_fuzzing:
 
       munmap(orig_in, afl->queue_cur->len);
 
-      if (in_buf != orig_in) ck_free(in_buf);
-      ck_free(out_buf);
-      ck_free(eff_map);
-
       if (afl->key_puppet == 1) {
 
         if (unlikely(
@@ -4379,18 +4380,13 @@ u8 fuzz_one(afl_state_t *afl) {
   int key_val_lv = 0;
 
 #ifdef _AFL_DOCUMENT_MUTATIONS
-  if (afl->do_document == 0) {
-
-    char *fn = alloc_printf("%s/mutations", afl->out_dir);
-    if (fn) {
 
-      afl->do_document = mkdir(fn, 0700);  // if it exists we do not care
-      afl->do_document = 1;
-      ck_free(fn);
-
-    } else
+  u8 path_buf[PATH_MAX];
+  if (afl->do_document == 0) {
 
-      PFATAL("malloc()");
+    snprintf(path_buf, PATH_MAX, "%s/mutations", afl->out_dir);
+    afl->do_document = mkdir(path_buf, 0700);  // if it exists we do not care
+    afl->do_document = 1;
 
   } else {
 
@@ -4418,5 +4414,7 @@ u8 fuzz_one(afl_state_t *afl) {
 
   return key_val_lv;
 
+#undef BUF_PARAMS
+
 }
 
diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c
index d3027d2b..12c3a09d 100644
--- a/src/afl-fuzz-python.c
+++ b/src/afl-fuzz-python.c
@@ -29,19 +29,28 @@
 #ifdef USE_PYTHON
 
 static void *unsupported(afl_state_t *afl, unsigned int seed) {
+
   FATAL("Python Mutator cannot be called twice yet");
   return NULL;
+
 }
 
-size_t fuzz_py(void *py_mutator, u8 **buf, size_t buf_size, u8 *add_buf,
-               size_t add_buf_size, size_t max_size) {
+/* sorry for this makro...
+it just fills in `&py_mutator->something_buf, &py_mutator->something_size`. */
+#define BUF_PARAMS(name)                              \
+  (void **)&((py_mutator_t *)py_mutator)->name##_buf, \
+      &((py_mutator_t *)py_mutator)->name##_size
+
+size_t fuzz_py(void *py_mutator, u8 *buf, size_t buf_size, u8 **out_buf,
+               u8 *add_buf, size_t add_buf_size, size_t max_size) {
 
   size_t    mutated_size;
   PyObject *py_args, *py_value;
   py_args = PyTuple_New(3);
+  py_mutator_t *py = (py_mutator_t *)py_mutator;
 
   /* buf */
-  py_value = PyByteArray_FromStringAndSize(*buf, buf_size);
+  py_value = PyByteArray_FromStringAndSize(buf, buf_size);
   if (!py_value) {
 
     Py_DECREF(py_args);
@@ -77,29 +86,29 @@ size_t fuzz_py(void *py_mutator, u8 **buf, size_t buf_size, u8 *add_buf,
 
   PyTuple_SetItem(py_args, 2, py_value);
 
-  py_value = PyObject_CallObject(((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_FUZZ], py_args);
+  py_value = PyObject_CallObject(py->py_functions[PY_FUNC_FUZZ], py_args);
 
   Py_DECREF(py_args);
 
   if (py_value != NULL) {
 
     mutated_size = PyByteArray_Size(py_value);
-    if (buf_size < mutated_size) *buf = ck_realloc(*buf, mutated_size);
 
-    memcpy(*buf, PyByteArray_AsString(py_value), mutated_size);
+    *out_buf = ck_maybe_grow(BUF_PARAMS(fuzz), mutated_size);
+
+    memcpy(*out_buf, PyByteArray_AsString(py_value), mutated_size);
     Py_DECREF(py_value);
     return mutated_size;
 
   } else {
 
     PyErr_Print();
-    FATAL("Call failed");
+    FATAL("python custom fuzz: call failed");
 
   }
 
 }
 
-
 static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
 
   if (!module_name) return NULL;
@@ -124,8 +133,8 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
   if (py_module != NULL) {
 
     u8 py_notrim = 0, py_idx;
+    /* init, required */
     py_functions[PY_FUNC_INIT] = PyObject_GetAttrString(py_module, "init");
-    py_functions[PY_FUNC_DEINIT] = PyObject_GetAttrString(py_module, "deinit");
     py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "fuzz");
     py_functions[PY_FUNC_PRE_SAVE] =
         PyObject_GetAttrString(py_module, "pre_save");
@@ -142,6 +151,7 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
         PyObject_GetAttrString(py_module, "queue_get");
     py_functions[PY_FUNC_QUEUE_NEW_ENTRY] =
         PyObject_GetAttrString(py_module, "queue_new_entry");
+    py_functions[PY_FUNC_DEINIT] = PyObject_GetAttrString(py_module, "deinit");
 
     for (py_idx = 0; py_idx < PY_FUNC_COUNT; ++py_idx) {
 
@@ -223,7 +233,8 @@ void finalize_py_module(void *py_mutator) {
 
 }
 
-static void init_py(afl_state_t *afl, py_mutator_t *py_mutator, unsigned int seed) {
+static void init_py(afl_state_t *afl, py_mutator_t *py_mutator,
+                    unsigned int seed) {
 
   PyObject *py_args, *py_value;
 
@@ -244,7 +255,8 @@ static void init_py(afl_state_t *afl, py_mutator_t *py_mutator, unsigned int see
 
   PyTuple_SetItem(py_args, 0, py_value);
 
-  py_value = PyObject_CallObject(py_mutator->py_functions[PY_FUNC_INIT], py_args);
+  py_value =
+      PyObject_CallObject(py_mutator->py_functions[PY_FUNC_INIT], py_args);
 
   Py_DECREF(py_args);
 
@@ -283,15 +295,16 @@ void deinit_py(void *py_mutator) {
 void load_custom_mutator_py(afl_state_t *afl, char *module_name) {
 
   afl->mutator = ck_alloc(sizeof(struct custom_mutator));
+  afl->mutator->pre_save_buf = NULL;
+  afl->mutator->pre_save_size = 0;
 
   afl->mutator->name = module_name;
   ACTF("Loading Python mutator library from '%s'...", module_name);
 
   py_mutator_t *py_mutator;
   py_mutator = init_py_module(afl, module_name);
-  if (!py_mutator) {
-    FATAL("Failed to load python mutator.");
-  }
+  afl->mutator->data = py_mutator;
+  if (!py_mutator) { FATAL("Failed to load python mutator."); }
 
   PyObject **py_functions = py_mutator->py_functions;
 
@@ -334,44 +347,50 @@ void load_custom_mutator_py(afl_state_t *afl, char *module_name) {
 
 }
 
-
 size_t pre_save_py(void *py_mutator, u8 *buf, size_t buf_size, u8 **out_buf) {
 
-  size_t    out_buf_size;
-  PyObject *py_args, *py_value;
+  size_t        py_out_buf_size;
+  PyObject *    py_args, *py_value;
+  py_mutator_t *py = (py_mutator_t *)py_mutator;
+
   py_args = PyTuple_New(1);
   py_value = PyByteArray_FromStringAndSize(buf, buf_size);
   if (!py_value) {
 
     Py_DECREF(py_args);
-    FATAL("Failed to convert arguments");
+    FATAL("Failed to convert arguments in custom pre_save");
 
   }
 
   PyTuple_SetItem(py_args, 0, py_value);
 
-  py_value = PyObject_CallObject(((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_PRE_SAVE], py_args);
+  py_value = PyObject_CallObject(
+      ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_PRE_SAVE], py_args);
 
   Py_DECREF(py_args);
 
   if (py_value != NULL) {
 
-    out_buf_size = PyByteArray_Size(py_value);
-    *out_buf = malloc(out_buf_size);
-    memcpy(*out_buf, PyByteArray_AsString(py_value), out_buf_size);
+    py_out_buf_size = PyByteArray_Size(py_value);
+
+    ck_maybe_grow(BUF_PARAMS(pre_save), py_out_buf_size);
+
+    memcpy(py->pre_save_buf, PyByteArray_AsString(py_value), py_out_buf_size);
     Py_DECREF(py_value);
-    return out_buf_size;
+
+    *out_buf = py->pre_save_buf;
+    return py_out_buf_size;
 
   } else {
 
     PyErr_Print();
-    FATAL("Call failed");
+    FATAL("Python custom mutator: pre_save call failed.");
 
   }
 
 }
 
-u32 init_trim_py(void *py_mutator, u8 *buf, size_t buf_size) {
+s32 init_trim_py(void *py_mutator, u8 *buf, size_t buf_size) {
 
   PyObject *py_args, *py_value;
 
@@ -386,7 +405,8 @@ u32 init_trim_py(void *py_mutator, u8 *buf, size_t buf_size) {
 
   PyTuple_SetItem(py_args, 0, py_value);
 
-  py_value = PyObject_CallObject(((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_INIT_TRIM], py_args);
+  py_value = PyObject_CallObject(
+      ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_INIT_TRIM], py_args);
   Py_DECREF(py_args);
 
   if (py_value != NULL) {
@@ -408,7 +428,7 @@ u32 init_trim_py(void *py_mutator, u8 *buf, size_t buf_size) {
 
 }
 
-u32 post_trim_py(void *py_mutator, u8 success) {
+s32 post_trim_py(void *py_mutator, u8 success) {
 
   PyObject *py_args, *py_value;
 
@@ -424,7 +444,8 @@ u32 post_trim_py(void *py_mutator, u8 success) {
 
   PyTuple_SetItem(py_args, 0, py_value);
 
-  py_value = PyObject_CallObject(((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_POST_TRIM], py_args);
+  py_value = PyObject_CallObject(
+      ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_POST_TRIM], py_args);
   Py_DECREF(py_args);
 
   if (py_value != NULL) {
@@ -446,19 +467,21 @@ u32 post_trim_py(void *py_mutator, u8 success) {
 
 }
 
-void trim_py(void *py_mutator, u8 **out_buf, size_t *out_buf_size) {
+size_t trim_py(void *py_mutator, u8 **out_buf) {
 
   PyObject *py_args, *py_value;
+  size_t    ret;
 
   py_args = PyTuple_New(0);
-  py_value = PyObject_CallObject(((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_TRIM], py_args);
+  py_value = PyObject_CallObject(
+      ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_TRIM], py_args);
   Py_DECREF(py_args);
 
   if (py_value != NULL) {
 
-    *out_buf_size = PyByteArray_Size(py_value);
-    *out_buf = malloc(*out_buf_size);
-    memcpy(*out_buf, PyByteArray_AsString(py_value), *out_buf_size);
+    ret = PyByteArray_Size(py_value);
+    *out_buf = ck_maybe_grow(BUF_PARAMS(trim), ret);
+    memcpy(*out_buf, PyByteArray_AsString(py_value), ret);
     Py_DECREF(py_value);
 
   } else {
@@ -468,17 +491,19 @@ void trim_py(void *py_mutator, u8 **out_buf, size_t *out_buf_size) {
 
   }
 
+  return ret;
+
 }
 
-size_t havoc_mutation_py(void *py_mutator, u8 **buf, size_t buf_size,
-                         size_t max_size) {
+size_t havoc_mutation_py(void *py_mutator, u8 *buf, size_t buf_size,
+                         u8 **out_buf, size_t max_size) {
 
   size_t    mutated_size;
   PyObject *py_args, *py_value;
   py_args = PyTuple_New(2);
 
   /* buf */
-  py_value = PyByteArray_FromStringAndSize(*buf, buf_size);
+  py_value = PyByteArray_FromStringAndSize(buf, buf_size);
   if (!py_value) {
 
     Py_DECREF(py_args);
@@ -503,17 +528,28 @@ size_t havoc_mutation_py(void *py_mutator, u8 **buf, size_t buf_size,
 
   PyTuple_SetItem(py_args, 1, py_value);
 
-  py_value =
-      PyObject_CallObject(((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_HAVOC_MUTATION], py_args);
+  py_value = PyObject_CallObject(
+      ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_HAVOC_MUTATION],
+      py_args);
 
   Py_DECREF(py_args);
 
   if (py_value != NULL) {
 
     mutated_size = PyByteArray_Size(py_value);
-    if (buf_size < mutated_size) *buf = ck_realloc(*buf, mutated_size);
+    if (mutated_size <= buf_size) {
 
-    memcpy(*buf, PyByteArray_AsString(py_value), mutated_size);
+      /* We reuse the input buf here. */
+      *out_buf = buf;
+
+    } else {
+
+      /* A new buf is needed... */
+      *out_buf = ck_maybe_grow(BUF_PARAMS(havoc), mutated_size);
+
+    }
+
+    memcpy(*out_buf, PyByteArray_AsString(py_value), mutated_size);
 
     Py_DECREF(py_value);
     return mutated_size;
@@ -533,7 +569,9 @@ u8 havoc_mutation_probability_py(void *py_mutator) {
 
   py_args = PyTuple_New(0);
   py_value = PyObject_CallObject(
-      ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_HAVOC_MUTATION_PROBABILITY], py_args);
+      ((py_mutator_t *)py_mutator)
+          ->py_functions[PY_FUNC_HAVOC_MUTATION_PROBABILITY],
+      py_args);
   Py_DECREF(py_args);
 
   if (py_value != NULL) {
@@ -573,7 +611,8 @@ u8 queue_get_py(void *py_mutator, const u8 *filename) {
   PyTuple_SetItem(py_args, 0, py_value);
 
   // Call Python function
-  py_value = PyObject_CallObject(((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_QUEUE_GET], py_args);
+  py_value = PyObject_CallObject(
+      ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_QUEUE_GET], py_args);
   Py_DECREF(py_args);
 
   if (py_value != NULL) {
@@ -642,8 +681,9 @@ void queue_new_entry_py(void *py_mutator, const u8 *filename_new_queue,
   PyTuple_SetItem(py_args, 1, py_value);
 
   // Call
-  py_value =
-      PyObject_CallObject(((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_QUEUE_NEW_ENTRY], py_args);
+  py_value = PyObject_CallObject(
+      ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_QUEUE_NEW_ENTRY],
+      py_args);
   Py_DECREF(py_args);
 
   if (py_value == NULL) {
@@ -655,5 +695,7 @@ void queue_new_entry_py(void *py_mutator, const u8 *filename_new_queue,
 
 }
 
+#undef BUF_PARAMS
+
 #endif                                                        /* USE_PYTHON */
 
diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c
index f49e1f1e..92cbab6f 100644
--- a/src/afl-fuzz-queue.c
+++ b/src/afl-fuzz-queue.c
@@ -30,18 +30,16 @@
 
 void mark_as_det_done(afl_state_t *afl, struct queue_entry *q) {
 
-  u8 *fn = strrchr(q->fname, '/');
+  u8  fn[PATH_MAX];
   s32 fd;
 
-  fn = alloc_printf("%s/queue/.state/deterministic_done/%s", afl->out_dir,
-                    fn + 1);
+  snprintf(fn, PATH_MAX, "%s/queue/.state/deterministic_done/%s", afl->out_dir,
+           strrchr(q->fname, '/') + 1);
 
   fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
   if (fd < 0) PFATAL("Unable to create '%s'", fn);
   close(fd);
 
-  ck_free(fn);
-
   q->passed_det = 1;
 
 }
@@ -51,10 +49,13 @@ void mark_as_det_done(afl_state_t *afl, struct queue_entry *q) {
 
 void mark_as_variable(afl_state_t *afl, struct queue_entry *q) {
 
-  u8 *fn = strrchr(q->fname, '/') + 1, *ldest;
+  u8 fn[PATH_MAX];
+  u8 ldest[PATH_MAX];
+
+  u8 *fn_name = strrchr(q->fname, '/') + 1;
 
-  ldest = alloc_printf("../../%s", fn);
-  fn = alloc_printf("%s/queue/.state/variable_behavior/%s", afl->out_dir, fn);
+  sprintf(ldest, "../../%s", fn_name);
+  sprintf(fn, "%s/queue/.state/variable_behavior/%s", afl->out_dir, fn_name);
 
   if (symlink(ldest, fn)) {
 
@@ -64,9 +65,6 @@ void mark_as_variable(afl_state_t *afl, struct queue_entry *q) {
 
   }
 
-  ck_free(ldest);
-  ck_free(fn);
-
   q->var_behavior = 1;
 
 }
@@ -76,14 +74,14 @@ void mark_as_variable(afl_state_t *afl, struct queue_entry *q) {
 
 void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) {
 
-  u8 *fn;
+  u8 fn[PATH_MAX];
 
   if (state == q->fs_redundant) return;
 
   q->fs_redundant = state;
 
-  fn = strrchr(q->fname, '/');
-  fn = alloc_printf("%s/queue/.state/redundant_edges/%s", afl->out_dir, fn + 1);
+  sprintf(fn, "%s/queue/.state/redundant_edges/%s", afl->out_dir,
+          strrchr(q->fname, '/') + 1);
 
   if (state) {
 
@@ -99,8 +97,6 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) {
 
   }
 
-  ck_free(fn);
-
 }
 
 /* Append new test case to the queue. */
@@ -114,6 +110,7 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
   q->depth = afl->cur_depth + 1;
   q->passed_det = passed_det;
   q->n_fuzz = 1;
+  q->trace_mini = NULL;
 
   if (q->depth > afl->max_depth) afl->max_depth = q->depth;
 
@@ -147,7 +144,8 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
     /* At the initialization stage, queue_cur is NULL */
     if (afl->queue_cur) fname_orig = afl->queue_cur->fname;
 
-    afl->mutator->afl_custom_queue_new_entry(afl, fname, fname_orig);
+    afl->mutator->afl_custom_queue_new_entry(afl->mutator->data, fname,
+                                             fname_orig);
 
   }
 
@@ -186,9 +184,9 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
 
   u32 i;
   u64 fav_factor;
-  u64 fuzz_p2 = next_p2(q->n_fuzz);
+  u64 fuzz_p2 = next_pow2(q->n_fuzz);
 
-  if (afl->schedule == MMOPT || afl->schedule == RARE)
+  if (afl->schedule == MMOPT || afl->schedule == RARE || unlikely(afl->fixed_seed))
     fav_factor = q->len << 2;
   else
     fav_factor = q->exec_us * q->len;
@@ -203,9 +201,9 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
 
         /* Faster-executing or smaller test cases are favored. */
         u64 top_rated_fav_factor;
-        u64 top_rated_fuzz_p2 = next_p2(afl->top_rated[i]->n_fuzz);
+        u64 top_rated_fuzz_p2 = next_pow2(afl->top_rated[i]->n_fuzz);
 
-        if (afl->schedule == MMOPT || afl->schedule == RARE)
+        if (afl->schedule == MMOPT || afl->schedule == RARE || unlikely(afl->fixed_seed))
           top_rated_fav_factor = afl->top_rated[i]->len << 2;
         else
           top_rated_fav_factor =
@@ -216,8 +214,17 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
         else if (fuzz_p2 == top_rated_fuzz_p2)
           if (fav_factor > top_rated_fav_factor) continue;
 
-        if (fav_factor > afl->top_rated[i]->exec_us * afl->top_rated[i]->len)
-          continue;
+        if (afl->schedule == MMOPT || afl->schedule == RARE || unlikely(afl->fixed_seed)) {
+
+          if (fav_factor > afl->top_rated[i]->len << 2)
+            continue;
+
+        } else {        
+
+          if (fav_factor > afl->top_rated[i]->exec_us * afl->top_rated[i]->len)
+            continue;
+        
+        }
 
         /* Looks like we're going to win. Decrease ref count for the
            previous winner, discard its afl->fsrv.trace_bits[] if necessary. */
@@ -332,7 +339,7 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) {
   // Longer execution time means longer work on the input, the deeper in
   // coverage, the better the fuzzing, right? -mh
 
-  if (afl->schedule != MMOPT && afl->schedule != RARE) {
+  if (afl->schedule != MMOPT && afl->schedule != RARE && likely(!afl->fixed_seed)) {
 
     if (q->exec_us * 0.1 > avg_exec_us)
       perf_score = 10;
@@ -442,7 +449,7 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) {
       if (q->fuzz_level < 16)
         factor = ((u32)(1 << q->fuzz_level)) / (fuzz == 0 ? 1 : fuzz);
       else
-        factor = MAX_FACTOR / (fuzz == 0 ? 1 : next_p2(fuzz));
+        factor = MAX_FACTOR / (fuzz == 0 ? 1 : next_pow2(fuzz));
       break;
 
     case LIN: factor = q->fuzz_level / (fuzz == 0 ? 1 : fuzz); break;
diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c
index b069fa77..4acc204b 100644
--- a/src/afl-fuzz-redqueen.c
+++ b/src/afl-fuzz-redqueen.c
@@ -529,9 +529,10 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len,
 
     if (!afl->shm.cmp_map->headers[k].hits) continue;
     if (afl->shm.cmp_map->headers[k].type == CMP_TYPE_INS)
-      afl->stage_max += MIN(afl->shm.cmp_map->headers[k].hits, CMP_MAP_H);
+      afl->stage_max += MIN((u32)afl->shm.cmp_map->headers[k].hits, CMP_MAP_H);
     else
-      afl->stage_max += MIN(afl->shm.cmp_map->headers[k].hits, CMP_MAP_RTN_H);
+      afl->stage_max +=
+          MIN((u32)afl->shm.cmp_map->headers[k].hits, CMP_MAP_RTN_H);
 
   }
 
diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c
index 8c4b5941..5875eb68 100644
--- a/src/afl-fuzz-run.c
+++ b/src/afl-fuzz-run.c
@@ -33,13 +33,10 @@
 u8 run_target(afl_state_t *afl, u32 timeout) {
 
   s32 res;
-  int sret;
+  u32 exec_ms;
 
-  fd_set readfds;
-
-  struct timeval it;
-  int            status = 0;
-  u32            tb4;
+  int status = 0;
+  u32 tb4;
 
   afl->fsrv.child_timed_out = 0;
 
@@ -70,26 +67,20 @@ u8 run_target(afl_state_t *afl, u32 timeout) {
 
   if (afl->fsrv.child_pid <= 0) FATAL("Fork server is misbehaving (OOM?)");
 
-  /* use select to monitor the forkserver for timeouts. */
-
-  FD_ZERO(&readfds);
-  FD_SET(afl->fsrv.fsrv_st_fd, &readfds);
-  it.tv_sec = ((timeout) / 1000);
-  it.tv_usec = ((timeout) % 1000) * 1000;
-
-  sret = select(afl->fsrv.fsrv_st_fd + 1, &readfds, NULL, NULL, &it);
+  exec_ms = read_timed(afl->fsrv.fsrv_st_fd, &status, 4, timeout);
 
-  if (sret == 0) {
+  if (exec_ms > timeout) {
 
     /* If there was no response from forkserver after timeout seconds,
     we kill the child. The forkserver should inform us afterwards */
 
     kill(afl->fsrv.child_pid, SIGKILL);
     afl->fsrv.child_timed_out = 1;
+    if (read(afl->fsrv.fsrv_st_fd, &status, 4) < 4) exec_ms = 0;
 
   }
 
-  if ((res = read(afl->fsrv.fsrv_st_fd, &status, 4)) != 4) {
+  if (!exec_ms) {
 
     if (afl->stop_soon) return 0;
     SAYF("\n" cLRD "[-] " cRST
@@ -176,20 +167,16 @@ void write_to_testcase(afl_state_t *afl, void *mem, u32 len) {
   s32 fd = afl->fsrv.out_fd;
 
 #ifdef _AFL_DOCUMENT_MUTATIONS
-  s32   doc_fd;
-  char *fn = alloc_printf("%s/mutations/%09u:%s", afl->out_dir,
+  s32  doc_fd;
+  char fn[PATH_MAX];
+  snprintf(fn, PATH_MAX, ("%s/mutations/%09u:%s", afl->out_dir,
                           afl->document_counter++, describe_op(afl, 0));
-  if (fn != NULL) {
-
-    if ((doc_fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600)) >= 0) {
-
-      if (write(doc_fd, mem, len) != len)
-        PFATAL("write to mutation file failed: %s", fn);
-      close(doc_fd);
 
-    }
+  if ((doc_fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600)) >= 0) {
 
-    ck_free(fn);
+    if (write(doc_fd, mem, len) != len)
+      PFATAL("write to mutation file failed: %s", fn);
+    close(doc_fd);
 
   }
 
@@ -214,16 +201,22 @@ void write_to_testcase(afl_state_t *afl, void *mem, u32 len) {
 
     lseek(fd, 0, SEEK_SET);
 
-  if (afl->mutator && afl->mutator->afl_custom_pre_save) {
+  if (unlikely(afl->mutator && afl->mutator->afl_custom_pre_save)) {
+
+    u8 *new_buf = NULL;
+
+    size_t new_size = afl->mutator->afl_custom_pre_save(afl->mutator->data, mem,
+                                                        len, &new_buf);
 
-    u8 *   new_data;
-    size_t new_size =
-        afl->mutator->afl_custom_pre_save(afl, mem, len, &new_data);
-    ck_write(fd, new_data, new_size, afl->fsrv.out_file);
-    ck_free(new_data);
+    if (unlikely(!new_buf))
+      FATAL("Custom_pre_save failed (ret: %lu)", (long unsigned)new_size);
+
+    /* everything as planned. use the new data. */
+    ck_write(fd, new_buf, new_size, afl->fsrv.out_file);
 
   } else {
 
+    /* boring uncustom. */
     ck_write(fd, mem, len, afl->fsrv.out_file);
 
   }
@@ -505,8 +498,8 @@ void sync_fuzzers(afl_state_t *afl) {
     afl->stage_cur = 0;
     afl->stage_max = 0;
 
-    /* For every file queued by this fuzzer, parse ID and see if we have looked
-       at it before; exec a test case if not. */
+    /* For every file queued by this fuzzer, parse ID and see if we have
+       looked at it before; exec a test case if not. */
 
     while ((qd_ent = readdir(qd))) {
 
@@ -615,7 +608,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
 
   /* Select initial chunk len, starting with large steps. */
 
-  len_p2 = next_p2(q->len);
+  len_p2 = next_pow2(q->len);
 
   remove_len = MAX(len_p2 / TRIM_START_STEPS, TRIM_MIN_BYTES);
 
@@ -627,8 +620,8 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
     u32 remove_pos = remove_len;
 
     sprintf(afl->stage_name_buf, "trim %s/%s",
-             u_stringify_int(val_bufs[0], remove_len),
-             u_stringify_int(val_bufs[1], remove_len));
+            u_stringify_int(val_bufs[0], remove_len),
+            u_stringify_int(val_bufs[1], remove_len));
 
     afl->stage_cur = 0;
     afl->stage_max = q->len / remove_len;
@@ -645,7 +638,8 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
 
       if (afl->stop_soon || fault == FAULT_ERROR) goto abort_trimming;
 
-      /* Note that we don't keep track of crashes or hangs here; maybe TODO? */
+      /* Note that we don't keep track of crashes or hangs here; maybe TODO?
+       */
 
       cksum = hash32(afl->fsrv.trace_bits, MAP_SIZE, HASH_CONST);
 
@@ -659,7 +653,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
         u32 move_tail = q->len - remove_pos - trim_avail;
 
         q->len -= trim_avail;
-        len_p2 = next_p2(q->len);
+        len_p2 = next_pow2(q->len);
 
         memmove(in_buf + remove_pos, in_buf + remove_pos + trim_avail,
                 move_tail);
@@ -734,8 +728,13 @@ u8 common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
 
   if (afl->post_handler) {
 
-    out_buf = afl->post_handler(out_buf, &len);
-    if (!out_buf || !len) return 0;
+    u8 *post_buf = NULL;
+
+    size_t post_len =
+        afl->post_handler(afl->post_data, out_buf, len, &post_buf);
+    if (!post_buf || !post_len) return 0;
+    out_buf = post_buf;
+    len = post_len;
 
   }
 
diff --git a/src/afl-fuzz-globals.c b/src/afl-fuzz-state.c
index 88633a1b..80176a10 100644
--- a/src/afl-fuzz-globals.c
+++ b/src/afl-fuzz-state.c
@@ -34,8 +34,6 @@ char *power_names[POWER_SCHEDULES_NUM] = {
 
     "explore", "fast", "coe", "lin", "quad", "exploit", "mmopt", "rare"};
 
-u8 *doc_path = NULL;                    /* gath to documentation dir        */
-
 /* Initialize MOpt "globals" for this afl state */
 
 static void init_mopt_globals(afl_state_t *afl) {
@@ -79,6 +77,8 @@ list_t afl_states = {.element_prealloc_count = 0};
 
 void afl_state_init(afl_state_t *afl) {
 
+  /* thanks to this memset, growing vars like out_buf
+  and out_size are NULL/0 by default. */
   memset(afl, 0, sizeof(afl_state_t));
 
   afl->w_init = 0.9;
@@ -347,6 +347,15 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
 
 void afl_state_deinit(afl_state_t *afl) {
 
+  if (afl->post_deinit) afl->post_deinit(afl->post_data);
+
+  free(afl->out_buf);
+  free(afl->out_scratch_buf);
+  free(afl->eff_buf);
+  free(afl->in_buf);
+  free(afl->in_scratch_buf);
+  free(afl->ex_buf);
+
   list_remove(&afl_states, afl);
 
 }
diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c
index dc16df8f..77bbe023 100644
--- a/src/afl-fuzz-stats.c
+++ b/src/afl-fuzz-stats.c
@@ -33,16 +33,17 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
   struct rusage rus;
 
   unsigned long long int cur_time = get_cur_time();
-  u8 *                   fn = alloc_printf("%s/fuzzer_stats", afl->out_dir);
+  u8                     fn[PATH_MAX];
   s32                    fd;
   FILE *                 f;
+  uint32_t               t_bytes = count_non_255_bytes(afl->virgin_bits);
+
+  snprintf(fn, PATH_MAX, "%s/fuzzer_stats", afl->out_dir);
 
   fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600);
 
   if (fd < 0) PFATAL("Unable to create '%s'", fn);
 
-  ck_free(fn);
-
   f = fdopen(fd, "w");
 
   if (!f) PFATAL("fdopen() failed");
@@ -95,8 +96,10 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
       "last_hang         : %llu\n"
       "execs_since_crash : %llu\n"
       "exec_timeout      : %u\n"
-      "slowest_exec_ms   : %llu\n"
+      "slowest_exec_ms   : %u\n"
       "peak_rss_mb       : %lu\n"
+      "var_byte_count    : %u\n"
+      "found_edges       : %u\n"
       "afl_banner        : %s\n"
       "afl_version       : " VERSION
       "\n"
@@ -119,9 +122,10 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
 #else
       (unsigned long int)(rus.ru_maxrss >> 10),
 #endif
-      afl->use_banner, afl->unicorn_mode ? "unicorn" : "",
-      afl->qemu_mode ? "qemu " : "", afl->dumb_mode ? " dumb " : "",
-      afl->no_forkserver ? "no_fsrv " : "", afl->crash_mode ? "crash " : "",
+      afl->var_byte_count, t_bytes, afl->use_banner,
+      afl->unicorn_mode ? "unicorn" : "", afl->qemu_mode ? "qemu " : "",
+      afl->dumb_mode ? " dumb " : "", afl->no_forkserver ? "no_fsrv " : "",
+      afl->crash_mode ? "crash " : "",
       afl->persistent_mode ? "persistent " : "",
       afl->deferred_mode ? "deferred " : "",
       (afl->unicorn_mode || afl->qemu_mode || afl->dumb_mode ||
@@ -257,7 +261,7 @@ void show_stats(afl_state_t *afl) {
   t_byte_ratio = ((double)t_bytes * 100) / MAP_SIZE;
 
   if (t_bytes)
-    stab_ratio = 100 - ((double)afl->var_byte_count) * 100 / t_bytes;
+    stab_ratio = 100 - (((double)afl->var_byte_count) * 100) / t_bytes;
   else
     stab_ratio = 100;
 
@@ -406,8 +410,7 @@ void show_stats(afl_state_t *afl) {
       (afl->last_path_time || afl->resuming_fuzz || afl->queue_cycle == 1 ||
        afl->in_bitmap || afl->crash_mode)) {
 
-    u_stringify_time_diff(time_tmp, cur_ms,
-                        afl->last_path_time);
+    u_stringify_time_diff(time_tmp, cur_ms, afl->last_path_time);
     SAYF(bV bSTOP "   last new path : " cRST "%-33s ", time_tmp);
 
   } else {
@@ -533,24 +536,21 @@ void show_stats(afl_state_t *afl) {
 
   if (afl->stats_avg_exec < 100) {
 
-    sprintf(tmp, "%s/sec (%s)",
-             u_stringify_float(IB(0), afl->stats_avg_exec),
-             afl->stats_avg_exec < 20 ? "zzzz..." : "slow!");
+    sprintf(tmp, "%s/sec (%s)", u_stringify_float(IB(0), afl->stats_avg_exec),
+            afl->stats_avg_exec < 20 ? "zzzz..." : "slow!");
 
     SAYF(bV bSTOP "  exec speed : " cLRD "%-20s ", tmp);
 
   } else {
 
-    sprintf(tmp, "%s/sec",
-             u_stringify_float(IB(0), afl->stats_avg_exec));
+    sprintf(tmp, "%s/sec", u_stringify_float(IB(0), afl->stats_avg_exec));
     SAYF(bV bSTOP "  exec speed : " cRST "%-20s ", tmp);
 
   }
 
-  sprintf(tmp, "%s (%s%s unique)",
-           u_stringify_int(IB(0), afl->total_tmouts),
-           u_stringify_int(IB(1), afl->unique_tmouts),
-           (afl->unique_hangs >= KEEP_UNIQUE_HANG) ? "+" : "");
+  sprintf(tmp, "%s (%s%s unique)", u_stringify_int(IB(0), afl->total_tmouts),
+          u_stringify_int(IB(1), afl->unique_tmouts),
+          (afl->unique_hangs >= KEEP_UNIQUE_HANG) ? "+" : "");
 
   SAYF(bSTG bV bSTOP "  total tmouts : " cRST "%-22s" bSTG bV "\n", tmp);
 
@@ -567,12 +567,12 @@ void show_stats(afl_state_t *afl) {
   } else {
 
     sprintf(tmp, "%s/%s, %s/%s, %s/%s",
-             u_stringify_int(IB(0), afl->stage_finds[STAGE_FLIP1]),
-             u_stringify_int(IB(1), afl->stage_cycles[STAGE_FLIP1]),
-             u_stringify_int(IB(2), afl->stage_finds[STAGE_FLIP2]),
-             u_stringify_int(IB(3), afl->stage_cycles[STAGE_FLIP2]),
-             u_stringify_int(IB(3), afl->stage_finds[STAGE_FLIP4]),
-             u_stringify_int(IB(5), afl->stage_cycles[STAGE_FLIP4]));
+            u_stringify_int(IB(0), afl->stage_finds[STAGE_FLIP1]),
+            u_stringify_int(IB(1), afl->stage_cycles[STAGE_FLIP1]),
+            u_stringify_int(IB(2), afl->stage_finds[STAGE_FLIP2]),
+            u_stringify_int(IB(3), afl->stage_cycles[STAGE_FLIP2]),
+            u_stringify_int(IB(4), afl->stage_finds[STAGE_FLIP4]),
+            u_stringify_int(IB(5), afl->stage_cycles[STAGE_FLIP4]));
 
   }
 
@@ -582,12 +582,12 @@ void show_stats(afl_state_t *afl) {
 
   if (!afl->skip_deterministic)
     sprintf(tmp, "%s/%s, %s/%s, %s/%s",
-             u_stringify_int(IB(0), afl->stage_finds[STAGE_FLIP8]),
-             u_stringify_int(IB(1), afl->stage_cycles[STAGE_FLIP8]),
-             u_stringify_int(IB(2), afl->stage_finds[STAGE_FLIP16]),
-             u_stringify_int(IB(3), afl->stage_cycles[STAGE_FLIP16]),
-             u_stringify_int(IB(4), afl->stage_finds[STAGE_FLIP32]),
-             u_stringify_int(IB(5), afl->stage_cycles[STAGE_FLIP32]));
+            u_stringify_int(IB(0), afl->stage_finds[STAGE_FLIP8]),
+            u_stringify_int(IB(1), afl->stage_cycles[STAGE_FLIP8]),
+            u_stringify_int(IB(2), afl->stage_finds[STAGE_FLIP16]),
+            u_stringify_int(IB(3), afl->stage_cycles[STAGE_FLIP16]),
+            u_stringify_int(IB(4), afl->stage_finds[STAGE_FLIP32]),
+            u_stringify_int(IB(5), afl->stage_cycles[STAGE_FLIP32]));
 
   SAYF(bV bSTOP "  byte flips : " cRST "%-36s " bSTG bV bSTOP
                 "   pending : " cRST "%-10s" bSTG       bV "\n",
@@ -595,12 +595,12 @@ void show_stats(afl_state_t *afl) {
 
   if (!afl->skip_deterministic)
     sprintf(tmp, "%s/%s, %s/%s, %s/%s",
-             u_stringify_int(IB(0), afl->stage_finds[STAGE_ARITH8]),
-             u_stringify_int(IB(1), afl->stage_cycles[STAGE_ARITH8]),
-             u_stringify_int(IB(2), afl->stage_finds[STAGE_ARITH16]),
-             u_stringify_int(IB(3), afl->stage_cycles[STAGE_ARITH16]),
-             u_stringify_int(IB(4), afl->stage_finds[STAGE_ARITH32]),
-             u_stringify_int(IB(5), afl->stage_cycles[STAGE_ARITH32]));
+            u_stringify_int(IB(0), afl->stage_finds[STAGE_ARITH8]),
+            u_stringify_int(IB(1), afl->stage_cycles[STAGE_ARITH8]),
+            u_stringify_int(IB(2), afl->stage_finds[STAGE_ARITH16]),
+            u_stringify_int(IB(3), afl->stage_cycles[STAGE_ARITH16]),
+            u_stringify_int(IB(4), afl->stage_finds[STAGE_ARITH32]),
+            u_stringify_int(IB(5), afl->stage_cycles[STAGE_ARITH32]));
 
   SAYF(bV bSTOP " arithmetics : " cRST "%-36s " bSTG bV bSTOP
                 "  pend fav : " cRST "%-10s" bSTG       bV "\n",
@@ -621,25 +621,26 @@ void show_stats(afl_state_t *afl) {
 
   if (!afl->skip_deterministic)
     sprintf(tmp, "%s/%s, %s/%s, %s/%s",
-             u_stringify_int(IB(0), afl->stage_finds[STAGE_EXTRAS_UO]),
-             u_stringify_int(IB(1), afl->stage_cycles[STAGE_EXTRAS_UO]),
-             u_stringify_int(IB(2), afl->stage_finds[STAGE_EXTRAS_UI]),
-             u_stringify_int(IB(3), afl->stage_cycles[STAGE_EXTRAS_UI]),
-             u_stringify_int(IB(4), afl->stage_finds[STAGE_EXTRAS_AO]),
-             u_stringify_int(IB(5), afl->stage_cycles[STAGE_EXTRAS_AO]));
+            u_stringify_int(IB(0), afl->stage_finds[STAGE_EXTRAS_UO]),
+            u_stringify_int(IB(1), afl->stage_cycles[STAGE_EXTRAS_UO]),
+            u_stringify_int(IB(2), afl->stage_finds[STAGE_EXTRAS_UI]),
+            u_stringify_int(IB(3), afl->stage_cycles[STAGE_EXTRAS_UI]),
+            u_stringify_int(IB(4), afl->stage_finds[STAGE_EXTRAS_AO]),
+            u_stringify_int(IB(5), afl->stage_cycles[STAGE_EXTRAS_AO]));
 
   SAYF(bV bSTOP "  dictionary : " cRST "%-36s " bSTG bV bSTOP
                 "  imported : " cRST "%-10s" bSTG       bV "\n",
        tmp,
-       afl->sync_id ? u_stringify_int(IB(0), afl->queued_imported) : (u8 *)"n/a");
+       afl->sync_id ? u_stringify_int(IB(0), afl->queued_imported)
+                    : (u8 *)"n/a");
 
   sprintf(tmp, "%s/%s, %s/%s, %s/%s",
-           u_stringify_int(IB(0), afl->stage_finds[STAGE_HAVOC]),
-           u_stringify_int(IB(2), afl->stage_cycles[STAGE_HAVOC]),
-           u_stringify_int(IB(3), afl->stage_finds[STAGE_SPLICE]),
-           u_stringify_int(IB(4), afl->stage_cycles[STAGE_SPLICE]),
-           u_stringify_int(IB(5), afl->stage_finds[STAGE_RADAMSA]),
-           u_stringify_int(IB(6), afl->stage_cycles[STAGE_RADAMSA]));
+          u_stringify_int(IB(0), afl->stage_finds[STAGE_HAVOC]),
+          u_stringify_int(IB(2), afl->stage_cycles[STAGE_HAVOC]),
+          u_stringify_int(IB(3), afl->stage_finds[STAGE_SPLICE]),
+          u_stringify_int(IB(4), afl->stage_cycles[STAGE_SPLICE]),
+          u_stringify_int(IB(5), afl->stage_finds[STAGE_RADAMSA]),
+          u_stringify_int(IB(6), afl->stage_cycles[STAGE_RADAMSA]));
 
   SAYF(bV bSTOP "   havoc/rad : " cRST "%-36s " bSTG bV bSTOP, tmp);
 
@@ -660,14 +661,14 @@ void show_stats(afl_state_t *afl) {
   if (afl->shm.cmplog_mode) {
 
     sprintf(tmp, "%s/%s, %s/%s, %s/%s, %s/%s",
-             u_stringify_int(IB(0), afl->stage_finds[STAGE_PYTHON]),
-             u_stringify_int(IB(1), afl->stage_cycles[STAGE_PYTHON]),
-             u_stringify_int(IB(2), afl->stage_finds[STAGE_CUSTOM_MUTATOR]),
-             u_stringify_int(IB(3), afl->stage_cycles[STAGE_CUSTOM_MUTATOR]),
-             u_stringify_int(IB(4), afl->stage_finds[STAGE_COLORIZATION]),
-             u_stringify_int(IB(5), afl->stage_cycles[STAGE_COLORIZATION]),
-             u_stringify_int(IB(6), afl->stage_finds[STAGE_ITS]),
-             u_stringify_int(IB(7), afl->stage_cycles[STAGE_ITS]));
+            u_stringify_int(IB(0), afl->stage_finds[STAGE_PYTHON]),
+            u_stringify_int(IB(1), afl->stage_cycles[STAGE_PYTHON]),
+            u_stringify_int(IB(2), afl->stage_finds[STAGE_CUSTOM_MUTATOR]),
+            u_stringify_int(IB(3), afl->stage_cycles[STAGE_CUSTOM_MUTATOR]),
+            u_stringify_int(IB(4), afl->stage_finds[STAGE_COLORIZATION]),
+            u_stringify_int(IB(5), afl->stage_cycles[STAGE_COLORIZATION]),
+            u_stringify_int(IB(6), afl->stage_finds[STAGE_ITS]),
+            u_stringify_int(IB(7), afl->stage_cycles[STAGE_ITS]));
 
     SAYF(bV bSTOP "   custom/rq : " cRST "%-36s " bSTG bVR bH20 bH2 bH bRB "\n",
          tmp);
@@ -675,10 +676,10 @@ void show_stats(afl_state_t *afl) {
   } else {
 
     sprintf(tmp, "%s/%s, %s/%s",
-             u_stringify_int(IB(0), afl->stage_finds[STAGE_PYTHON]),
-             u_stringify_int(IB(1), afl->stage_cycles[STAGE_PYTHON]),
-             u_stringify_int(IB(2), afl->stage_finds[STAGE_CUSTOM_MUTATOR]),
-             u_stringify_int(IB(3), afl->stage_cycles[STAGE_CUSTOM_MUTATOR]));
+            u_stringify_int(IB(0), afl->stage_finds[STAGE_PYTHON]),
+            u_stringify_int(IB(1), afl->stage_cycles[STAGE_PYTHON]),
+            u_stringify_int(IB(2), afl->stage_finds[STAGE_CUSTOM_MUTATOR]),
+            u_stringify_int(IB(3), afl->stage_cycles[STAGE_CUSTOM_MUTATOR]));
 
     SAYF(bV bSTOP "   py/custom : " cRST "%-36s " bSTG bVR bH20 bH2 bH bRB "\n",
          tmp);
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index ba56ff67..ad4f5b6b 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -25,8 +25,6 @@
 
 #include "afl-fuzz.h"
 
-u8 be_quiet = 0;
-
 static u8 *get_libradamsa_path(u8 *own_loc) {
 
   u8 *tmp, *cp, *rsl, *own_copy;
@@ -693,6 +691,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
   if (afl->fixed_seed) OKF("Running with fixed seed: %u", (u32)afl->init_seed);
   srandom((u32)afl->init_seed);
+  srand((u32)afl->init_seed);  // in case it is a different implementation
 
   if (afl->use_radamsa) {
 
@@ -723,6 +722,16 @@ int main(int argc, char **argv_orig, char **envp) {
 
   }
 
+#if defined(__SANITIZE_ADDRESS__)
+  if (afl->fsrv.mem_limit) {
+
+    WARNF("in the ASAN build we disable all memory limits");
+    afl->fsrv.mem_limit = 0;
+
+  }
+
+#endif
+
   setup_signal_handlers();
   check_asan_opts();
 
diff --git a/src/afl-showmap.c b/src/afl-showmap.c
index caacefe4..f8a38c36 100644
--- a/src/afl-showmap.c
+++ b/src/afl-showmap.c
@@ -59,13 +59,10 @@
 #include <sys/types.h>
 #include <sys/resource.h>
 
-u8 be_quiet;
-
 char *stdin_file;                      /* stdin file                        */
 
 u8 *in_dir,                            /* input folder                      */
-    *doc_path,                         /* Path to docs                      */
-        *at_file = NULL;               /* Substitution string for @@        */
+    *at_file = NULL;              /* Substitution string for @@             */
 
 static u8 *in_data;                    /* Input data                        */
 
@@ -224,26 +221,6 @@ static u32 write_results(afl_forkserver_t *fsrv) {
 
 }
 
-/* Write output file. */
-
-static s32 write_to_file(u8 *path, u8 *mem, u32 len) {
-
-  s32 ret;
-
-  unlink(path);                                            /* Ignore errors */
-
-  ret = open(path, O_RDWR | O_CREAT | O_EXCL, 0600);
-
-  if (ret < 0) PFATAL("Unable to create '%s'", path);
-
-  ck_write(ret, mem, len, path);
-
-  lseek(ret, 0, SEEK_SET);
-
-  return ret;
-
-}
-
 /* Write modified data to file for testing. If use_stdin is clear, the old file
    is unlinked and a new one is created. Otherwise, out_fd is rewound and
    truncated. */
diff --git a/src/afl-tmin.c b/src/afl-tmin.c
index 2275aef5..30e76d42 100644
--- a/src/afl-tmin.c
+++ b/src/afl-tmin.c
@@ -61,8 +61,7 @@
 static u8 *mask_bitmap;                /* Mask for trace bits (-B)          */
 
 u8 *in_file,                           /* Minimizer input test case         */
-    *output_file,                      /* Minimizer output file             */
-    *doc_path;                         /* Path to docs                      */
+    *output_file;                      /* Minimizer output file             */
 
 static u8 *in_data;                    /* Input data for trimming           */
 
@@ -77,8 +76,7 @@ u8 crash_mode,                         /* Crash-centric mode?               */
     hang_mode,                         /* Minimize as long as it hangs      */
     exit_crash,                        /* Treat non-zero exit as crash?     */
     edges_only,                        /* Ignore hit counts?                */
-    exact_mode,                        /* Require path match for crashes?   */
-    be_quiet;
+    exact_mode;                        /* Require path match for crashes?   */
 
 static volatile u8 stop_soon;          /* Ctrl-C pressed?                   */
 
@@ -406,17 +404,6 @@ static u8 run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len,
 
 }
 
-/* Find first power of two greater or equal to val. */
-
-static u32 next_p2(u32 val) {
-
-  u32 ret = 1;
-  while (val > ret)
-    ret <<= 1;
-  return ret;
-
-}
-
 /* Actually minimize! */
 
 static void minimize(afl_forkserver_t *fsrv, char **argv) {
@@ -434,7 +421,7 @@ static void minimize(afl_forkserver_t *fsrv, char **argv) {
    * BLOCK NORMALIZATION *
    ***********************/
 
-  set_len = next_p2(in_len / TMIN_SET_STEPS);
+  set_len = next_pow2(in_len / TMIN_SET_STEPS);
   set_pos = 0;
 
   if (set_len < TMIN_SET_MIN_SIZE) set_len = TMIN_SET_MIN_SIZE;
@@ -484,7 +471,7 @@ next_pass:
    * BLOCK DELETION *
    ******************/
 
-  del_len = next_p2(in_len / TRIM_START_STEPS);
+  del_len = next_pow2(in_len / TRIM_START_STEPS);
   stage_o_len = in_len;
 
   ACTF(cBRI "Stage #1: " cRST "Removing blocks of data...");
diff --git a/src/third_party/libradamsa/libradamsa.c b/src/third_party/libradamsa/libradamsa.c
index f3677fa7..fe91594e 100644
--- a/src/third_party/libradamsa/libradamsa.c
+++ b/src/third_party/libradamsa/libradamsa.c
@@ -30815,7 +30815,7 @@ size_t copy_list(uint8_t *ptr, word lispval, size_t max) {
       lispval = G(lispval, 2);              // list   = cdr(list)
    }
    if (lispval != INULL && max == 0) {
-      printf("ERROR: lisp return value was not a proper list. Trailing %lu\n", lispval);
+      printf("ERROR: lisp return value was not a proper list. Trailing %lu\n", (unsigned long)lispval);
    }
    return n;
 }
diff --git a/test/test-custom-mutator.c b/test/test-custom-mutator.c
new file mode 100644
index 00000000..83baafab
--- /dev/null
+++ b/test/test-custom-mutator.c
@@ -0,0 +1,19 @@
+/**
+ * Reference: https://github.com/bruce30262/libprotobuf-mutator_fuzzing_learning/blob/master/4_libprotobuf_aflpp_custom_mutator/vuln.c
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+int main(int argc, char *argv[])
+{
+    char str[100];
+    read(0, str, 100);
+    if( str[6] == 'A') {
+        abort();
+    }
+    return 0;
+}
diff --git a/test/test.sh b/test/test.sh
index 8434aaf1..a04df384 100755
--- a/test/test.sh
+++ b/test/test.sh
@@ -73,7 +73,7 @@ export ASAN_OPTIONS=detect_leaks=0:allocator_may_return_null=1:abort_on_error=1:
 # on OpenBSD we need to work with llvm from /usr/local/bin
 test -e /usr/local/bin/opt && {
   export PATH=/usr/local/bin:${PATH}
-} 
+}
 # on MacOS X we prefer afl-clang over afl-gcc, because
 # afl-gcc does not work there
 test `uname -s` = 'Darwin' -o `uname -s` = 'FreeBSD' && {
@@ -142,11 +142,11 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc
       CODE=1
     }
     rm -f test-compcov.harden
-  } || { 
+  } || {
     $ECHO "$RED[!] ${AFL_GCC} hardened mode compilation failed"
     CODE=1
   }
-  # now we want to be sure that afl-fuzz is working  
+  # now we want to be sure that afl-fuzz is working
   # make sure core_pattern is set to core on linux
   (test "$(uname -s)" = "Linux" && test "$(sysctl kernel.core_pattern)" != "kernel.core_pattern = core" && {
     $ECHO "$YELLOW[-] we should not run afl-fuzz with enabled core dumps. Run 'sudo sh afl-system-config'.$RESET"
@@ -210,13 +210,13 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc
     unset AFL_QUIET
   }
   rm -f test-instr.plain
- } || { 
+ } || {
   $ECHO "$YELLOW[-] afl is not compiled, cannot test"
   INCOMPLETE=1
  }
-} || { 
+} || {
  $ECHO "$YELLOW[-] not an intel platform, cannot test afl-gcc"
-} 
+}
 
 $ECHO "$BLUE[*] Testing: llvm_mode, afl-showmap, afl-fuzz, afl-cmin and afl-tmin"
 test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
@@ -248,7 +248,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
           CODE=1
         }
       }
-    } || { 
+    } || {
       $ECHO "$RED[!] llvm_mode instrumentation failed"
       CODE=1
     }
@@ -265,11 +265,11 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
       CODE=1
     }
     rm -f test-compcov.harden
-  } || { 
+  } || {
     $ECHO "$RED[!] llvm_mode hardened mode compilation failed"
     CODE=1
   }
-  # now we want to be sure that afl-fuzz is working  
+  # now we want to be sure that afl-fuzz is working
   (test "$(uname -s)" = "Linux" && test "$(sysctl kernel.core_pattern)" != "kernel.core_pattern = core" && {
     $ECHO "$YELLOW[-] we should not run afl-fuzz with enabled core dumps. Run 'sudo sh afl-system-config'.$RESET"
     true
@@ -373,7 +373,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
       $ECHO "$RED[!] llvm_mode whitelist feature failed"
       CODE=1
     }
-  } || { 
+  } || {
     $ECHO "$RED[!] llvm_mode whitelist feature compilation failed"
     CODE=1
   }
@@ -426,7 +426,7 @@ test -e ../afl-clang-lto -a -e ../afl-llvm-lto-instrumentation.so && {
           CODE=1
         }
       }
-    } || { 
+    } || {
       $ECHO "$RED[!] llvm_mode LTO instrumentation failed"
       CODE=1
     }
@@ -447,7 +447,7 @@ test -e ../afl-clang-lto -a -e ../afl-llvm-lto-instrumentation.so && {
 #      $ECHO "$RED[!] llvm_mode LTO whitelist feature failed"
 #      CODE=1
 #    }
-#  } || { 
+#  } || {
 #    $ECHO "$RED[!] llvm_mode LTO whitelist feature compilation failed"
 #    CODE=1
 #  }
@@ -483,7 +483,7 @@ test -e ../afl-gcc-fast -a -e ../afl-gcc-rt.o && {
       diff test-instr.plain.0 test-instr.plain.1 > /dev/null 2>&1 && {
         $ECHO "$RED[!] gcc_plugin instrumentation should be different on different input but is not"
         CODE=1
-      } || { 
+      } || {
         $ECHO "$GREEN[+] gcc_plugin instrumentation present and working correctly"
         TUPLES=`echo 0|../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-instr.plain.gccpi 2>&1 | grep Captur | awk '{print$3}'`
         test "$TUPLES" -gt 3 -a "$TUPLES" -lt 7 && {
@@ -516,7 +516,7 @@ test -e ../afl-gcc-fast -a -e ../afl-gcc-rt.o && {
     $ECHO "$RED[!] gcc_plugin hardened mode compilation failed"
     CODE=1
   }
-  # now we want to be sure that afl-fuzz is working  
+  # now we want to be sure that afl-fuzz is working
   (test "$(uname -s)" = "Linux" && test "$(sysctl kernel.core_pattern)" != "kernel.core_pattern = core" && {
     $ECHO "$YELLOW[-] we should not run afl-fuzz with enabled core dumps. Run 'sudo sh afl-system-config'.$RESET"
     true
@@ -552,11 +552,11 @@ test -e ../afl-gcc-fast -a -e ../afl-gcc-rt.o && {
   test -e test-compcov && {
     echo 1 | ../afl-showmap -m ${MEM_LIMIT} -o - -r -- ./test-compcov 2>&1 | grep -q "Captured 1 tuples" && {
       $ECHO "$GREEN[+] gcc_plugin whitelist feature works correctly"
-    } || { 
+    } || {
       $ECHO "$RED[!] gcc_plugin whitelist feature failed"
       CODE=1
     }
-  } || { 
+  } || {
     $ECHO "$RED[!] gcc_plugin whitelist feature compilation failed"
     CODE=1
   }
@@ -580,12 +580,12 @@ test -e ../afl-gcc-fast -a -e ../afl-gcc-rt.o && {
 }
 
 $ECHO "$BLUE[*] Testing: shared library extensions"
-cc -o test-compcov test-compcov.c > /dev/null 2>&1
+cc $CFLAGS -o test-compcov test-compcov.c > /dev/null 2>&1
 test -e ../libtokencap.so && {
   AFL_TOKEN_FILE=token.out LD_PRELOAD=../libtokencap.so DYLD_INSERT_LIBRARIES=../libtokencap.so DYLD_FORCE_FLAT_NAMESPACE=1 ./test-compcov foobar > /dev/null 2>&1
   grep -q BUGMENOT token.out > /dev/null 2>&1 && {
     $ECHO "$GREEN[+] libtokencap did successfully capture tokens"
-  } || { 
+  } || {
     $ECHO "$RED[!] libtokencap did not capture tokens"
     CODE=1
   }
@@ -604,7 +604,7 @@ test -e ../libdislocator.so && {
     $ECHO "$RED[!] libdislocator did not detect the memory corruption"
     CODE=1
   } || {
-    $ECHO "$GREEN[+] libdislocator did successfully detect the memory corruption" 
+    $ECHO "$GREEN[+] libdislocator did successfully detect the memory corruption"
   }
   rm -f test.out core test-compcov.core core.test-compcov
 } || {
@@ -700,7 +700,7 @@ test -e ../afl-qemu-trace && {
         test -e ../libcompcov.so && {
           $ECHO "$GREY[*] running afl-fuzz for qemu_mode compcov, this will take approx 10 seconds"
           {
-            export AFL_PRELOAD=../libcompcov.so 
+            export AFL_PRELOAD=../libcompcov.so
             export AFL_COMPCOV_LEVEL=2
             ../afl-fuzz -m ${MEM_LIMIT} -V10 -Q -i in -o out -- ./test-compcov >>errors 2>&1
             unset AFL_PRELOAD
@@ -720,10 +720,10 @@ test -e ../afl-qemu-trace && {
           INCOMPLETE=1
         }
         rm -f errors
-      } || { 
+      } || {
        $ECHO "$YELLOW[-] not an intel or arm platform, cannot test qemu_mode compcov"
       }
-      
+
       test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc" -o "$SYS" = "aarch64" -o ! "${SYS%%arm*}" && {
         $ECHO "$GREY[*] running afl-fuzz for persistent qemu_mode, this will take approx 10 seconds"
         {
@@ -757,9 +757,9 @@ test -e ../afl-qemu-trace && {
           exit 1
         }
         rm -rf in out errors
-      } || { 
+      } || {
        $ECHO "$YELLOW[-] not an intel or arm platform, cannot test persistent qemu_mode"
-      } 
+      }
 
       test -e ../qemu_mode/unsigaction/unsigaction32.so && {
         ${AFL_CC} -o test-unsigaction32 -m32 test-unsigaction.c >> errors 2>&1 && {
@@ -824,7 +824,7 @@ test -e ../afl-qemu-trace && {
     $ECHO "$RED[!] gcc compilation of test targets failed - what is going on??"
     CODE=1
   }
-  
+
   rm -f test-instr test-compcov
 } || {
   $ECHO "$YELLOW[-] qemu_mode is not compiled, cannot test"
@@ -887,12 +887,94 @@ test -d ../unicorn_mode/unicornafl && {
     $ECHO "$RED[!] missing sample binaries in unicorn_mode/samples/ - what is going on??"
     CODE=1
   }
-  
+
 } || {
   $ECHO "$YELLOW[-] unicorn_mode is not compiled, cannot test"
   INCOMPLETE=1
 }
 
+$ECHO "$BLUE[*] Testing: custom mutator"
+unset AFL_CC  # Test case "gcc_plugin" sets AFL_CC to "gcc". We reset it to use the default compiler
+test `uname -s` = 'Darwin' && {
+  CUSTOM_MUTATOR_PATH=$( realpath ../examples/custom_mutators )
+} || {
+  CUSTOM_MUTATOR_PATH=$( readlink -f ../examples/custom_mutators )
+}
+test -e test-custom-mutator.c -a -e ${CUSTOM_MUTATOR_PATH}/example.c -a -e ${CUSTOM_MUTATOR_PATH}/example.py && {
+  # Compile the vulnerable program
+  ../afl-clang-fast -o test-custom-mutator test-custom-mutator.c > /dev/null 2>&1
+  # Compile the custom mutator
+  make -C ../examples/custom_mutators libexamplemutator.so > /dev/null 2>&1
+  test -e test-custom-mutator -a -e ${CUSTOM_MUTATOR_PATH}/libexamplemutator.so && {
+    # Create input directory
+    mkdir -p in
+    echo "00000" > in/in
+
+    # Run afl-fuzz w/ the C mutator
+    $ECHO "$GREY[*] running afl-fuzz for the C mutator, this will take approx 10 seconds"
+    {
+      AFL_CUSTOM_MUTATOR_LIBRARY=${CUSTOM_MUTATOR_PATH}/libexamplemutator.so ../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -- ./test-custom-mutator >>errors 2>&1
+    } >>errors 2>&1
+
+    # Check results
+    test -n "$( ls out/crashes/id:000000* 2>/dev/null )" && {  # TODO: update here
+      $ECHO "$GREEN[+] afl-fuzz is working correctly with the C mutator"
+    } || {
+      echo CUT------------------------------------------------------------------CUT
+      cat errors
+      echo CUT------------------------------------------------------------------CUT
+      $ECHO "$RED[!] afl-fuzz is not working correctly with the C mutator"
+      CODE=1
+    }
+
+    # Clean
+    rm -rf out errors
+
+    # Run afl-fuzz w/ the Python mutator
+    $ECHO "$GREY[*] running afl-fuzz for the Python mutator, this will take approx 10 seconds"
+    {
+      export PYTHONPATH=${CUSTOM_MUTATOR_PATH}
+      export AFL_PYTHON_MODULE=example
+      ../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -- ./test-custom-mutator >>errors 2>&1
+      unset PYTHONPATH
+      unset AFL_PYTHON_MODULE
+    } >>errors 2>&1
+
+    # Check results
+    test -n "$( ls out/crashes/id:000000* 2>/dev/null )" && {  # TODO: update here
+      $ECHO "$GREEN[+] afl-fuzz is working correctly with the Python mutator"
+    } || {
+      echo CUT------------------------------------------------------------------CUT
+      cat errors
+      echo CUT------------------------------------------------------------------CUT
+      $ECHO "$RED[!] afl-fuzz is not working correctly with the Python mutator"
+      CODE=1
+    }
+
+    # Clean
+    rm -rf in out errors
+    rm -rf ${CUSTOM_MUTATOR_PATH}/__pycache__/
+  } || {
+    ls .
+    ls ${CUSTOM_MUTATOR_PATH}
+    $ECHO "$RED[!] cannot compile the test program or the custom mutator"
+    CODE=1
+  }
+
+  #test "$CODE" = 1 && { $ECHO "$YELLOW[!] custom mutator tests currently will not fail travis" ; CODE=0 ; }
+
+  make -C ../examples/custom_mutators clean > /dev/null 2>&1
+  rm -f test-custom-mutator
+} || {
+  $ECHO "$YELLOW[-] no custom mutators in $CUSTOM_MUTATOR_PATH, cannot test"
+  INCOMPLETE=1
+}
+unset CUSTOM_MUTATOR_PATH
+
+$ECHO "$BLUE[*] Execution cmocka Unit-Tests $GREY"
+unset AFL_CC
+make -C .. unit || "$CODE" = "1"
+
 $ECHO "$GREY[*] all test cases completed.$RESET"
 test "$INCOMPLETE" = "0" && $ECHO "$GREEN[+] all test cases executed"
 test "$INCOMPLETE" = "1" && $ECHO "$YELLOW[-] not all test cases were executed"
diff --git a/test/unittests/unit_list.c b/test/unittests/unit_list.c
new file mode 100644
index 00000000..03217112
--- /dev/null
+++ b/test/unittests/unit_list.c
@@ -0,0 +1,128 @@
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <assert.h>
+#include <cmocka.h>
+/* cmocka < 1.0 didn't support these features we need */
+#ifndef assert_ptr_equal
+#define assert_ptr_equal(a, b) \
+    _assert_int_equal(cast_ptr_to_largest_integral_type(a), \
+                      cast_ptr_to_largest_integral_type(b), \
+                      __FILE__, __LINE__)
+#define CMUnitTest UnitTest
+#define cmocka_unit_test unit_test
+#define cmocka_run_group_tests(t, setup, teardown) run_tests(t)
+#endif
+
+
+extern void mock_assert(const int result, const char* const expression,
+                        const char * const file, const int line);
+#undef assert
+#define assert(expression) \
+    mock_assert((int)(expression), #expression, __FILE__, __LINE__);
+
+#include "list.h"
+
+/* remap exit -> assert, then use cmocka's mock_assert
+    (compile with `--wrap=exit`) */
+extern void exit(int status);
+extern void __real_exit(int status);
+void __wrap_exit(int status) {
+    assert(0);
+}
+
+/* ignore all printfs */
+extern int printf(const char *format, ...);
+extern int __real_printf(const char *format, ...);
+int __wrap_printf(const char *format, ...) {
+    return 1;
+}
+
+list_t testlist;
+
+static void test_contains(void **state) {
+
+    u32 one = 1;
+    u32 two = 2;
+
+    list_append(&testlist, &one);
+    assert_true(list_contains(&testlist, &one));
+    assert_false(list_contains(&testlist, &two));
+    list_remove(&testlist, &one);
+    assert_false(list_contains(&testlist, &one));
+}
+
+static void test_foreach(void **state) {
+
+    u32 one = 1;
+    u32 two = 2;
+    u32 result = 0;
+
+    list_append(&testlist, &one);
+    list_append(&testlist, &two);
+    list_append(&testlist, &one);
+
+    /* The list is for pointers, so int doesn't work as type directly */
+    LIST_FOREACH(&testlist, u32, {
+        result += *el;
+    });
+
+    assert_int_equal(result, 4);
+
+}
+
+static void test_long_list(void **state) {
+
+    u32 result1 = 0;
+    u32 result2 = 0;
+    u32 i;
+
+    u32 vals[100];
+
+    for (i = 0; i < 100; i++) {
+        vals[i] = i;
+    }
+
+    LIST_FOREACH_CLEAR(&testlist, void, {});
+    for (i = 0; i < 100; i++) {
+        list_append(&testlist, &vals[i]);
+    }
+    LIST_FOREACH(&testlist, u32, {
+        result1 += *el;
+    });
+    printf("removing %d\n", vals[50]);
+    list_remove(&testlist, &vals[50]);
+
+    LIST_FOREACH(&testlist, u32, {
+        // printf("var: %d\n", *el);
+        result2 += *el;
+    });
+    assert_int_not_equal(result1, result2);
+    assert_int_equal(result1, result2 + 50);
+
+    result1 = 0;
+    LIST_FOREACH_CLEAR(&testlist, u32, {
+        result1 += *el;
+    });
+    assert_int_equal(result1, result2);
+
+    result1 = 0;
+    LIST_FOREACH(&testlist, u32, {
+        result1 += *el;
+    });
+    assert_int_equal(result1, 0);
+
+}
+
+int main(int argc, char **argv) {
+
+	const struct CMUnitTest tests[] = {
+        cmocka_unit_test(test_contains),
+        cmocka_unit_test(test_foreach),
+        cmocka_unit_test(test_long_list),
+	};
+
+    //return cmocka_run_group_tests (tests, setup, teardown);
+    return cmocka_run_group_tests (tests, NULL, NULL);
+
+}
diff --git a/test/unittests/unit_maybe_alloc.c b/test/unittests/unit_maybe_alloc.c
new file mode 100644
index 00000000..a856fa08
--- /dev/null
+++ b/test/unittests/unit_maybe_alloc.c
@@ -0,0 +1,158 @@
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <assert.h>
+#include <cmocka.h>
+/* cmocka < 1.0 didn't support these features we need */
+#ifndef assert_ptr_equal
+#define assert_ptr_equal(a, b) \
+    _assert_int_equal(cast_ptr_to_largest_integral_type(a), \
+                      cast_ptr_to_largest_integral_type(b), \
+                      __FILE__, __LINE__)
+#define CMUnitTest UnitTest
+#define cmocka_unit_test unit_test
+#define cmocka_run_group_tests(t, setup, teardown) run_tests(t)
+#endif
+
+
+extern void mock_assert(const int result, const char* const expression,
+                        const char * const file, const int line);
+#undef assert
+#define assert(expression) \
+    mock_assert((int)(expression), #expression, __FILE__, __LINE__);
+#include "alloc-inl.h"
+
+/* remap exit -> assert, then use cmocka's mock_assert
+    (compile with `--wrap=exit`) */
+extern void exit(int status);
+extern void __real_exit(int status);
+void __wrap_exit(int status) {
+    assert(0);
+}
+
+/* ignore all printfs */
+extern int printf(const char *format, ...);
+extern int __real_printf(const char *format, ...);
+int __wrap_printf(const char *format, ...) {
+    return 1;
+}
+
+#define BUF_PARAMS (void **)&buf, &size
+
+/*
+static int setup(void **state) {
+
+    return 0;
+
+}
+*/
+
+static void test_null_allocs(void **state) {
+
+    void *buf = NULL;
+    size_t size = 0;
+    void *ptr = ck_maybe_grow(BUF_PARAMS, 100);
+    assert_true(buf == ptr);
+    assert_true(size >= 100);
+    ck_free(ptr);
+
+}
+
+static void test_nonpow2_size(void **state) {
+
+    char *buf = ck_alloc(150);
+    size_t size = 150;
+    buf[140] = '5';
+    char *ptr = ck_maybe_grow(BUF_PARAMS, 160);
+    assert_ptr_equal(buf, ptr);
+    assert_true(size >= 160);
+    assert_true(buf[140] == '5');
+    ck_free(ptr);
+
+}
+
+static void test_zero_size() {
+
+    char *buf = NULL;
+    size_t size = 0;
+    assert_non_null(maybe_grow(BUF_PARAMS, 0));
+    free(buf);
+    buf = NULL;
+    size = 0;
+
+    char *ptr = ck_maybe_grow(BUF_PARAMS, 100);
+    assert_non_null(ptr);
+    assert_ptr_equal(buf, ptr);
+    assert_true(size >= 100);
+
+    expect_assert_failure(ck_maybe_grow(BUF_PARAMS, 0));
+
+    ck_free(ptr);
+
+}
+
+static void test_unchanged_size(void **state) {
+
+    void *buf = ck_alloc(100);
+    size_t size = 100;
+    void *buf_before = buf;
+    void *buf_after = ck_maybe_grow(BUF_PARAMS, 100);
+    assert_ptr_equal(buf, buf_after);
+    assert_ptr_equal(buf_after, buf_before);
+    ck_free(buf);
+
+}
+
+static void test_grow_multiple(void **state) {
+
+    char *buf = NULL;
+    size_t size = 0;
+
+    char *ptr = ck_maybe_grow(BUF_PARAMS, 100);
+    assert_ptr_equal(ptr, buf);
+    assert_true(size >= 100);
+    assert_int_equal(size, next_pow2(size));
+    buf[50] = '5';
+
+    ptr = (char *)ck_maybe_grow(BUF_PARAMS, 1000);
+    assert_ptr_equal(ptr, buf);
+    assert_true(size >= 100);
+    assert_int_equal(size, next_pow2(size));
+    buf[500] = '5';
+
+    ptr = (char *)ck_maybe_grow(BUF_PARAMS, 10000);
+    assert_ptr_equal(ptr, buf);
+    assert_true(size >= 10000);
+    assert_int_equal(size, next_pow2(size));
+    buf[5000] = '5';
+
+    assert_int_equal(buf[50], '5');
+    assert_int_equal(buf[500], '5');
+    assert_int_equal(buf[5000], '5');
+
+    ck_free(buf);
+
+}
+
+/*
+static int teardown(void **state) {
+
+    return 0;
+
+}
+*/
+
+int main(int argc, char **argv) {
+
+	const struct CMUnitTest tests[] = {
+		cmocka_unit_test(test_null_allocs),
+		cmocka_unit_test(test_nonpow2_size),
+		cmocka_unit_test(test_zero_size),
+        cmocka_unit_test(test_unchanged_size),
+        cmocka_unit_test(test_grow_multiple),
+	};
+
+    //return cmocka_run_group_tests (tests, setup, teardown);
+    return cmocka_run_group_tests (tests, NULL, NULL);
+
+}
diff --git a/test/unittests/unit_preallocable.c b/test/unittests/unit_preallocable.c
new file mode 100644
index 00000000..8cd36165
--- /dev/null
+++ b/test/unittests/unit_preallocable.c
@@ -0,0 +1,111 @@
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <assert.h>
+#include <cmocka.h>
+/* cmocka < 1.0 didn't support these features we need */
+#ifndef assert_ptr_equal
+#define assert_ptr_equal(a, b) \
+    _assert_int_equal(cast_ptr_to_largest_integral_type(a), \
+                      cast_ptr_to_largest_integral_type(b), \
+                      __FILE__, __LINE__)
+#define CMUnitTest UnitTest
+#define cmocka_unit_test unit_test
+#define cmocka_run_group_tests(t, setup, teardown) run_tests(t)
+#endif
+
+
+extern void mock_assert(const int result, const char* const expression,
+                        const char * const file, const int line);
+#undef assert
+#define assert(expression) \
+    mock_assert((int)(expression), #expression, __FILE__, __LINE__);
+
+#include "afl-prealloc.h"
+
+/* remap exit -> assert, then use cmocka's mock_assert
+    (compile with `--wrap=exit`) */
+extern void exit(int status);
+extern void __real_exit(int status);
+void __wrap_exit(int status) {
+    assert(0);
+}
+
+/* ignore all printfs */
+extern int printf(const char *format, ...);
+extern int __real_printf(const char *format, ...);
+int __wrap_printf(const char *format, ...) {
+    return 1;
+}
+
+typedef struct prealloc_me
+{
+    PREALLOCABLE;
+
+    u8 *content[128];
+
+} prealloc_me_t;
+
+#define PREALLOCED_BUF_SIZE (64)
+prealloc_me_t prealloc_me_buf[PREALLOCED_BUF_SIZE];
+size_t prealloc_me_size = 0;
+
+static void test_alloc_free(void **state) {
+
+    prealloc_me_t *prealloced = NULL;
+    PRE_ALLOC(prealloced, prealloc_me_buf, PREALLOCED_BUF_SIZE, prealloc_me_size);
+    assert_non_null(prealloced);
+    PRE_FREE(prealloced, prealloc_me_size);
+
+}
+
+static void test_prealloc_overflow(void **state) {
+
+    u32 i = 0;
+    prealloc_me_t *prealloced[PREALLOCED_BUF_SIZE + 10];
+
+    for (i = 0; i < PREALLOCED_BUF_SIZE + 10; i++) {
+
+        PRE_ALLOC(prealloced[i], prealloc_me_buf, PREALLOCED_BUF_SIZE, prealloc_me_size);
+        assert_non_null(prealloced[i]);
+
+    }
+    assert_int_equal(prealloced[0]->pre_status,  PRE_STATUS_USED);
+    assert_int_equal(prealloced[PREALLOCED_BUF_SIZE]->pre_status,  PRE_STATUS_MALLOC);
+
+    PRE_FREE(prealloced[20], prealloc_me_size);
+    PRE_ALLOC(prealloced[20], prealloc_me_buf, PREALLOCED_BUF_SIZE, prealloc_me_size);
+    assert_non_null(prealloced[20]);
+    assert_int_equal(prealloced[20]->pre_status,  PRE_STATUS_USED);
+
+    PRE_FREE(prealloced[PREALLOCED_BUF_SIZE], prealloc_me_size);
+    PRE_FREE(prealloced[0], prealloc_me_size);
+    PRE_ALLOC(prealloced[PREALLOCED_BUF_SIZE], prealloc_me_buf, PREALLOCED_BUF_SIZE, prealloc_me_size);
+    assert_non_null(prealloced[PREALLOCED_BUF_SIZE]);
+    /* there should be space now! */
+    assert_int_equal(prealloced[PREALLOCED_BUF_SIZE]->pre_status,  PRE_STATUS_USED);
+
+    PRE_ALLOC(prealloced[0], prealloc_me_buf, PREALLOCED_BUF_SIZE, prealloc_me_size);
+    assert_non_null(prealloced[0]);
+    /* no more space */
+    assert_int_equal(prealloced[0]->pre_status,  PRE_STATUS_MALLOC);
+
+    for (i = 0; i < PREALLOCED_BUF_SIZE + 10; i++) {
+
+        PRE_FREE(prealloced[i], prealloc_me_size);
+
+    }
+
+}
+
+int main(int argc, char **argv) {
+
+	const struct CMUnitTest tests[] = {
+		cmocka_unit_test(test_alloc_free),
+		cmocka_unit_test(test_prealloc_overflow),
+	};
+
+    //return cmocka_run_group_tests (tests, setup, teardown);
+    return cmocka_run_group_tests (tests, NULL, NULL);
+
+}
diff --git a/unicorn_mode/samples/c/GNUmakefile b/unicorn_mode/samples/c/GNUmakefile
new file mode 100644
index 00000000..fe100490
--- /dev/null
+++ b/unicorn_mode/samples/c/GNUmakefile
@@ -0,0 +1,42 @@
+# UnicornAFL Usage
+# Original Unicorn Example Makefile by Nguyen Anh Quynh <aquynh@gmail.com>, 2015
+# Adapted for AFL++ by domenukk <domenukk@gmail.com>, 2020
+
+UNAME_S := $(shell uname -s)
+
+LIBDIR = ../../unicornafl
+BIN_EXT =
+AR_EXT = a
+
+# Verbose output?
+V ?= 0
+
+CFLAGS += -Wall -Werror -I../../unicornafl/include
+
+LDFLAGS += -L$(LIBDIR) -lpthread -lm
+ifeq ($(UNAME_S), Linux)
+LDFLAGS += -lrt
+endif
+
+ifneq ($(CROSS),)
+CC = $(CROSS)gcc
+endif
+
+.PHONY: all clean
+
+all: harness
+
+clean:		
+	rm -rf *.o harness harness-debug
+
+harness.o: harness.c ../../unicornafl/include/unicorn/*.h
+	${CC} ${CFLAGS} -O3 -c $<
+
+harness-debug.o: harness.c ../../unicornafl/include/unicorn/*.h
+	${CC} ${CFLAGS} -g -c $< -o $@
+
+harness: harness.o
+	${CC} -L${LIBDIR} $< ../../unicornafl/libunicornafl.a $(LDFLAGS) -o $@
+
+debug: harness-debug.o
+	${CC} -L${LIBDIR} $< ../../unicornafl/libunicornafl.a $(LDFLAGS) -o harness-debug
diff --git a/unicorn_mode/samples/c/Makefile b/unicorn_mode/samples/c/Makefile
index fe100490..0b306dde 100644
--- a/unicorn_mode/samples/c/Makefile
+++ b/unicorn_mode/samples/c/Makefile
@@ -1,42 +1,2 @@
-# UnicornAFL Usage
-# Original Unicorn Example Makefile by Nguyen Anh Quynh <aquynh@gmail.com>, 2015
-# Adapted for AFL++ by domenukk <domenukk@gmail.com>, 2020
-
-UNAME_S := $(shell uname -s)
-
-LIBDIR = ../../unicornafl
-BIN_EXT =
-AR_EXT = a
-
-# Verbose output?
-V ?= 0
-
-CFLAGS += -Wall -Werror -I../../unicornafl/include
-
-LDFLAGS += -L$(LIBDIR) -lpthread -lm
-ifeq ($(UNAME_S), Linux)
-LDFLAGS += -lrt
-endif
-
-ifneq ($(CROSS),)
-CC = $(CROSS)gcc
-endif
-
-.PHONY: all clean
-
-all: harness
-
-clean:		
-	rm -rf *.o harness harness-debug
-
-harness.o: harness.c ../../unicornafl/include/unicorn/*.h
-	${CC} ${CFLAGS} -O3 -c $<
-
-harness-debug.o: harness.c ../../unicornafl/include/unicorn/*.h
-	${CC} ${CFLAGS} -g -c $< -o $@
-
-harness: harness.o
-	${CC} -L${LIBDIR} $< ../../unicornafl/libunicornafl.a $(LDFLAGS) -o $@
-
-debug: harness-debug.o
-	${CC} -L${LIBDIR} $< ../../unicornafl/libunicornafl.a $(LDFLAGS) -o harness-debug
+all:
+	@echo please use GNU make, thanks!
diff --git a/unicorn_mode/samples/persistent/GNUmakefile b/unicorn_mode/samples/persistent/GNUmakefile
new file mode 100644
index 00000000..fe100490
--- /dev/null
+++ b/unicorn_mode/samples/persistent/GNUmakefile
@@ -0,0 +1,42 @@
+# UnicornAFL Usage
+# Original Unicorn Example Makefile by Nguyen Anh Quynh <aquynh@gmail.com>, 2015
+# Adapted for AFL++ by domenukk <domenukk@gmail.com>, 2020
+
+UNAME_S := $(shell uname -s)
+
+LIBDIR = ../../unicornafl
+BIN_EXT =
+AR_EXT = a
+
+# Verbose output?
+V ?= 0
+
+CFLAGS += -Wall -Werror -I../../unicornafl/include
+
+LDFLAGS += -L$(LIBDIR) -lpthread -lm
+ifeq ($(UNAME_S), Linux)
+LDFLAGS += -lrt
+endif
+
+ifneq ($(CROSS),)
+CC = $(CROSS)gcc
+endif
+
+.PHONY: all clean
+
+all: harness
+
+clean:		
+	rm -rf *.o harness harness-debug
+
+harness.o: harness.c ../../unicornafl/include/unicorn/*.h
+	${CC} ${CFLAGS} -O3 -c $<
+
+harness-debug.o: harness.c ../../unicornafl/include/unicorn/*.h
+	${CC} ${CFLAGS} -g -c $< -o $@
+
+harness: harness.o
+	${CC} -L${LIBDIR} $< ../../unicornafl/libunicornafl.a $(LDFLAGS) -o $@
+
+debug: harness-debug.o
+	${CC} -L${LIBDIR} $< ../../unicornafl/libunicornafl.a $(LDFLAGS) -o harness-debug
diff --git a/unicorn_mode/samples/persistent/Makefile b/unicorn_mode/samples/persistent/Makefile
index fe100490..0b306dde 100644
--- a/unicorn_mode/samples/persistent/Makefile
+++ b/unicorn_mode/samples/persistent/Makefile
@@ -1,42 +1,2 @@
-# UnicornAFL Usage
-# Original Unicorn Example Makefile by Nguyen Anh Quynh <aquynh@gmail.com>, 2015
-# Adapted for AFL++ by domenukk <domenukk@gmail.com>, 2020
-
-UNAME_S := $(shell uname -s)
-
-LIBDIR = ../../unicornafl
-BIN_EXT =
-AR_EXT = a
-
-# Verbose output?
-V ?= 0
-
-CFLAGS += -Wall -Werror -I../../unicornafl/include
-
-LDFLAGS += -L$(LIBDIR) -lpthread -lm
-ifeq ($(UNAME_S), Linux)
-LDFLAGS += -lrt
-endif
-
-ifneq ($(CROSS),)
-CC = $(CROSS)gcc
-endif
-
-.PHONY: all clean
-
-all: harness
-
-clean:		
-	rm -rf *.o harness harness-debug
-
-harness.o: harness.c ../../unicornafl/include/unicorn/*.h
-	${CC} ${CFLAGS} -O3 -c $<
-
-harness-debug.o: harness.c ../../unicornafl/include/unicorn/*.h
-	${CC} ${CFLAGS} -g -c $< -o $@
-
-harness: harness.o
-	${CC} -L${LIBDIR} $< ../../unicornafl/libunicornafl.a $(LDFLAGS) -o $@
-
-debug: harness-debug.o
-	${CC} -L${LIBDIR} $< ../../unicornafl/libunicornafl.a $(LDFLAGS) -o harness-debug
+all:
+	@echo please use GNU make, thanks!