about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml2
-rw-r--r--Makefile33
-rw-r--r--README.md86
-rw-r--r--TODO.md6
-rwxr-xr-xafl-cmin4
-rwxr-xr-xafl-plot2
-rwxr-xr-xafl-whatsup33
-rw-r--r--docs/Changelog.md18
-rw-r--r--docs/PATCHES.md1
-rw-r--r--docs/env_variables.md34
-rw-r--r--docs/ideas.md2
-rw-r--r--docs/notes_for_asan.md4
-rw-r--r--docs/power_schedules.md1
-rw-r--r--docs/status_screen.md52
-rw-r--r--examples/custom_mutators/Makefile2
-rw-r--r--examples/custom_mutators/README.md2
-rw-r--r--examples/custom_mutators/custom_mutator_helpers.h268
-rw-r--r--examples/custom_mutators/example.c83
-rw-r--r--gcc_plugin/Makefile6
-rw-r--r--include/afl-as.h4
-rw-r--r--include/afl-fuzz.h111
-rw-r--r--[-rwxr-xr-x]include/android-ashmem.h0
-rw-r--r--include/common.h324
-rw-r--r--include/debug.h4
-rw-r--r--include/forkserver.h3
-rw-r--r--llvm_mode/Makefile33
-rw-r--r--llvm_mode/README.ngram.md20
-rw-r--r--llvm_mode/afl-clang-fast.c60
-rw-r--r--llvm_mode/afl-llvm-pass.so.cc134
-rw-r--r--llvm_mode/afl-llvm-rt.o.c13
-rw-r--r--llvm_mode/llvm-ngram-coverage.h18
-rwxr-xr-xqemu_mode/build_qemu_support.sh28
-rw-r--r--qemu_mode/patches/afl-qemu-tcg-runtime-inl.h4
-rw-r--r--src/afl-analyze.c14
-rw-r--r--src/afl-common.c8
-rw-r--r--src/afl-forkserver.c98
-rw-r--r--src/afl-fuzz-bitmap.c42
-rw-r--r--src/afl-fuzz-cmplog.c235
-rw-r--r--src/afl-fuzz-extras.c23
-rw-r--r--src/afl-fuzz-globals.c30
-rw-r--r--src/afl-fuzz-init.c33
-rw-r--r--src/afl-fuzz-misc.c186
-rw-r--r--src/afl-fuzz-mutators.c95
-rw-r--r--src/afl-fuzz-one.c324
-rw-r--r--src/afl-fuzz-python.c240
-rw-r--r--src/afl-fuzz-queue.c51
-rw-r--r--src/afl-fuzz-redqueen.c2
-rw-r--r--src/afl-fuzz-run.c52
-rw-r--r--src/afl-fuzz-stats.c303
-rw-r--r--src/afl-fuzz.c25
-rw-r--r--src/afl-gotcpu.c2
-rw-r--r--src/afl-showmap.c12
-rw-r--r--src/afl-tmin.c157
-rwxr-xr-xtest/checkcommit.sh41
-rwxr-xr-xtest/test.sh57
-rwxr-xr-xunicorn_mode/build_unicorn_support.sh18
56 files changed, 2030 insertions, 1413 deletions
diff --git a/.travis.yml b/.travis.yml
index 278f312c..2c8c8bea 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,6 +5,7 @@ sudo: required
 branches:
   only:
     - master
+    - dev
 
 matrix:
   include:
@@ -28,6 +29,7 @@ matrix:
 jobs:
   allow_failures:
     - os: osx
+    - arch: arm64
 
 env:
   - AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 AFL_NO_UI=1 AFL_STOP_MANUALLY=1
diff --git a/Makefile b/Makefile
index c8095b05..9913c603 100644
--- a/Makefile
+++ b/Makefile
@@ -151,6 +151,18 @@ ifdef 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
@@ -165,11 +177,6 @@ ifeq "$(TEST_MMAP)" "1"
 	LDFLAGS+=-Wno-deprecated-declarations
 endif
 
-ifdef ASAN_BUILD
-  CFLAGS+=-fsanitize=address
-	LDFLAGS+=-fsanitize=address
-endif
-
 all:	test_x86 test_shm test_python ready $(PROGS) afl-as test_build all_done
 
 man:    $(MANPAGES) 
@@ -208,6 +215,7 @@ help:
 	@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
@@ -406,7 +414,7 @@ source-only: all radamsa
 	@./$* -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> and Andrea Fioraldi <andreafioraldi@gmail.com>" >> $@
+	@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 >> $@
@@ -419,18 +427,7 @@ install: all $(MANPAGES)
 	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
-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
+	$(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
diff --git a/README.md b/README.md
index ca321f31..5b2995d8 100644
--- a/README.md
+++ b/README.md
@@ -23,19 +23,6 @@
   Note that although afl now has a Google afl repository [https://github.com/Google/afl](https://github.com/Google/afl),
   it is unlikely to receive any noteable enhancements: [https://twitter.com/Dor3s/status/1154737061787660288](https://twitter.com/Dor3s/status/1154737061787660288)
 
-## Branches
-
-  The following branches exist:
-
-  * [master/trunk](https://github.com/AFLplusplus/AFLplusplus/) : stable state of afl++ - it is synced from dev from time to
-    time when we are satisfied with it's stability
-  * [dev](https://github.com/AFLplusplus/AFLplusplus/tree/dev) : development state of afl++ - bleeding edge and you might catch a
-    checkout which does not compile or has a bug. *We only accept PRs in dev!!*
-  * (any other) : experimental branches to work on specific features or testing
-    new functionality or changes
-
-  For releases, please see the [Releases](https://github.com/AFLplusplus/AFLplusplus/releases) tab.
-
 ## The enhancements compared to the original stock afl
 
   Many improvements were made over the official afl release - which did not
@@ -57,9 +44,9 @@
 
   * Custom mutator by a library (instead of Python) by kyakdan
 
-  * unicorn_mode which allows fuzzing of binaries from completely different platforms (integration provided by domenukk)
+  * Unicron mode which allows fuzzing of binaries from completely different platforms (integration provided by domenukk)
 
-  * laf-intel or CompCov support for llvm_mode, qemu_mode and unicorn_mode
+  * LAF-Intel or CompCov support for llvm_mode, qemu_mode and unicorn_mode
 
   * NeverZero patch for afl-gcc, llvm_mode, qemu_mode and unicorn_mode which prevents a wrapping map value to zero, increases coverage
   
@@ -69,27 +56,30 @@
 
   * Radamsa mutator (enable with `-R` to add or `-RR` to run it exclusivly).
 
-  * qbdi_mode: fuzz android native libraries via QBDI framework
+  * QBDI mode to fuzz android native libraries via QBDI framework
 
   * The new CmpLog instrumentation for LLVM and QEMU inspired by [Redqueen](https://www.syssec.ruhr-uni-bochum.de/media/emma/veroeffentlichungen/2018/12/17/NDSS19-Redqueen.pdf)
 
+  * LLVM mode Ngram coverage by Adrian Herrera [https://github.com/adrianherrera/afl-ngram-pass](https://github.com/adrianherrera/afl-ngram-pass)
+
   A more thorough list is available in the PATCHES file.
 
   | Feature/Instrumentation | afl-gcc | llvm_mode | gcc_plugin | qemu_mode        | unicorn_mode |
   | ----------------------- |:-------:|:---------:|:----------:|:----------------:|:------------:|
   | NeverZero               |    x    |     x(1)  |      (2)   |         x        |       x      |
   | Persistent mode         |         |     x     |     x      | x86[_64]/arm[64] |       x      |
-  | laf-intel / CompCov     |         |     x     |            | x86[_64]/arm[64] | x86[_64]/arm |
+  | LAF-Intel / CompCov     |         |     x     |            | x86[_64]/arm[64] | x86[_64]/arm |
   | CmpLog                  |         |     x     |            | x86[_64]/arm[64] |              |
   | Whitelist               |         |     x     |     x      |        (x)(3)    |              |
-  | non-colliding coverage  |         |     x(4)  |            |        (x)(5)    |              |
+  | Non-colliding coverage  |         |     x(4)  |            |        (x)(5)    |              |
   | InsTrim                 |         |     x     |            |                  |              |
+  | Ngram prev_loc coverage |         |     x(6)  |            |                  |              |
 
   neverZero:
 
-  (1) only in LLVM >= 9.0 due to a bug in llvm in previous versions
+  (1) only in LLVM >= 9.0 due to a bug in LLVM in previous versions
 
-  (2) gcc creates non-performant code, hence it is disabled in gcc_plugin
+  (2) GCC creates non-performant code, hence it is disabled in gcc_plugin
 
   (3) partially via AFL_CODE_START/AFL_CODE_END
 
@@ -97,6 +87,8 @@
 
   (5) upcoming, development in branch
 
+  (6) not compatible with LTO and InsTrim modes
+
   So all in all this is the best-of afl that is currently out there :-)
 
   For new versions and additional information, check out:
@@ -108,6 +100,18 @@
   See [docs/QuickStartGuide.md](docs/QuickStartGuide.md) if you don't have time to
   read this file.
 
+## Branches
+
+  The following branches exist:
+
+  * [master/trunk](https://github.com/AFLplusplus/AFLplusplus/) : stable state of afl++ - it is synced from dev from time to
+    time when we are satisfied with it's stability
+  * [dev](https://github.com/AFLplusplus/AFLplusplus/tree/dev) : development state of afl++ - bleeding edge and you might catch a
+    checkout which does not compile or has a bug. *We only accept PRs in dev!!*
+  * (any other) : experimental branches to work on specific features or testing
+    new functionality or changes.
+
+  For releases, please see the [Releases](https://github.com/AFLplusplus/AFLplusplus/releases) tab.
 
 ## Google Summer of Code 2020 (and any other students and enthusiast developers)
 
@@ -125,7 +129,7 @@ We have an idea list in [docs/ideas.md](docs/ideas.md)
 For everyone who wants to contribute (and send pull requests) please read
 [CONTRIBUTING.md](CONTRIBUTING.md) before your submit.
 
-## 0) Building and installing afl++
+## Building and installing afl++
 
 afl++ has many build options.
 The easiest is to build and install everything:
@@ -169,6 +173,7 @@ These build options exist:
 
 * STATIC - compile AFL++ static
 * ASAN_BUILD - compiles with memory sanitizer for debug purposes
+* PROFILING - compile with profiling information (gprof)
 * AFL_NO_X86 - if compiling on non-intel/amd platforms
 * LLVM_CONFIG - if your distro doesn't use the standard name for llvm-config (e.g. Debian)
 
@@ -185,7 +190,7 @@ $ sudo docker build -t aflplusplus .
 ```
 
 
-## 1) Challenges of guided fuzzing
+## Challenges of guided fuzzing
 
 Fuzzing is one of the most powerful and proven strategies for identifying
 security issues in real-world software; it is responsible for the vast
@@ -212,7 +217,7 @@ to suffer from reliability and performance problems in practical uses - and
 currently do not offer a viable alternative to "dumb" fuzzing techniques.
 
 
-## 2) The afl-fuzz approach
+## The afl-fuzz approach
 
 American Fuzzy Lop is a brute-force fuzzer coupled with an exceedingly simple
 but rock-solid instrumentation-guided genetic algorithm. It uses a modified
@@ -251,7 +256,7 @@ The fuzzer is thoroughly tested to deliver out-of-the-box performance far
 superior to blind fuzzing or coverage-only tools.
 
 
-## 3) Instrumenting programs for use with AFL
+## 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.
@@ -307,7 +312,7 @@ PS. ASAN users are advised to review [docs/notes_for_asan.md](docs/notes_for_asa
 file for important caveats.
 
 
-## 4) Instrumenting binary-only apps
+## Instrumenting binary-only apps
 
 When source code is *NOT* available, the fuzzer offers experimental support for
 fast, on-the-fly instrumentation of black-box binaries. This is accomplished
@@ -335,8 +340,7 @@ the speed compared to qemu_mode.
 A more comprehensive description of these and other options can be found in
 [docs/binaryonly_fuzzing.md](docs/binaryonly_fuzzing.md)
 
-
-## 5) Good examples and writeups
+## Good examples and writeups
 
 Here are some good writeups to show how to effectibly use AFL++:
 
@@ -351,7 +355,7 @@ structure is), these two links have you covered:
 
 If you find other good ones, please send them to us :-)
 
-## 6) Power schedules
+## Power schedules
 
 The power schedules were copied from Marcel Böhme's excellent AFLfast
 implementation and expand on the ability to discover new paths and
@@ -365,7 +369,8 @@ The available schedules are:
  - quad
  - lin
  - exploit
- - mmopt
+ - mmopt (experimental)
+ - rare (experimental)
 
 In parallel mode (-M/-S, several instances with shared queue), we suggest to
 run the master using the explore or fast schedule (-p explore) and the slaves
@@ -381,7 +386,7 @@ made the default mode).
 More details can be found in the paper published at the 23rd ACM Conference on
 Computer and Communications Security [CCS'16](https://www.sigsac.org/ccs/CCS2016/accepted-papers/)
 
-## 7) Choosing initial test cases
+## Choosing initial test cases
 
 To operate correctly, the fuzzer requires one or more starting file that
 contains a good example of the input data normally expected by the targeted
@@ -402,7 +407,7 @@ the afl-cmin utility to identify a subset of functionally distinct files that
 exercise different code paths in the target binary.
 
 
-## 8) Fuzzing binaries
+## Fuzzing binaries
 
 The fuzzing process itself is carried out by the afl-fuzz utility. This program
 requires a read-only directory with initial test cases, a separate place to
@@ -439,7 +444,7 @@ steps, which can take several days, but tend to produce neat test cases. If you
 want quick & dirty results right away - akin to zzuf and other traditional
 fuzzers - add the -d option to the command line.
 
-## 9) Interpreting output
+## Interpreting output
 
 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
@@ -499,7 +504,7 @@ If you have gnuplot installed, you can also generate some pretty graphs for any
 active fuzzing task using afl-plot. For an example of how this looks like,
 see [http://lcamtuf.coredump.cx/afl/plot/](http://lcamtuf.coredump.cx/afl/plot/).
 
-## 10) Parallelized fuzzing
+## Parallelized fuzzing
 
 Every instance of afl-fuzz takes up roughly one core. This means that on
 multi-core systems, parallelization is necessary to fully utilize the hardware.
@@ -510,7 +515,7 @@ The parallel fuzzing mode also offers a simple way for interfacing AFL to other
 fuzzers, to symbolic or concolic execution engines, and so forth; again, see the
 last section of [docs/parallel_fuzzing.md](docs/parallel_fuzzing.md) for tips.
 
-## 12) Fuzzer dictionaries
+## Fuzzer dictionaries
 
 By default, afl-fuzz mutation engine is optimized for compact data formats -
 say, images, multimedia, compressed data, regular expression syntax, or shell
@@ -545,7 +550,7 @@ 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
 utility with AFL. For that, see [libtokencap/README.md](libtokencap/README.tokencap.md).
 
-## 13) Crash triage
+## Crash triage
 
 The coverage-based grouping of crashes usually produces a small data set that
 can be quickly triaged manually or with a very simple GDB or Valgrind script.
@@ -592,8 +597,7 @@ be critical, and which are not; while not bulletproof, it can often offer quick
 insights into complex file formats. More info about its operation can be found
 near the end of [docs/technical_details.md](docs/technical_details.md).
 
-
-## 14) Going beyond crashes
+## Going beyond crashes
 
 Fuzzing is a wonderful and underutilized technique for discovering non-crashing
 design and implementation errors, too. Quite a few interesting bugs have been
@@ -616,7 +620,7 @@ if you are the maintainer of a particular package, you can make this code
 conditional with `#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION` (a flag also
 shared with libfuzzer) or `#ifdef __AFL_COMPILER` (this one is just for AFL).
 
-## 15) Common-sense risks
+## 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:
@@ -645,7 +649,7 @@ tasks, fuzzing may put strain on your hardware and on the OS. In particular:
     $ iostat -d 3 -x -k [...optional disk ID...]
 ```
 
-## 16) Known limitations & areas for improvement
+## Known limitations & areas for improvement
 
 Here are some of the most important caveats for AFL:
 
@@ -685,7 +689,7 @@ Here are some of the most important caveats for AFL:
 
 Beyond this, see INSTALL for platform-specific tips.
 
-## 17) Special thanks
+## Special thanks
 
 Many of the improvements to the original afl and afl++ wouldn't be possible
 without feedback, bug reports, or patches from:
@@ -739,7 +743,7 @@ without feedback, bug reports, or patches from:
 Thank you!
 (For people sending pull requests - please add yourself to this list :-)
 
-## 18) Contact
+## Contact
 
 Questions? Concerns? Bug reports? The contributors can be reached via
 [https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
diff --git a/TODO.md b/TODO.md
index ffd6b5ad..1a34fba4 100644
--- a/TODO.md
+++ b/TODO.md
@@ -4,7 +4,6 @@
 
  - get "no global vars" working
 
-
 ## Further down the road
 
 afl-fuzz:
@@ -13,6 +12,11 @@ afl-fuzz:
  - ascii_only mode for mutation output
  - setting min_len/max_len/start_offset/end_offset limits for mutation output
 
+llvm_mode:
+ - added context sensitive branch coverage
+ - add CT cov and ngram cov to LTO and InsTrim
+ - better whitelist solution for LTO
+
 gcc_plugin:
  - laf-intel
  - better instrumentation (seems to be better with gcc-9+)
diff --git a/afl-cmin b/afl-cmin
index d96a103f..d38e7a97 100755
--- a/afl-cmin
+++ b/afl-cmin
@@ -264,7 +264,7 @@ BEGIN {
 
   if (target_bin && !exists_and_is_executable(target_bin)) {
 
-    "type "target_bin" | awk '{print $NF}' 2>/dev/null" | getline tnew
+    "command -v "target_bin" 2>/dev/null" | getline tnew
     if (!tnew || !exists_and_is_executable(tnew)) {
       print "[-] Error: binary '"target_bin"' not found or not executable." > "/dev/stderr"
       exit 1
@@ -313,7 +313,7 @@ BEGIN {
     if (0 == system("test -f afl-cmin")) {
       showmap = "./afl-showmap"
     } else {
-      "type afl-showmap | awk '{print $NF}' 2>/dev/null" | getline showmap
+      "command -v afl-showmap 2>/dev/null" | getline showmap
     }
   } else {
     showmap = ENVIRON["AFL_PATH"] "/afl-showmap"
diff --git a/afl-plot b/afl-plot
index 0f0154a6..6ad3f790 100755
--- a/afl-plot
+++ b/afl-plot
@@ -68,7 +68,7 @@ BANNER="`cat "$1/fuzzer_stats" | grep '^afl_banner ' | cut -d: -f2- | cut -b2-`"
 
 test "$BANNER" = "" && BANNER="(none)"
 
-GNUPLOT=`which gnuplot 2>/dev/null`
+GNUPLOT=`command -v gnuplot 2>/dev/null`
 
 if [ "$GNUPLOT" = "" ]; then
 
diff --git a/afl-whatsup b/afl-whatsup
index 5983ca82..01edb210 100755
--- a/afl-whatsup
+++ b/afl-whatsup
@@ -61,8 +61,12 @@ if [ -d queue ]; then
 
 fi
 
-RED=`tput setaf 1 1 1`
+RED=`tput setaf 9 1 1`
+GREEN=`tput setaf 2 1 1`
+BLUE=`tput setaf 4 1 1`
+YELLOW=`tput setaf 11 1 1`
 NC=`tput sgr0`
+RESET="$NC"
 
 CUR_TIME=`date +%s`
 
@@ -116,6 +120,9 @@ fmt_duration()
   fi
 }
 
+FIRST=true
+TOTAL_WCOP=
+
 for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do
 
   sed 's/^command_line.*$/_skip:1/;s/[ ]*:[ ]*/="/;s/$/"/' "$i" >"$TMP"
@@ -125,6 +132,12 @@ for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do
   RUN_DAYS=$((RUN_UNIX / 60 / 60 / 24))
   RUN_HRS=$(((RUN_UNIX / 60 / 60) % 24))
 
+  test -n "$cycles_wo_finds" && {
+    test -z "$FIRST" && TOTAL_WCOP="${TOTAL_WCOP}/"
+    TOTAL_WCOP="${TOTAL_WCOP}${cycles_wo_finds}"
+    FIRST=
+  }
+
   if [ "$SUMMARY_ONLY" = "" ]; then
 
     echo ">>> $afl_banner ($RUN_DAYS days, $RUN_HRS hrs) fuzzer PID: $fuzzer_pid <<<"
@@ -173,10 +186,17 @@ for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do
     fmt_duration $last_path && FMT_PATH=$DUR_STRING
     fmt_duration $last_crash && FMT_CRASH=$DUR_STRING
     fmt_duration $last_hang && FMT_HANG=$DUR_STRING
-
-    echo "  last_path  : $FMT_PATH"
-    echo "  last_crash : $FMT_CRASH"
-    echo "  last_hang  : $FMT_HANG"
+    FMT_CWOP="not available"
+    test -n "$cycles_wo_finds" && {
+      test "$cycles_wo_finds" = 0 && FMT_CWOP="$cycles_wo_finds"
+      test "$cycles_wo_finds" -gt 10 && FMT_CWOP="${YELLOW}$cycles_wo_finds${NC}"
+      test "$cycles_wo_finds" -gt 50 && FMT_CWOP="${RED}$cycles_wo_finds${NC}"
+    }
+
+    echo "  last_path       : $FMT_PATH"
+    echo "  last_crash      : $FMT_CRASH"
+    echo "  last_hang       : $FMT_HANG"
+    echo "  cycles_wo_finds : $FMT_CWOP"
 
     CPU_USAGE=$(ps aux | grep $fuzzer_pid | grep -v grep | awk '{print $3}')
     MEM_USAGE=$(ps aux | grep $fuzzer_pid | grep -v grep | awk '{print $4}')
@@ -215,6 +235,8 @@ rm -f "$TMP"
 TOTAL_DAYS=$((TOTAL_TIME / 60 / 60 / 24))
 TOTAL_HRS=$(((TOTAL_TIME / 60 / 60) % 24))
 
+test -z "$TOTAL_WCOP" && TOTAL_WCOP="not available"
+
 test "$TOTAL_TIME" = "0" && TOTAL_TIME=1
 
 echo "Summary stats"
@@ -239,6 +261,7 @@ if [ "$ALIVE_CNT" -gt "1" ]; then
 fi
 
 echo "       Crashes found : $TOTAL_CRASHES locally unique"
+echo "Cycles without finds : $TOTAL_WCOP"
 echo
 
 exit 0
diff --git a/docs/Changelog.md b/docs/Changelog.md
index e1f3cd7e..6af269ce 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -11,21 +11,31 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
 
 ### Version ++2.62d (develop):
 
+  ! the repository was moved from vanhauser-thc to AFLplusplus. It is now
+    an own organisation :)
+  ! 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 
       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)
   - afl-fuzz:
     - python mutator modules and custom mutator modules now use the same
       interface and hence the API changed
     - AFL_AUTORESUME will resume execution without the need to specify `-i -`
-    - added experimental power schedule -p mmopt that ignores the runtime of
-      queue entries and gives higher weighting to the last 5 queue entries
-      it is currently experimental and subject to change but preliminary
-      results are good
+    - added experimental power schedules (-p):
+      - mmopt: ignores runtime of queue entries, gives higher weighting to
+               the last 5 queue entries
+      - rare: puts focus on queue entries that hits rare branches, also ignores
+              runtime
   - 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 
       imported fix by author
diff --git a/docs/PATCHES.md b/docs/PATCHES.md
index 1dfb6622..a6783523 100644
--- a/docs/PATCHES.md
+++ b/docs/PATCHES.md
@@ -20,6 +20,7 @@ afl-qemu-speed.diff			by abiondo on github
 afl-qemu-optimize-map.diff		by mh(at)mh-sec(dot)de
 ```
 
++ llvm_mode ngram prev_loc coverage (github.com/adrianherrera/afl-ngram-pass)
 + Custom mutator (native library) (by kyakdan)
 + unicorn_mode (modernized and updated by domenukk)
 + instrim (https://github.com/csienslab/instrim) was integrated
diff --git a/docs/env_variables.md b/docs/env_variables.md
index 8c7510cd..98f27bdf 100644
--- a/docs/env_variables.md
+++ b/docs/env_variables.md
@@ -93,23 +93,26 @@ Then there are a few specific features that are only available in llvm_mode:
 
 ### LTO
 
-This is a different kind way of instrumentation: first it compiles all
-code in LTO (link time optimization) and then performs an edge inserting
-instrumentation which is 100% collision free (collisions are a big issue
-in afl and afl-like instrumentations). This is performed by using
-afl-clang-lto/afl-clang-lto++ instead of afl-clang-fast, but is only
-built if LLVM 9 or newer is used.
-
-None of these options are necessary to be used and are rather for manual
-use (which only ever the author of this LTO implementation will use ;-)
-These are used if several seperated instrumentation are performed which
-are then later combined.
+    This is a different kind way of instrumentation: first it compiles all
+    code in LTO (link time optimization) and then performs an edge inserting
+    instrumentation which is 100% collision free (collisions are a big issue
+    in afl and afl-like instrumentations). This is performed by using
+    afl-clang-lto/afl-clang-lto++ instead of afl-clang-fast, but is only
+    built if LLVM 9 or newer is used.
+
+    None of these options are necessary to be used and are rather for manual
+    use (which only ever the author of this LTO implementation will use ;-)
+    These are used if several seperated instrumentation are performed which
+    are then later combined.
 
    - AFL_LLVM_LTO_STARTID sets the starting location ID for the instrumentation.
      This defaults to 1
    - AFL_LLVM_LTO_DONTWRITEID prevents that the highest location ID written
      into the instrumentation is set in a global variable
 
+    Instrim, LTO and ngram modes can not be used together.
+    See llvm_mode/README.LTO.md for more information.
+
 ### LAF-INTEL
 
     This great feature will split compares to series of single byte comparisons
@@ -149,8 +152,17 @@ are then later combined.
       functions with a single basic block. This is useful for most C and
       some C++ targets.
 
+    Instrim, LTO and ngram modes can not be used together.
     See llvm_mode/README.instrim.md
 
+### NGRAM
+
+    - Setting AFL_LLVM_NGRAM_SIZE activates ngram prev_loc coverage, good
+      values are 2, 4 or 8.
+
+    Instrim, LTO and ngram modes can not be used together.
+    See llvm_mode/README.ngram.md
+
 ### NOT_ZERO
 
     - Setting AFL_LLVM_NOT_ZERO=1 during compilation will use counters
diff --git a/docs/ideas.md b/docs/ideas.md
index 44dcccb2..686c262d 100644
--- a/docs/ideas.md
+++ b/docs/ideas.md
@@ -33,7 +33,7 @@ This is an excellent mutations scheduler based on Particle Swarm
 Optimization but the current implementation schedule only the mutations
 that were present on AFL.
 
-AFL++ added a lost of optional mutators like the Input-2-State one based
+AFL++ added a lot of optional mutators like the Input-2-State one based
 on Redqueen, the Radamsa mutator, the Custom mutator (the user can define
 its own mutator) and the work is to generalize MOpt for all the current
 and future mutators.
diff --git a/docs/notes_for_asan.md b/docs/notes_for_asan.md
index feac49f9..b65873be 100644
--- a/docs/notes_for_asan.md
+++ b/docs/notes_for_asan.md
@@ -28,6 +28,10 @@ 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
+compiled in.
+
 There is also the option of generating a corpus using a non-ASAN binary, and
 then feeding it to an ASAN-instrumented one to check for bugs. This is faster,
 and can give you somewhat comparable results. You can also try using
diff --git a/docs/power_schedules.md b/docs/power_schedules.md
index cdada0f6..c69c64d2 100644
--- a/docs/power_schedules.md
+++ b/docs/power_schedules.md
@@ -20,6 +20,7 @@ We find that AFL's exploitation-based constant schedule assigns **too much energ
 | `-p lin` | ![LIN](http://latex.codecogs.com/gif.latex?p%28i%29%20%3D%20%5Cmin%5Cleft%28%5Cfrac%7B%5Calpha%28i%29%7D%7B%5Cbeta%7D%5Ccdot%5Cfrac%7Bs%28i%29%7D%7Bf%28i%29%7D%2CM%5Cright%29) |
 | `-p exploit` (AFL) | ![LIN](http://latex.codecogs.com/gif.latex?p%28i%29%20%3D%20%5Calpha%28i%29) |
 | `-p mmopt` | Experimental: `explore` with no weighting to runtime and increased weighting on the last 5 queue entries |
+| `-p rare` | Experimental: `rare` puts focus on queue entries that hit rare edges |
 where *α(i)* is the performance score that AFL uses to compute for the seed input *i*, *β(i)>1* is a constant, *s(i)* is the number of times that seed *i* has been chosen from the queue, *f(i)* is the number of generated inputs that exercise the same path as seed *i*, and *μ* is the average number of generated inputs exercising a path.
   
 More details can be found in the paper that was accepted at the [23rd ACM Conference on Computer and Communications Security (CCS'16)](https://www.sigsac.org/ccs/CCS2016/accepted-papers/).
diff --git a/docs/status_screen.md b/docs/status_screen.md
index 0bc636c4..8b3d5bda 100644
--- a/docs/status_screen.md
+++ b/docs/status_screen.md
@@ -372,26 +372,38 @@ For unattended operation, some of the key status screen information can be also
 found in a machine-readable format in the fuzzer_stats file in the output
 directory. This includes:
 
-  - `start_time`     - unix time indicating the start time of afl-fuzz
-  - `last_update`    - unix time corresponding to the last update of this file
-  - `fuzzer_pid`     - PID of the fuzzer process
-  - `cycles_done`    - queue cycles completed so far
-  - `execs_done`     - number of execve() calls attempted
-  - `execs_per_sec`  - overall number of execs per second
-  - `paths_total`    - total number of entries in the queue
-  - `paths_found`    - number of entries discovered through local fuzzing
-  - `paths_imported` - number of entries imported from other instances
-  - `max_depth`      - number of levels in the generated data set
-  - `cur_path`       - currently processed entry number
-  - `pending_favs`   - number of favored entries still waiting to be fuzzed
-  - `pending_total`  - number of all entries waiting to be fuzzed
-  - `stability      - percentage of bitmap bytes that behave consistently
-  - `variable_paths` - number of test cases showing variable behavior
-  - `unique_crashes` - number of unique crashes recorded
-  - `unique_hangs`   - number of unique hangs encountered
-  - `command_line`   - full command line used for the fuzzing session
-  - `slowest_exec_ms`- real time of the slowest execution in seconds
-  - `peak_rss_mb`    - max rss usage reached during fuzzing in MB
+  - `start_time`        - unix time indicating the start time of afl-fuzz
+  - `last_update`       - unix time corresponding to the last update of this file
+  - `run_time`          - run time in seconds to the last update of this file
+  - `fuzzer_pid`        - PID of the fuzzer process
+  - `cycles_done`       - queue cycles completed so far
+  - `cycles_wo_finds`   - number of cycles without any new paths found
+  - `execs_done`        - number of execve() calls attempted
+  - `execs_per_sec`     - overall number of execs per second
+  - `paths_total`       - total number of entries in the queue
+  - `paths_favored`     - number of queue entries that are favored
+  - `paths_found`       - number of entries discovered through local fuzzing
+  - `paths_imported`    - number of entries imported from other instances
+  - `max_depth`         - number of levels in the generated data set
+  - `cur_path`          - currently processed entry number
+  - `pending_favs`      - number of favored entries still waiting to be fuzzed
+  - `pending_total`     - number of all entries waiting to be fuzzed
+  - `variable_paths`    - number of test cases showing variable behavior
+  - `stability`         - percentage of bitmap bytes that behave consistently
+  - `bitmap_cvg`        - percentage of edge coverage found in the map so far
+  - `unique_crashes`    - number of unique crashes recorded
+  - `unique_hangs`      - number of unique hangs encountered
+  - `last_path`         - seconds since the last path was found
+  - `last_crash`        - seconds since the last crash was found
+  - `last_hang`         - seconds since the last hang was found
+  - `execs_since_crash` - execs since the last crash was found
+  - `exec_timeout`      - the -t command line value
+  - `slowest_exec_ms`   - real time of the slowest execution in ms
+  - `peak_rss_mb`       - max rss usage reached during fuzzing in MB
+  - `afl_banner`        - banner text (e.g. the target name)
+  - `afl_version`       - the version of afl used
+  - `target_mode`       - default, persistent, qemu, unicorn, dumb
+  - `command_line`      - full command line used for the fuzzing session
 
 Most of these map directly to the UI elements discussed earlier on.
 
diff --git a/examples/custom_mutators/Makefile b/examples/custom_mutators/Makefile
new file mode 100644
index 00000000..a83e87fe
--- /dev/null
+++ b/examples/custom_mutators/Makefile
@@ -0,0 +1,2 @@
+all:
+	$(CC) $(CFLAGS) -fPIC -shared -g -I ../../include example.c -o libexamplemutator.so
diff --git a/examples/custom_mutators/README.md b/examples/custom_mutators/README.md
index ce49436e..93f824cd 100644
--- a/examples/custom_mutators/README.md
+++ b/examples/custom_mutators/README.md
@@ -7,7 +7,7 @@ Note that if you compile with python3.7 you must use python3 scripts, and if
 you use pyton2.7 to compile python2 scripts!
 
 example.c - this is a simple example written in C and should be compiled to a
-          shared library
+          shared library. Use make to compile it and produce libexamplemutator.so
 
 example.py - this is the template you can use, the functions are there but they
            are empty
diff --git a/examples/custom_mutators/custom_mutator_helpers.h b/examples/custom_mutators/custom_mutator_helpers.h
new file mode 100644
index 00000000..844ccf94
--- /dev/null
+++ b/examples/custom_mutators/custom_mutator_helpers.h
@@ -0,0 +1,268 @@
+#ifndef CUSTOM_MUTATOR_HELPERS
+#define CUSTOM_MUTATOR_HELPERS
+
+#include "config.h"
+#include "types.h"
+#include <stdlib.h>
+
+#define RAND_BELOW(limit) (rand() % (limit))
+
+typedef struct{} afl_t;
+
+static void surgical_havoc_mutate(u8 *out_buf, s32 begin, s32 end) {
+
+  static s8  interesting_8[]  = {INTERESTING_8};
+  static s16 interesting_16[] = {INTERESTING_8, INTERESTING_16};
+  static s32 interesting_32[] = {INTERESTING_8, INTERESTING_16, INTERESTING_32};
+
+  switch (RAND_BELOW(12)) {
+
+    case 0: {
+
+      /* Flip a single bit somewhere. Spooky! */
+
+      s32 bit_idx = ((RAND_BELOW(end - begin) + begin) << 3) + RAND_BELOW(8);
+
+      out_buf[bit_idx >> 3] ^= 128 >> (bit_idx & 7);
+
+      break;
+
+    }
+
+    case 1: {
+
+      /* Set byte to interesting value. */
+
+      u8 val = interesting_8[RAND_BELOW(sizeof(interesting_8))];
+      out_buf[(RAND_BELOW(end - begin) + begin)] = val;
+
+      break;
+
+    }
+
+    case 2: {
+
+      /* Set word to interesting value, randomly choosing endian. */
+
+      if (end - begin < 2) break;
+
+      s32 byte_idx = (RAND_BELOW(end - begin) + begin);
+
+      if (byte_idx >= end - 1) break;
+
+      switch (RAND_BELOW(2)) {
+
+        case 0:
+          *(u16 *)(out_buf + byte_idx) =
+              interesting_16[RAND_BELOW(sizeof(interesting_16) >> 1)];
+          break;
+        case 1:
+          *(u16 *)(out_buf + byte_idx) =
+              SWAP16(interesting_16[RAND_BELOW(sizeof(interesting_16) >> 1)]);
+          break;
+
+      }
+
+      break;
+
+    }
+
+    case 3: {
+
+      /* Set dword to interesting value, randomly choosing endian. */
+
+      if (end - begin < 4) break;
+
+      s32 byte_idx = (RAND_BELOW(end - begin) + begin);
+
+      if (byte_idx >= end - 3) break;
+
+      switch (RAND_BELOW(2)) {
+
+        case 0:
+          *(u32 *)(out_buf + byte_idx) =
+              interesting_32[RAND_BELOW(sizeof(interesting_32) >> 2)];
+          break;
+        case 1:
+          *(u32 *)(out_buf + byte_idx) =
+              SWAP32(interesting_32[RAND_BELOW(sizeof(interesting_32) >> 2)]);
+          break;
+
+      }
+
+      break;
+
+    }
+
+    case 4: {
+
+      /* Set qword to interesting value, randomly choosing endian. */
+
+      if (end - begin < 8) break;
+
+      s32 byte_idx = (RAND_BELOW(end - begin) + begin);
+
+      if (byte_idx >= end - 7) break;
+
+      switch (RAND_BELOW(2)) {
+
+        case 0:
+          *(u64 *)(out_buf + byte_idx) =
+              (s64)interesting_32[RAND_BELOW(sizeof(interesting_32) >> 2)];
+          break;
+        case 1:
+          *(u64 *)(out_buf + byte_idx) =
+              SWAP64((s64)interesting_32[RAND_BELOW(sizeof(interesting_32) >> 2)]);
+          break;
+
+      }
+
+      break;
+
+    }
+
+    case 5: {
+
+      /* Randomly subtract from byte. */
+
+      out_buf[(RAND_BELOW(end - begin) + begin)] -= 1 + RAND_BELOW(ARITH_MAX);
+
+      break;
+
+    }
+
+    case 6: {
+
+      /* Randomly add to byte. */
+
+      out_buf[(RAND_BELOW(end - begin) + begin)] += 1 + RAND_BELOW(ARITH_MAX);
+
+      break;
+
+    }
+
+    case 7: {
+
+      /* Randomly subtract from word, random endian. */
+
+      if (end - begin < 2) break;
+
+      s32 byte_idx = (RAND_BELOW(end - begin) + begin);
+
+      if (byte_idx >= end - 1) break;
+
+      if (RAND_BELOW(2)) {
+
+        *(u16 *)(out_buf + byte_idx) -= 1 + RAND_BELOW(ARITH_MAX);
+
+      } else {
+
+        u16 num = 1 + RAND_BELOW(ARITH_MAX);
+
+        *(u16 *)(out_buf + byte_idx) =
+            SWAP16(SWAP16(*(u16 *)(out_buf + byte_idx)) - num);
+
+      }
+
+      break;
+
+    }
+
+    case 8: {
+
+      /* Randomly add to word, random endian. */
+
+      if (end - begin < 2) break;
+
+      s32 byte_idx = (RAND_BELOW(end - begin) + begin);
+
+      if (byte_idx >= end - 1) break;
+
+      if (RAND_BELOW(2)) {
+
+        *(u16 *)(out_buf + byte_idx) += 1 + RAND_BELOW(ARITH_MAX);
+
+      } else {
+
+        u16 num = 1 + RAND_BELOW(ARITH_MAX);
+
+        *(u16 *)(out_buf + byte_idx) =
+            SWAP16(SWAP16(*(u16 *)(out_buf + byte_idx)) + num);
+
+      }
+
+      break;
+
+    }
+
+    case 9: {
+
+      /* Randomly subtract from dword, random endian. */
+
+      if (end - begin < 4) break;
+
+      s32 byte_idx = (RAND_BELOW(end - begin) + begin);
+
+      if (byte_idx >= end - 3) break;
+
+      if (RAND_BELOW(2)) {
+
+        *(u32 *)(out_buf + byte_idx) -= 1 + RAND_BELOW(ARITH_MAX);
+
+      } else {
+
+        u32 num = 1 + RAND_BELOW(ARITH_MAX);
+
+        *(u32 *)(out_buf + byte_idx) =
+            SWAP32(SWAP32(*(u32 *)(out_buf + byte_idx)) - num);
+
+      }
+
+      break;
+
+    }
+
+    case 10: {
+
+      /* Randomly add to dword, random endian. */
+
+      if (end - begin < 4) break;
+
+      s32 byte_idx = (RAND_BELOW(end - begin) + begin);
+
+      if (byte_idx >= end - 3) break;
+
+      if (RAND_BELOW(2)) {
+
+        *(u32 *)(out_buf + byte_idx) += 1 + RAND_BELOW(ARITH_MAX);
+
+      } else {
+
+        u32 num = 1 + RAND_BELOW(ARITH_MAX);
+
+        *(u32 *)(out_buf + byte_idx) =
+            SWAP32(SWAP32(*(u32 *)(out_buf + byte_idx)) + num);
+
+      }
+
+      break;
+
+    }
+
+    case 11: {
+
+      /* Just set a random byte to a random value. Because,
+         why not. We use XOR with 1-255 to eliminate the
+         possibility of a no-op. */
+
+      out_buf[(RAND_BELOW(end - begin) + begin)] ^= 1 + RAND_BELOW(255);
+
+      break;
+
+    }
+
+  }
+
+}
+
+#endif
diff --git a/examples/custom_mutators/example.c b/examples/custom_mutators/example.c
index 127f971e..560a5919 100644
--- a/examples/custom_mutators/example.c
+++ b/examples/custom_mutators/example.c
@@ -3,12 +3,18 @@
   Written by Khaled Yakdan <yakdan@code-intelligence.de>
              Andrea Fioraldi <andreafioraldi@gmail.com>
              Shengtuo Hu <h1994st@gmail.com>
+             Dominik Maier <mail@dmnk.co>
 */
 
+// You need to use -I /path/to/AFLplusplus/include
+#include "custom_mutator_helpers.h"
+
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
 
+#define DATA_SIZE (100)
+
 static const char *commands[] = {
 
     "GET",
@@ -17,11 +23,35 @@ static const char *commands[] = {
 
 };
 
-static size_t data_size = 100;
 
-void afl_custom_init(unsigned int seed) {
+typedef struct my_mutator {
+
+  afl_t *afl;
+  // any additional data here!
+
+} 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.
+ * @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.
+ */
+my_mutator_t *afl_custom_init(afl_t *afl, unsigned int seed) {
+
+  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;
 
-  srand(seed);
+  return data;
 
 }
 
@@ -30,6 +60,7 @@ void afl_custom_init(unsigned int seed) {
  *
  * (Optional for now. Required in the future)
  *
+ * @param[in] data pointer returned in afl_custom_init for this fuzz case
  * @param[in] buf Pointer to input data to be mutated
  * @param[in] buf_size Size of input data
  * @param[in] add_buf Buffer containing the additional test case
@@ -38,13 +69,14 @@ void afl_custom_init(unsigned int seed) {
  *     produce data larger than max_size.
  * @return Size of the mutated output.
  */
-size_t afl_custom_fuzz(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,
+                       uint8_t *add_buf,
                        size_t add_buf_size,  // add_buf can be NULL
                        size_t max_size) {
 
   // Make sure that the packet size does not exceed the maximum size expected by
   // the fuzzer
-  size_t mutated_size = data_size <= max_size ? data_size : max_size;
+  size_t mutated_size = DATA_SIZE <= max_size ? DATA_SIZE : max_size;
 
   if (mutated_size > buf_size) *buf = realloc(*buf, mutated_size);
 
@@ -54,9 +86,11 @@ size_t afl_custom_fuzz(uint8_t **buf, size_t buf_size, uint8_t *add_buf,
   memcpy(mutated_out, commands[rand() % 3], 3);
 
   // Mutate the payload of the packet
-  for (int i = 3; i < mutated_size; i++) {
+  int i;
+  for (i = 0; i < 8; ++i) {
 
-    mutated_out[i] = (mutated_out[i] + rand() % 10) & 0xff;
+    // Randomly perform one of the (no len modification) havoc mutations
+    surgical_havoc_mutate(mutated_out, 3, mutated_size);
 
   }
 
@@ -71,6 +105,7 @@ size_t afl_custom_fuzz(uint8_t **buf, size_t buf_size, uint8_t *add_buf,
  * (Optional) If this functionality is not needed, simply don't define this
  * function.
  *
+ * @param[in] data pointer returned in afl_custom_init for this fuzz case
  * @param[in] buf Buffer containing the test case to be executed
  * @param[in] buf_size Size of the test case
  * @param[out] out_buf Pointer to the buffer containing the test case after
@@ -78,7 +113,7 @@ size_t afl_custom_fuzz(uint8_t **buf, size_t buf_size, uint8_t *add_buf,
  *     will release the memory after saving the test case.
  * @return Size of the output buffer after processing
  */
-size_t afl_custom_pre_save(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) {
 
   size_t out_buf_size;
 
@@ -113,11 +148,12 @@ static int      cur_step;
  *
  * (Optional)
  *
+ * @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
  */
-int afl_custom_init_trim(uint8_t *buf, size_t buf_size) {
+int afl_custom_init_trim(my_mutator_t *data, uint8_t *buf, size_t buf_size) {
 
   // We simply trim once
   trimmming_steps = 1;
@@ -141,12 +177,13 @@ int afl_custom_init_trim(uint8_t *buf, size_t buf_size) {
  *
  * (Optional)
  *
+ * @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
  */
-void afl_custom_trim(uint8_t **out_buf, size_t *out_buf_size) {
+void afl_custom_trim(my_mutator_t *data, uint8_t **out_buf, size_t *out_buf_size) {
 
   *out_buf_size = trim_buf_size - 1;
 
@@ -164,11 +201,12 @@ void afl_custom_trim(uint8_t **out_buf, size_t *out_buf_size) {
  *
  * (Optional)
  *
+ * @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)
  */
-int afl_custom_post_trim(int success) {
+int afl_custom_post_trim(my_mutator_t *data, int success) {
 
   if (success) {
 
@@ -187,6 +225,7 @@ int afl_custom_post_trim(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
  *     output
  * @param[in] buf_size Size of input data
@@ -194,7 +233,7 @@ int afl_custom_post_trim(int success) {
  *     not produce data larger than max_size.
  * @return Size of the mutated output.
  */
-size_t afl_custom_havoc_mutation(uint8_t **buf, size_t buf_size,
+size_t afl_custom_havoc_mutation(my_mutator_t *data, uint8_t **buf, size_t buf_size,
                                  size_t max_size) {
 
   if (buf_size == 0) {
@@ -218,9 +257,10 @@ size_t afl_custom_havoc_mutation(uint8_t **buf, size_t buf_size,
  *
  * (Optional)
  *
+ * @param[in] data pointer returned in afl_custom_init for this fuzz case
  * @return The probability (0-100).
  */
-uint8_t afl_custom_havoc_mutation_probability(void) {
+uint8_t afl_custom_havoc_mutation_probability(my_mutator_t *data) {
 
   return 5;  // 5 %
 
@@ -231,11 +271,12 @@ uint8_t afl_custom_havoc_mutation_probability(void) {
  *
  * (Optional)
  *
+ * @param[in] data pointer returned in afl_custom_init for this fuzz case
  * @param filename File name of the test case in the queue entry
  * @return Return True(1) if the fuzzer will fuzz the queue entry, and
  *     False(0) otherwise.
  */
-uint8_t afl_custom_queue_get(const uint8_t *filename) {
+uint8_t afl_custom_queue_get(my_mutator_t *data, const uint8_t *filename) {
 
   return 1;
 
@@ -247,13 +288,25 @@ uint8_t afl_custom_queue_get(const uint8_t *filename) {
  *
  * (Optional)
  *
+ * @param data pointer returned in afl_custom_init for this fuzz case
  * @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(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 */
 
 }
 
+/**
+ * Deinitialize everything
+ *
+ * @param data The data ptr from afl_custom_init
+ */
+void afl_custom_deinit(my_mutator_t *data) {
+
+  free(data);
+
+}
+
diff --git a/gcc_plugin/Makefile b/gcc_plugin/Makefile
index 17962401..506d690d 100644
--- a/gcc_plugin/Makefile
+++ b/gcc_plugin/Makefile
@@ -44,7 +44,7 @@ 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 `type $(CC) | awk '{print $$NF}'` 2>/dev/null )
+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
@@ -132,7 +132,7 @@ vpath  % ..
 	@../$* -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> and Andrea Fioraldi <andreafioraldi@gmail.com>" >> ../$@
+	@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 >> ../$@
@@ -143,7 +143,7 @@ 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
+	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
diff --git a/include/afl-as.h b/include/afl-as.h
index 7fc00ffe..a2bf1f9c 100644
--- a/include/afl-as.h
+++ b/include/afl-as.h
@@ -152,7 +152,7 @@ static const u8 *trampoline_fmt_64 =
     "/* --- END --- */\n"
     "\n";
 
-static const u8*main_payload_32 = 
+static const u8 *main_payload_32 = 
 
   "\n"
   "/* --- AFL MAIN PAYLOAD (32-BIT) --- */\n"
@@ -409,7 +409,7 @@ static const u8*main_payload_32 =
 #define CALL_L64(str) "call " str "@PLT\n"
 #endif                                                        /* ^__APPLE__ */
 
-static const u8* main_payload_64 = 
+static const u8 *main_payload_64 = 
 
   "\n"
   "/* --- AFL MAIN PAYLOAD (64-BIT) --- */\n"
diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h
index 620f5062..7dddefb0 100644
--- a/include/afl-fuzz.h
+++ b/include/afl-fuzz.h
@@ -109,6 +109,8 @@
 #define CASE_PREFIX "id_"
 #endif                                                    /* ^!SIMPLE_FILES */
 
+#define STAGE_BUF_SIZE (64)  /* usable size for stage name buf in afl_state */
+
 extern s8  interesting_8[INTERESTING_8_LEN];
 extern s16 interesting_16[INTERESTING_8_LEN + INTERESTING_16_LEN];
 extern s32
@@ -231,6 +233,7 @@ enum {
   /* 04 */ QUAD,    /* Quadratic schedule               */
   /* 05 */ EXPLOIT, /* AFL's exploitation-based const.  */
   /* 06 */ MMOPT,   /* Modified MOPT schedule           */
+  /* 07 */ RARE,    /* Rare edges                       */
 
   POWER_SCHEDULES_NUM
 
@@ -278,10 +281,20 @@ enum {
   /* 07 */ PY_FUNC_HAVOC_MUTATION_PROBABILITY,
   /* 08 */ PY_FUNC_QUEUE_GET,
   /* 09 */ PY_FUNC_QUEUE_NEW_ENTRY,
+  /* 10 */ PY_FUNC_DEINIT,
   PY_FUNC_COUNT
 
 };
 
+typedef struct py_mutator {
+
+  PyObject *py_module;
+  PyObject *py_functions[PY_FUNC_COUNT];
+  void *afl_state;
+  void *py_data;
+
+} py_mutator_t;
+
 #endif
 
 typedef struct MOpt_globals {
@@ -479,7 +492,7 @@ typedef struct afl_state {
       *stage_short,                     /* Short stage name                 */
       *syncing_party;                   /* Currently syncing with...        */
 
-  u8 stage_name_buf64[64];              /* A name buf with len 64 if needed */
+  u8 stage_name_buf[STAGE_BUF_SIZE];    /* reused stagename buf with len 64 */
 
   s32 stage_cur, stage_max;             /* Stage progression                */
   s32 splicing_with;                    /* Splicing with which test case?   */
@@ -537,24 +550,36 @@ 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;
+  u32 cmplog_prev_timed_out;
 
   u8 describe_op_buf_256[256]; /* describe_op will use this to return a string
                                   up to 256 */
 
-#ifdef USE_PYTHON
-  /* Python Mutators */
-  PyObject *py_module;
-  PyObject *py_functions[PY_FUNC_COUNT];
-#endif
-
 #ifdef _AFL_DOCUMENT_MUTATIONS
   u8  do_document;
   u32 document_counter;
 #endif
 
+  /* statis file */
+  double last_bitmap_cvg, last_stability, last_eps;
+
+  /* plot file saves from last run */
+  u32 plot_prev_qp, plot_prev_pf, plot_prev_pnf, plot_prev_ce, plot_prev_md;
+  u64 plot_prev_qc, plot_prev_uc, plot_prev_uh;
+
+  u64 stats_last_stats_ms, stats_last_plot_ms, stats_last_ms, stats_last_execs;
+  double stats_avg_exec;
+
+  u8 clean_trace[MAP_SIZE];
+  u8 clean_trace_custom[MAP_SIZE];
+  u8 first_trace[MAP_SIZE];
+
 } afl_state_t;
 
 /* A global pointer to all instances is needed (for now) for signals to arrive
@@ -567,22 +592,25 @@ struct custom_mutator {
   const char *name;
   void *      dh;
 
+  void *data;    /* custom mutator data ptr */
+
   /* hooks for the custom mutator function */
 
   /**
    * Initialize the custom mutator.
    *
-   * (Optional)
-   *
+   * @param afl AFL instance.
    * @param seed Seed used for the mutation.
+   * @return pointer to internal data or NULL on error
    */
-  void (*afl_custom_init)(afl_state_t *afl, unsigned int seed);
+  void *(*afl_custom_init)(afl_state_t *afl, unsigned int seed);
 
   /**
    * Perform custom mutations on a given input
    *
    * (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
    *     output
    * @param[in] buf_size Size of the input/output data
@@ -592,7 +620,7 @@ struct custom_mutator {
    * not produce data larger than max_size.
    * @return Size of the mutated output.
    */
-  size_t (*afl_custom_fuzz)(afl_state_t *afl, u8 **buf, size_t buf_size,
+  size_t (*afl_custom_fuzz)(void *data, u8 **buf, size_t buf_size,
                             u8 *add_buf, size_t add_buf_size, size_t max_size);
 
   /**
@@ -602,6 +630,7 @@ struct custom_mutator {
    * (Optional) If this functionality is not needed, simply don't define this
    * function.
    *
+   * @param[in] data pointer returned in afl_custom_init for this fuzz case
    * @param[in] buf Buffer containing the test case to be executed
    * @param[in] buf_size Size of the test case
    * @param[out] out_buf Pointer to the buffer of storing the test case after
@@ -609,7 +638,7 @@ struct custom_mutator {
    *     will release the memory after saving the test case.
    * @return Size of the output buffer after processing
    */
-  size_t (*afl_custom_pre_save)(afl_state_t *afl, u8 *buf, size_t buf_size,
+  size_t (*afl_custom_pre_save)(void *data, u8 *buf, size_t buf_size,
                                 u8 **out_buf);
 
   /**
@@ -628,11 +657,12 @@ struct custom_mutator {
    *
    * (Optional)
    *
+   * @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
    */
-  u32 (*afl_custom_init_trim)(afl_state_t *afl, u8 *buf, size_t buf_size);
+  u32 (*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
@@ -645,12 +675,13 @@ struct custom_mutator {
    *
    * (Optional)
    *
+   * @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
    */
-  void (*afl_custom_trim)(afl_state_t *afl, u8 **out_buf, size_t *out_buf_size);
+  void (*afl_custom_trim)(void *data, u8 **out_buf, size_t *out_buf_size);
 
   /**
    * This method is called after each trim operation to inform you if your
@@ -659,11 +690,12 @@ struct custom_mutator {
    *
    * (Optional)
    *
+   * @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)
    */
-  u32 (*afl_custom_post_trim)(afl_state_t *afl, u8 success);
+  u32 (*afl_custom_post_trim)(void *data, u8 success);
 
   /**
    * Perform a single custom mutation on a given input.
@@ -671,6 +703,7 @@ 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
    *     output
    * @param[in] buf_size Size of input data
@@ -678,7 +711,7 @@ struct custom_mutator {
    *     not produce data larger than max_size.
    * @return Size of the mutated output.
    */
-  size_t (*afl_custom_havoc_mutation)(afl_state_t *afl, u8 **buf,
+  size_t (*afl_custom_havoc_mutation)(void *data, u8 **buf,
                                       size_t buf_size, size_t max_size);
 
   /**
@@ -687,20 +720,22 @@ struct custom_mutator {
    *
    * (Optional)
    *
+   * @param data pointer returned in afl_custom_init for this fuzz case
    * @return The probability (0-100).
    */
-  u8 (*afl_custom_havoc_mutation_probability)(afl_state_t *afl);
+  u8 (*afl_custom_havoc_mutation_probability)(void *data);
 
   /**
    * Determine whether the fuzzer should fuzz the current queue entry or not.
    *
    * (Optional)
    *
+   * @param data pointer returned in afl_custom_init for this fuzz case
    * @param filename File name of the test case in the queue entry
    * @return Return True(1) if the fuzzer will fuzz the queue entry, and
    *     False(0) otherwise.
    */
-  u8 (*afl_custom_queue_get)(afl_state_t *afl, const u8 *filename);
+  u8 (*afl_custom_queue_get)(void *data, const u8 *filename);
 
   /**
    * Allow for additional analysis (e.g. calling a different tool that does a
@@ -708,13 +743,20 @@ struct custom_mutator {
    *
    * (Optional)
    *
+   * @param data pointer returned in afl_custom_init for this fuzz case
    * @param filename_new_queue File name of the new queue entry
    * @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)(afl_state_t *afl,
+  void (*afl_custom_queue_new_entry)(void *data,
                                      const u8 *   filename_new_queue,
                                      const u8 *   filename_orig_queue);
+  /**
+   * Deinitialize the custom mutator.
+   *
+   * @param data pointer returned in afl_custom_init for this fuzz case
+   */
+  void (*afl_custom_deinit)(void *data);
 
 };
 
@@ -732,19 +774,17 @@ u8   trim_case_custom(afl_state_t *, struct queue_entry *q, u8 *in_buf);
 /* Python */
 #ifdef USE_PYTHON
 
-int  init_py_module(afl_state_t *, u8 *);
-void finalize_py_module(afl_state_t *);
+void finalize_py_module(void *);
 
-void   init_py(afl_state_t *, unsigned int);
-size_t fuzz_py(afl_state_t *, u8 **, size_t, u8 *, size_t, size_t);
-size_t pre_save_py(afl_state_t *, u8 *, size_t, u8 **);
-u32    init_trim_py(afl_state_t *, u8 *, size_t);
-u32    post_trim_py(afl_state_t *, u8);
-void   trim_py(afl_state_t *, u8 **, size_t *);
-size_t havoc_mutation_py(afl_state_t *, u8 **, size_t, size_t);
-u8     havoc_mutation_probability_py(afl_state_t *);
-u8     queue_get_py(afl_state_t *, const u8 *);
-void   queue_new_entry_py(afl_state_t *, const u8 *, const u8 *);
+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);
+u8     havoc_mutation_probability_py(void *);
+u8     queue_get_py(void *, const u8 *);
+void   queue_new_entry_py(void *, const u8 *, const u8 *);
+void   deinit_py(void *);
 
 #endif
 
@@ -781,13 +821,6 @@ u8 *describe_op(afl_state_t *, u8);
 u8 save_if_interesting(afl_state_t *, void *, u32, u8);
 u8 has_new_bits(afl_state_t *, u8 *);
 
-/* Misc */
-
-u8 *DI(u64);
-u8 *DF(double);
-u8 *DMS(u64);
-u8 *DTD(u64, u64);
-
 /* Extras */
 
 void load_extras_file(afl_state_t *, u8 *, u32 *, u32 *, u32);
@@ -862,7 +895,7 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len,
 /* Generate a random number (from 0 to limit - 1). This may
    have slight bias. */
 
-static inline u32 UR(afl_state_t *afl, u32 limit) {
+static inline u32 rand_below(afl_state_t *afl, u32 limit) {
 
 #ifdef HAVE_ARC4RANDOM
   if (afl->fixed_seed) { return random() % limit; }
diff --git a/include/android-ashmem.h b/include/android-ashmem.h
index 3a0b9969..3a0b9969 100755..100644
--- a/include/android-ashmem.h
+++ b/include/android-ashmem.h
diff --git a/include/common.h b/include/common.h
index 28c11049..97076004 100644
--- a/include/common.h
+++ b/include/common.h
@@ -27,10 +27,16 @@
 #ifndef __AFLCOMMON_H
 #define __AFLCOMMON_H
 
+#include <stdio.h>
+#include <string.h>
 #include <sys/time.h>
 #include "types.h"
 #include "stdbool.h"
 
+/* STRINGIFY_VAL_SIZE_MAX will fit all stringify_ strings. */
+
+#define STRINGIFY_VAL_SIZE_MAX (16)
+
 void detect_file_args(char **argv, u8 *prog_in, u8 *use_stdin);
 void check_environment_vars(char **env);
 
@@ -67,5 +73,323 @@ static 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;
+
+}
+
+/* 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;
+
+}
+
+/* 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;
+
+}
+
+/* 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;
+
+}
+
+
+/* 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;
+
+}
+
+/* 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;
+
+}
+
+/* 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;
+
+}
+
+/* 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;
+
+}
+
 #endif
 
diff --git a/include/debug.h b/include/debug.h
index b3865c19..ff2845f9 100644
--- a/include/debug.h
+++ b/include/debug.h
@@ -32,6 +32,10 @@
  * Terminal colors *
  *******************/
 
+#ifndef MESSAGES_TO_STDOUT
+#define MESSAGES_TO_STDOUT
+#endif
+
 #ifdef USE_COLOR
 
 #define cBLK "\x1b[0;30m"
diff --git a/include/forkserver.h b/include/forkserver.h
index 9802b216..5d1bd2cf 100644
--- a/include/forkserver.h
+++ b/include/forkserver.h
@@ -62,9 +62,10 @@ typedef struct afl_forkserver {
 
   u8 use_fauxsrv;                       /* Fauxsrv for non-forking targets? */
 
+  u32 prev_timed_out;                   /* if prev forkserver run timed out */
+
 } afl_forkserver_t;
 
-void handle_timeout(int sig);
 void afl_fsrv_init(afl_forkserver_t *fsrv);
 void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv);
 void afl_fsrv_deinit(afl_forkserver_t *fsrv);
diff --git a/llvm_mode/Makefile b/llvm_mode/Makefile
index 5ce0e579..9626665c 100644
--- a/llvm_mode/Makefile
+++ b/llvm_mode/Makefile
@@ -21,8 +21,11 @@
 HASH=\#
 
 PREFIX      ?= /usr/local
-HELPER_PATH  = $(PREFIX)/lib/afl
-BIN_PATH     = $(PREFIX)/bin
+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)
 
@@ -159,7 +162,7 @@ ifeq "$(shell uname)" "OpenBSD"
   CLANG_LFL += `$(LLVM_CONFIG) --libdir`/libLLVM.so
 endif
 
-ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -fuse-ld=`type ld | awk '{print $$NF}'` -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
+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
 
@@ -317,6 +320,24 @@ all_done: test_build
 
 .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++" > ../$@
@@ -331,14 +352,14 @@ vpath  % ..
 	@../$* -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> and Andrea Fioraldi <andreafioraldi@gmail.com>" >> ../$@
+	@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)" "0"
+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
@@ -346,4 +367,4 @@ 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
+	rm -f $(PROGS) afl-common.o ../afl-clang-fast++ ../afl-clang-lto ../afl-clang-lto++ ../afl-clang*.8 ../ld
diff --git a/llvm_mode/README.ngram.md b/llvm_mode/README.ngram.md
new file mode 100644
index 00000000..ef248198
--- /dev/null
+++ b/llvm_mode/README.ngram.md
@@ -0,0 +1,20 @@
+# AFL N-Gram Branch Coverage
+
+## Source
+
+This is an LLVM-based implementation of the n-gram branch coverage proposed in
+the paper ["Be Sensitive and Collaborative: Analzying Impact of Coverage Metrics
+in Greybox Fuzzing"](https://www.usenix.org/system/files/raid2019-wang-jinghan.pdf),
+by Jinghan Wang, et. al.
+
+Note that the original implementation (available
+[here](https://github.com/bitsecurerlab/afl-sensitive))
+is built on top of AFL's QEMU mode.
+This is essentially a port that uses LLVM vectorized instructions to achieve
+the same results when compiling source code.
+
+## Usage
+
+The size of `n` (i.e., the number of branches to remember) is an option
+that is specified in the `AFL_LLVM_NGRAM_SIZE` environment variable.
+Good values are 2, 4 or 8.
diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c
index 313a2533..aec3bfd5 100644
--- a/llvm_mode/afl-clang-fast.c
+++ b/llvm_mode/afl-clang-fast.c
@@ -158,14 +158,20 @@ static void edit_params(u32 argc, char **argv) {
 #endif
     if (lto_flag[0] != '-')
       FATAL(
-          "afl-clang-lto not possible because Makefile magic did not identify "
-          "the correct -flto flag");
+          "Using afl-clang-lto is not possible because Makefile magic did not "
+          "identify the correct -flto flag");
     if (getenv("AFL_LLVM_INSTRIM") != NULL)
       FATAL("afl-clang-lto does not work with InsTrim mode");
+    if (getenv("AFL_LLVM_NGRAM_SIZE") != NULL)
+      FATAL("afl-clang-lto does not work with ngram coverage mode");
     lto_mode = 1;
 
   }
 
+  if (getenv("AFL_LLVM_NGRAM_SIZE") != NULL &&
+      getenv("AFL_LLVM_INSTRIM") != NULL)
+    FATAL("AFL_LLVM_NGRAM_SIZE and AFL_LLVM_INSTRIM cannot be used together");
+
   if (!strcmp(name, "afl-clang-fast++") || !strcmp(name, "afl-clang-lto++")) {
 
     u8 *alt_cxx = getenv("AFL_CXX");
@@ -545,12 +551,12 @@ int main(int argc, char **argv, char **envp) {
 #else
     if (strstr(argv[0], "afl-clang-lto") == NULL)
 
-      printf(cCYA "afl-clang-fast" VERSION cRST " by <lszekeres@google.com>\n");
+      printf("afl-clang-fast" VERSION " by <lszekeres@google.com>\n");
 
     else {
 
-      printf(cCYA "afl-clang-lto" VERSION cRST
-                  "  by Marc \"vanHauser\" Heuse <mh@mh-sec.de>\n");
+      printf("afl-clang-lto" VERSION
+             "  by Marc \"vanHauser\" Heuse <mh@mh-sec.de>\n");
 
     }
 
@@ -602,20 +608,36 @@ int main(int argc, char **argv, char **envp) {
             "AFL_LLVM_LAF_SPLIT_FLOATS: transform floating point comp. to "
             "cascaded "
             "comp.\n"
-            "AFL_LLVM_LAF_SPLIT_COMPARES_BITW: size limit (default 8)\n"
-            "AFL_LLVM_INSTRIM: use light weight instrumentation InsTrim\n"
-            "AFL_LLVM_INSTRIM_LOOPHEAD: optimize loop tracing for speed\n"
-            "AFL_LLVM_CMPLOG: log operands of comparisons (RedQueen mutator)\n"
-            "\nafl-clang-fast was built for llvm %s with the llvm binary path "
-            "of "
-            "\"%s\".\n",
-            callname, BIN_PATH, BIN_PATH, LLVM_VERSION, LLVM_BINDIR);
-
-    if (strcmp(callname, "afl-clang-lto") == 0)
-      SAYF(
-          "Compiled with linker target \"%s\" and LTO flags \"%s\"\n\n"
-          "If anything fails - be sure to read README.lto.md!\n\n",
-          AFL_REAL_LD, AFL_CLANG_FLTO);
+            "AFL_LLVM_LAF_SPLIT_COMPARES_BITW: size limit (default 8)\n",
+            callname, BIN_PATH, BIN_PATH);
+
+    SAYF(
+        "\nafl-clang-fast specific environment variables:\n"
+        "AFL_LLVM_INSTRIM: use light weight instrumentation InsTrim\n"
+        "AFL_LLVM_INSTRIM_LOOPHEAD: optimize loop tracing for speed\n"
+        "AFL_LLVM_NGRAM_SIZE: use ngram prev_loc coverage\n"
+        "AFL_LLVM_CMPLOG: log operands of comparisons (RedQueen mutator)\n");
+
+#ifdef AFL_CLANG_FLTO
+    SAYF(
+        "\nafl-clang-lto specific environment variables:\n"
+        "AFL_LLVM_LTO_STARTID: from which ID to start counting from for a "
+        "bb\n"
+        "AFL_LLVM_LTO_DONTWRITEID: don't write the highest ID used to a "
+        "global var\n"
+        "AFL_REAL_LD: use this linker instead of the compiled in path\n"
+        "AFL_LD_PASSTHROUGH: do not perform instrumentation (for configure "
+        "scripts)\n"
+        "\nafl-clang-lto was built with linker target \"%s\" and LTO flags "
+        "\"%s\"\n"
+        "If anything fails - be sure to read README.lto.md!\n",
+        AFL_REAL_LD, AFL_CLANG_FLTO);
+#endif
+
+    SAYF(
+        "\nafl-clang-fast was built for llvm %s with the llvm binary path "
+        "of \"%s\".\n",
+        LLVM_VERSION, LLVM_BINDIR);
 
     SAYF("\n");
 
diff --git a/llvm_mode/afl-llvm-pass.so.cc b/llvm_mode/afl-llvm-pass.so.cc
index 133c64b4..fefd9edd 100644
--- a/llvm_mode/afl-llvm-pass.so.cc
+++ b/llvm_mode/afl-llvm-pass.so.cc
@@ -2,12 +2,15 @@
    american fuzzy lop++ - LLVM-mode instrumentation pass
    ---------------------------------------------------
 
-   Written by Laszlo Szekeres <lszekeres@google.com> and
+   Written by Laszlo Szekeres <lszekeres@google.com>,
+              Adrian Herrera <adrian.herrera@anu.edu.au>,
               Michal Zalewski
 
    LLVM integration design comes from Laszlo Szekeres. C bits copied-and-pasted
    from afl-as.c are Michal's fault.
 
+   NGRAM previous location coverage comes from Adrian Herrera.
+
    Copyright 2015, 2016 Google Inc. All rights reserved.
    Copyright 2019-2020 AFLplusplus Project. All rights reserved.
 
@@ -27,7 +30,6 @@
 
 #include "config.h"
 #include "debug.h"
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -47,6 +49,7 @@ typedef long double max_align_t;
 #include "llvm/IR/BasicBlock.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Support/Debug.h"
+#include "llvm/Support/MathExtras.h"
 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
 
 #if LLVM_VERSION_MAJOR > 3 || \
@@ -58,6 +61,8 @@ typedef long double max_align_t;
 #include "llvm/Support/CFG.h"
 #endif
 
+#include "llvm-ngram-coverage.h"
+
 using namespace llvm;
 
 namespace {
@@ -118,6 +123,7 @@ class AFLCoverage : public ModulePass {
 
  protected:
   std::list<std::string> myWhitelist;
+  uint32_t               ngram_size = 0;
 
 };
 
@@ -129,8 +135,10 @@ bool AFLCoverage::runOnModule(Module &M) {
 
   LLVMContext &C = M.getContext();
 
-  IntegerType *   Int8Ty = IntegerType::getInt8Ty(C);
-  IntegerType *   Int32Ty = IntegerType::getInt32Ty(C);
+  IntegerType *Int8Ty = IntegerType::getInt8Ty(C);
+  IntegerType *Int32Ty = IntegerType::getInt32Ty(C);
+  IntegerType *IntLocTy =
+      IntegerType::getIntNTy(C, sizeof(PREV_LOC_T) * CHAR_BIT);
   struct timeval  tv;
   struct timezone tz;
   u32             rand_seed;
@@ -147,7 +155,8 @@ bool AFLCoverage::runOnModule(Module &M) {
 
   if ((isatty(2) && !getenv("AFL_QUIET")) || getenv("AFL_DEBUG") != NULL) {
 
-    SAYF(cCYA "afl-llvm-pass" VERSION cRST " by <lszekeres@google.com>\n");
+    SAYF(cCYA "afl-llvm-pass" VERSION cRST
+              " by <lszekeres@google.com> and <adrian.herrera@anu.edu.au>\n");
 
   } else
 
@@ -170,21 +179,73 @@ 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) */
+
+  char *ngram_size_str = getenv("AFL_LLVM_NGRAM_SIZE");
+  if (!ngram_size_str) ngram_size_str = getenv("AFL_NGRAM_SIZE");
+
+  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)");
+
+  unsigned PrevLocSize;
+  if (ngram_size == 1) ngram_size = 0;
+  if (ngram_size)
+    PrevLocSize = ngram_size - 1;
+  else
+    PrevLocSize = 1;
+  uint64_t    PrevLocVecSize = PowerOf2Ceil(PrevLocSize);
+  VectorType *PrevLocTy;
+
+  if (ngram_size) PrevLocTy = VectorType::get(IntLocTy, PrevLocVecSize);
+
   /* Get globals for the SHM region and the previous location. Note that
      __afl_prev_loc is thread-local. */
 
   GlobalVariable *AFLMapPtr =
       new GlobalVariable(M, PointerType::get(Int8Ty, 0), false,
                          GlobalValue::ExternalLinkage, 0, "__afl_area_ptr");
+  GlobalVariable *AFLPrevLoc;
 
+  if (ngram_size)
 #ifdef __ANDROID__
-  GlobalVariable *AFLPrevLoc = new GlobalVariable(
-      M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc");
+    AFLPrevLoc = new GlobalVariable(
+        M, PrevLocTy, /* isConstant */ false, GlobalValue::ExternalLinkage,
+        /* Initializer */ nullptr, "__afl_prev_loc");
 #else
-  GlobalVariable *AFLPrevLoc = new GlobalVariable(
-      M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc", 0,
-      GlobalVariable::GeneralDynamicTLSModel, 0, false);
+    AFLPrevLoc = new GlobalVariable(
+        M, PrevLocTy, /* isConstant */ false, GlobalValue::ExternalLinkage,
+        /* Initializer */ nullptr, "__afl_prev_loc",
+        /* InsertBefore */ nullptr, GlobalVariable::GeneralDynamicTLSModel,
+        /* AddressSpace */ 0, /* IsExternallyInitialized */ false);
 #endif
+  else
+#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);
+#endif
+
+  /* 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. */
+
+  SmallVector<Constant *, 32> PrevLocShuffle = {UndefValue::get(Int32Ty)};
+
+  for (unsigned I = 0; I < PrevLocSize - 1; ++I)
+    PrevLocShuffle.push_back(ConstantInt::get(Int32Ty, I));
+
+  for (unsigned I = PrevLocSize; I < PrevLocVecSize; ++I)
+    PrevLocShuffle.push_back(ConstantInt::get(Int32Ty, PrevLocSize));
+
+  Constant *PrevLocShuffleMask = ConstantVector::get(PrevLocShuffle);
+
+  // other constants we need
   ConstantInt *Zero = ConstantInt::get(Int8Ty, 0);
   ConstantInt *One = ConstantInt::get(Int8Ty, 1);
 
@@ -356,20 +417,41 @@ bool AFLCoverage::runOnModule(Module &M) {
       // fprintf(stderr, " == %d\n", more_than_one);
       if (more_than_one != 1) continue;
 #endif
-      ConstantInt *CurLoc = ConstantInt::get(Int32Ty, cur_loc);
+
+      ConstantInt *CurLoc;
+
+      if (ngram_size)
+        CurLoc = ConstantInt::get(IntLocTy, cur_loc);
+      else
+        CurLoc = ConstantInt::get(Int32Ty, cur_loc);
 
       /* Load prev_loc */
 
       LoadInst *PrevLoc = IRB.CreateLoad(AFLPrevLoc);
       PrevLoc->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
-      Value *PrevLocCasted = IRB.CreateZExt(PrevLoc, IRB.getInt32Ty());
+      Value *PrevLocTrans;
+
+      /* "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)" */
+
+      if (ngram_size)
+        PrevLocTrans = IRB.CreateXorReduce(PrevLoc);
+      else
+        PrevLocTrans = IRB.CreateZExt(PrevLoc, IRB.getInt32Ty());
 
       /* Load SHM pointer */
 
       LoadInst *MapPtr = IRB.CreateLoad(AFLMapPtr);
       MapPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
-      Value *MapPtrIdx =
-          IRB.CreateGEP(MapPtr, IRB.CreateXor(PrevLocCasted, CurLoc));
+
+      Value *MapPtrIdx;
+      if (ngram_size)
+        MapPtrIdx = IRB.CreateGEP(
+            MapPtr,
+            IRB.CreateZExt(IRB.CreateXor(PrevLocTrans, CurLoc), Int32Ty));
+      else
+        MapPtrIdx = IRB.CreateGEP(MapPtr, IRB.CreateXor(PrevLocTrans, CurLoc));
 
       /* Update bitmap */
 
@@ -449,11 +531,27 @@ bool AFLCoverage::runOnModule(Module &M) {
       IRB.CreateStore(Incr, MapPtrIdx)
           ->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
 
-      /* Set prev_loc to cur_loc >> 1 */
+      /* Update prev_loc history vector (by placing cur_loc at the head of the
+         vector and shuffle the other elements back by one) */
 
-      StoreInst *Store =
-          IRB.CreateStore(ConstantInt::get(Int32Ty, cur_loc >> 1), AFLPrevLoc);
-      Store->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
+      StoreInst *Store;
+
+      if (ngram_size) {
+
+        Value *ShuffledPrevLoc = IRB.CreateShuffleVector(
+            PrevLoc, UndefValue::get(PrevLocTy), PrevLocShuffleMask);
+        Value *UpdatedPrevLoc = IRB.CreateInsertElement(
+            ShuffledPrevLoc, IRB.CreateLShr(CurLoc, (uint64_t)1), (uint64_t)0);
+
+        Store = IRB.CreateStore(UpdatedPrevLoc, AFLPrevLoc);
+        Store->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
+
+      } else {
+
+        Store = IRB.CreateStore(ConstantInt::get(Int32Ty, cur_loc >> 1),
+                                AFLPrevLoc);
+
+      }
 
       inst_blocks++;
 
diff --git a/llvm_mode/afl-llvm-rt.o.c b/llvm_mode/afl-llvm-rt.o.c
index 5f9a5534..8fad0fbb 100644
--- a/llvm_mode/afl-llvm-rt.o.c
+++ b/llvm_mode/afl-llvm-rt.o.c
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "types.h"
 #include "cmplog.h"
+#include "llvm-ngram-coverage.h"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -62,11 +63,11 @@ u8  __afl_area_initial[MAP_SIZE];
 u8 *__afl_area_ptr = __afl_area_initial;
 
 #ifdef __ANDROID__
-u32 __afl_prev_loc;
-u32 __afl_final_loc;
+PREV_LOC_T __afl_prev_loc[MAX_NGRAM_SIZE];
+u32        __afl_final_loc;
 #else
-__thread u32 __afl_prev_loc;
-__thread u32 __afl_final_loc;
+__thread PREV_LOC_T __afl_prev_loc[MAX_NGRAM_SIZE];
+__thread u32        __afl_final_loc;
 #endif
 
 struct cmp_map *__afl_cmp_map;
@@ -281,7 +282,7 @@ int __afl_persistent_loop(unsigned int max_cnt) {
 
       memset(__afl_area_ptr, 0, MAP_SIZE);
       __afl_area_ptr[0] = 1;
-      __afl_prev_loc = 0;
+      memset(__afl_prev_loc, 0, MAX_NGRAM_SIZE * sizeof(PREV_LOC_T));
 
     }
 
@@ -298,7 +299,7 @@ int __afl_persistent_loop(unsigned int max_cnt) {
       raise(SIGSTOP);
 
       __afl_area_ptr[0] = 1;
-      __afl_prev_loc = 0;
+      memset(__afl_prev_loc, 0, MAX_NGRAM_SIZE * sizeof(PREV_LOC_T));
 
       return 1;
 
diff --git a/llvm_mode/llvm-ngram-coverage.h b/llvm_mode/llvm-ngram-coverage.h
new file mode 100644
index 00000000..4459bcd7
--- /dev/null
+++ b/llvm_mode/llvm-ngram-coverage.h
@@ -0,0 +1,18 @@
+#ifndef AFL_NGRAM_CONFIG_H
+#define AFL_NGRAM_CONFIG_H
+
+#include "../config.h"
+
+#if (MAP_SIZE_POW2 <= 16)
+typedef u16 PREV_LOC_T;
+#elif (MAP_SIZE_POW2 <= 32)
+typedef u32 PREV_LOC_T;
+#else
+typedef u64 PREV_LOC_T;
+#endif
+
+/* Maximum ngram size */
+#define MAX_NGRAM_SIZE 128
+
+#endif
+
diff --git a/qemu_mode/build_qemu_support.sh b/qemu_mode/build_qemu_support.sh
index 09c04e7f..bd42c58e 100755
--- a/qemu_mode/build_qemu_support.sh
+++ b/qemu_mode/build_qemu_support.sh
@@ -62,15 +62,15 @@ if [ ! -f "../afl-showmap" ]; then
 
 fi
 
+PREREQ_NOTFOUND=
+for i in libtool wget python automake autoconf sha384sum bison flex iconv patch pkg-config; do
 
-for i in libtool wget python automake autoconf sha384sum bison iconv; do
-
-  T=`which "$i" 2>/dev/null`
+  T=`command -v "$i" 2>/dev/null`
 
   if [ "$T" = "" ]; then
 
     echo "[-] Error: '$i' not found, please install first."
-    exit 1
+    PREREQ_NOTFOUND=1
 
   fi
 
@@ -79,17 +79,21 @@ done
 if [ ! -d "/usr/include/glib-2.0/" -a ! -d "/usr/local/include/glib-2.0/" ]; then
 
   echo "[-] Error: devel version of 'glib2' not found, please install first."
-  exit 1
+  PREREQ_NOTFOUND=1
 
 fi
 
 if echo "$CC" | grep -qF /afl-; then
 
   echo "[-] Error: do not use afl-gcc or afl-clang to compile this tool."
-  exit 1
+  PREREQ_NOTFOUND=1
 
 fi
 
+if [ "$PREREQ_NOTFOUND" = "1" ]; then
+  exit 1
+fi
+
 echo "[+] All checks passed!"
 
 ARCHIVE="`basename -- "$QEMU_URL"`"
@@ -139,8 +143,16 @@ echo "[*] Configuring QEMU for $CPU_TARGET..."
 
 ORIG_CPU_TARGET="$CPU_TARGET"
 
-test "$CPU_TARGET" = "" && CPU_TARGET="`uname -m`"
-test "$CPU_TARGET" = "i686" && CPU_TARGET="i386"
+if [ "$ORIG_CPU_TARGET" = "" ]; then
+  CPU_TARGET="`uname -m`"
+  test "$CPU_TARGET" = "i686" && CPU_TARGET="i386"
+  test "$CPU_TARGET" = "arm64v8" && CPU_TARGET="aarch64"
+  case "$CPU_TARGET" in 
+    *arm*)
+      CPU_TARGET="arm"
+      ;;
+  esac
+fi
 
 cd qemu-$VERSION || exit 1
 
diff --git a/qemu_mode/patches/afl-qemu-tcg-runtime-inl.h b/qemu_mode/patches/afl-qemu-tcg-runtime-inl.h
index b7cd71bb..1526f09c 100644
--- a/qemu_mode/patches/afl-qemu-tcg-runtime-inl.h
+++ b/qemu_mode/patches/afl-qemu-tcg-runtime-inl.h
@@ -185,8 +185,8 @@ void HELPER(afl_cmplog_rtn)(CPUArchState *env) {
   if (!area_is_mapped(stack, sizeof(target_ulong) * 2)) return;
 
   // when this hook is executed, the retaddr is not on stack yet
-  void *ptr1 = g2h(stack[0]);
-  void *ptr2 = g2h(stack[1]);
+  void *    ptr1 = g2h(stack[0]);
+  void *    ptr2 = g2h(stack[1]);
 
 #else
 
diff --git a/src/afl-analyze.c b/src/afl-analyze.c
index 2148cdf0..d509c43e 100644
--- a/src/afl-analyze.c
+++ b/src/afl-analyze.c
@@ -207,15 +207,6 @@ static s32 write_to_file(u8 *path, u8 *mem, u32 len) {
 
 }
 
-/* Handle timeout signal. */
-
-static void handle_timeout(int sig) {
-
-  child_timed_out = 1;
-  if (child_pid > 0) kill(child_pid, SIGKILL);
-
-}
-
 /* Execute target application. Returns exec checksum, or 0 if program
    times out. */
 
@@ -770,11 +761,6 @@ static void setup_signal_handlers(void) {
   sigaction(SIGINT, &sa, NULL);
   sigaction(SIGTERM, &sa, NULL);
 
-  /* Exec timeout notifications. */
-
-  sa.sa_handler = handle_timeout;
-  sigaction(SIGALRM, &sa, NULL);
-
 }
 
 /* Display usage hints. */
diff --git a/src/afl-common.c b/src/afl-common.c
index 1aa15442..8c4d53e8 100644
--- a/src/afl-common.c
+++ b/src/afl-common.c
@@ -57,10 +57,10 @@ char *    afl_environment_variables[] = {
     "AFL_LLVM_INSTRIM_LOOPHEAD", "AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK",
     "AFL_LLVM_LAF_SPLIT_COMPARES", "AFL_LLVM_LAF_SPLIT_COMPARES_BITW",
     "AFL_LLVM_LAF_SPLIT_FLOATS", "AFL_LLVM_LAF_SPLIT_SWITCHES",
-    "AFL_LLVM_LAF_TRANSFORM_COMPARES", "AFL_LLVM_NOT_ZERO",
-    "AFL_LLVM_WHITELIST", "AFL_NO_AFFINITY", "AFL_LLVM_LTO_STARTID",
-    "AFL_LLVM_LTO_DONTWRITEID", "AFL_NO_ARITH", "AFL_NO_BUILTIN",
-    "AFL_NO_CPU_RED", "AFL_NO_FORKSRV", "AFL_NO_UI",
+    "AFL_LLVM_LAF_TRANSFORM_COMPARES", "AFL_LLVM_NGRAM_SIZE", "AFL_NGRAM_SIZE",
+    "AFL_LLVM_NOT_ZERO", "AFL_LLVM_WHITELIST", "AFL_NO_AFFINITY",
+    "AFL_LLVM_LTO_STARTID", "AFL_LLVM_LTO_DONTWRITEID", "AFL_NO_ARITH",
+    "AFL_NO_BUILTIN", "AFL_NO_CPU_RED", "AFL_NO_FORKSRV", "AFL_NO_UI",
     "AFL_NO_X86",  // not really an env but we dont want to warn on it
     "AFL_PATH", "AFL_PERFORMANCE_FILE",
     //"AFL_PERSISTENT", // not implemented anymore, so warn additionally
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index c7a3475f..2dd7a9f0 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -51,91 +51,8 @@
 
 extern u8 *doc_path;
 
-u8 *forkserver_DMS(u64 val) {
-
-  static u8 tmp[12][16];
-  static u8 cur;
-
-#define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast)    \
-  do {                                                    \
-                                                          \
-    if (val < (_divisor) * (_limit_mult)) {               \
-                                                          \
-      sprintf(tmp[cur], _fmt, ((_cast)val) / (_divisor)); \
-      return tmp[cur];                                    \
-                                                          \
-    }                                                     \
-                                                          \
-  } while (0)
-
-  cur = (cur + 1) % 12;
-
-  /* 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(tmp[cur], "infty");
-  return tmp[cur];
-
-}
-
 list_t fsrv_list = {.element_prealloc_count = 0};
 
-/* the timeout handler */
-
-void handle_timeout(int sig) {
-
-  LIST_FOREACH(&fsrv_list, afl_forkserver_t, {
-
-    // TODO: We need a proper timer to handle multiple timeouts
-    if (el->child_pid > 0) {
-
-      el->child_timed_out = 1;
-      kill(el->child_pid, SIGKILL);
-
-    } else if (el->child_pid == -1 && el->fsrv_pid > 0) {
-
-      el->child_timed_out = 1;
-      kill(el->fsrv_pid, SIGKILL);
-
-    }
-
-  });
-
-}
-
 /* Initializes the struct */
 
 void afl_fsrv_init(afl_forkserver_t *fsrv) {
@@ -156,6 +73,7 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
   fsrv->out_dir_fd = -1;
 
   fsrv->use_fauxsrv = 0;
+  fsrv->prev_timed_out = 0;
 
   list_append(&fsrv_list, fsrv);
 
@@ -166,8 +84,8 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
 
 static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) {
 
-  static unsigned char tmp[4] = {0};
-  pid_t                child_pid = -1;
+  unsigned char tmp[4] = {0};
+  pid_t         child_pid = -1;
 
   /* Phone home and tell the parent that we're OK. If parent isn't there,
      assume we're not running in forkserver mode and just execute program. */
@@ -476,6 +394,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv) {
 
     } else {
 
+      u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
+
       SAYF("\n" cLRD "[-] " cRST
            "Whoops, the target binary crashed suddenly, "
            "before receiving any input\n"
@@ -508,7 +428,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv) {
            "options\n"
            "      fail, poke <afl-users@googlegroups.com> for troubleshooting "
            "tips.\n",
-           forkserver_DMS(fsrv->mem_limit << 20), fsrv->mem_limit - 1);
+           stringify_mem_size(val_buf, sizeof(val_buf), fsrv->mem_limit << 20),
+           fsrv->mem_limit - 1);
 
     }
 
@@ -543,6 +464,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv) {
 
   } else {
 
+    u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
+
     SAYF(
         "\n" cLRD "[-] " cRST
         "Hmm, looks like the target binary terminated "
@@ -574,7 +497,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv) {
               "never\n"
               "      reached before the program terminates.\n\n"
             : "",
-        forkserver_DMS(fsrv->mem_limit << 20), fsrv->mem_limit - 1);
+        stringify_int(val_buf, sizeof(val_buf), fsrv->mem_limit << 20),
+        fsrv->mem_limit - 1);
 
   }
 
diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c
index 7e2d3212..0d5b542d 100644
--- a/src/afl-fuzz-bitmap.c
+++ b/src/afl-fuzz-bitmap.c
@@ -138,7 +138,8 @@ u8 has_new_bits(afl_state_t *afl, u8 *virgin_map) {
 
   }
 
-  if (ret && virgin_map == afl->virgin_bits) afl->bitmap_changed = 1;
+  if (unlikely(ret) && unlikely(virgin_map == afl->virgin_bits))
+    afl->bitmap_changed = 1;
 
   return ret;
 
@@ -413,13 +414,13 @@ void minimize_bits(u8 *dst, u8 *src) {
 #ifndef SIMPLE_FILES
 
 /* Construct a file name for a new test case, capturing the operation
-   that led to its discovery. Uses a static buffer. */
+   that led to its discovery. Returns a ptr to afl->describe_op_buf_256. */
 
 u8 *describe_op(afl_state_t *afl, u8 hnb) {
 
   u8 *ret = afl->describe_op_buf_256;
 
-  if (afl->syncing_party) {
+  if (unlikely(afl->syncing_party)) {
 
     sprintf(ret, "sync:%s,src:%06u", afl->syncing_party, afl->syncing_case);
 
@@ -465,16 +466,18 @@ static void write_crash_readme(afl_state_t *afl) {
   s32   fd;
   FILE *f;
 
+  u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
+
   fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
   ck_free(fn);
 
   /* Do not die on errors here - that would be impolite. */
 
-  if (fd < 0) return;
+  if (unlikely(fd < 0)) return;
 
   f = fdopen(fd, "w");
 
-  if (!f) {
+  if (unlikely(!f)) {
 
     close(fd);
     return;
@@ -501,7 +504,9 @@ static void write_crash_readme(afl_state_t *afl) {
 
       "  https://github.com/AFLplusplus/AFLplusplus\n\n",
 
-      afl->orig_cmdline, DMS(afl->fsrv.mem_limit << 20));  /* ignore errors */
+      afl->orig_cmdline,
+      stringify_mem_size(val_buf, sizeof(val_buf),
+                         afl->fsrv.mem_limit << 20));      /* ignore errors */
 
   fclose(f);
 
@@ -513,7 +518,7 @@ static void write_crash_readme(afl_state_t *afl) {
 
 u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
 
-  if (len == 0) return 0;
+  if (unlikely(len == 0)) return 0;
 
   u8 *fn = "";
   u8  hnb;
@@ -537,14 +542,14 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
 
   }
 
-  if (fault == afl->crash_mode) {
+  if (unlikely(fault == afl->crash_mode)) {
 
     /* Keep only if there are new bits in the map, add to queue for
        future fuzzing, etc. */
 
     if (!(hnb = has_new_bits(afl, afl->virgin_bits))) {
 
-      if (afl->crash_mode) ++afl->total_crashes;
+      if (unlikely(afl->crash_mode)) ++afl->total_crashes;
       return 0;
 
     }
@@ -576,10 +581,11 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
 
     res = calibrate_case(afl, afl->queue_top, mem, afl->queue_cycle - 1, 0);
 
-    if (res == FAULT_ERROR) FATAL("Unable to execute target application");
+    if (unlikely(res == FAULT_ERROR))
+      FATAL("Unable to execute target application");
 
     fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
-    if (fd < 0) PFATAL("Unable to create '%s'", fn);
+    if (unlikely(fd < 0)) PFATAL("Unable to create '%s'", fn);
     ck_write(fd, mem, len, fn);
     close(fd);
 
@@ -600,7 +606,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
 
       if (afl->unique_hangs >= KEEP_UNIQUE_HANG) return keeping;
 
-      if (!afl->dumb_mode) {
+      if (likely(!afl->dumb_mode)) {
 
 #ifdef WORD_SIZE_64
         simplify_trace((u64 *)afl->fsrv.trace_bits);
@@ -663,7 +669,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
 
       if (afl->unique_crashes >= KEEP_UNIQUE_CRASH) return keeping;
 
-      if (!afl->dumb_mode) {
+      if (likely(!afl->dumb_mode)) {
 
 #ifdef WORD_SIZE_64
         simplify_trace((u64 *)afl->fsrv.trace_bits);
@@ -675,7 +681,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
 
       }
 
-      if (!afl->unique_crashes) write_crash_readme(afl);
+      if (unlikely(!afl->unique_crashes)) write_crash_readme(afl);
 
 #ifndef SIMPLE_FILES
 
@@ -691,10 +697,10 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
 #endif                                                    /* ^!SIMPLE_FILES */
 
       ++afl->unique_crashes;
-      if (afl->infoexec) {  // if the user wants to be informed on new crashes -
-                            // do
+      if (unlikely(afl->infoexec)) {
+
+        // if the user wants to be informed on new crashes - do that
 #if !TARGET_OS_IPHONE
-        // that
         if (system(afl->infoexec) == -1)
           hnb += 0;  // we dont care if system errors, but we dont want a
                      // compiler warning either
@@ -719,7 +725,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
      test case, too. */
 
   fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
-  if (fd < 0) PFATAL("Unable to create '%s'", fn);
+  if (unlikely(fd < 0)) PFATAL("Unable to create '%s'", fn);
   ck_write(fd, mem, len, fn);
   close(fd);
 
diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c
index 1600af53..6c6f05ac 100644
--- a/src/afl-fuzz-cmplog.c
+++ b/src/afl-fuzz-cmplog.c
@@ -31,10 +31,10 @@
 
 void init_cmplog_forkserver(afl_state_t *afl) {
 
-  static struct timeval timeout;
-  int                   st_pipe[2], ctl_pipe[2];
-  int                   status;
-  s32                   rlen;
+  struct timeval timeout;
+  int            st_pipe[2], ctl_pipe[2];
+  int            status;
+  s32            rlen;
 
   ACTF("Spinning up the cmplog fork server...");
 
@@ -264,6 +264,8 @@ void init_cmplog_forkserver(afl_state_t *afl) {
 
     } else {
 
+      u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
+
       SAYF("\n" cLRD "[-] " cRST
            "Whoops, the target binary crashed suddenly, "
            "before receiving any input\n"
@@ -296,7 +298,9 @@ void init_cmplog_forkserver(afl_state_t *afl) {
            "options\n"
            "      fail, poke <afl-users@googlegroups.com> for troubleshooting "
            "tips.\n",
-           DMS(afl->fsrv.mem_limit << 20), afl->fsrv.mem_limit - 1);
+           stringify_mem_size(val_buf, sizeof(val_buf),
+                              afl->fsrv.mem_limit << 20),
+           afl->fsrv.mem_limit - 1);
 
     }
 
@@ -331,6 +335,8 @@ void init_cmplog_forkserver(afl_state_t *afl) {
 
   } else {
 
+    u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
+
     SAYF(
         "\n" cLRD "[-] " cRST
         "Hmm, looks like the target binary terminated "
@@ -362,7 +368,8 @@ void init_cmplog_forkserver(afl_state_t *afl) {
               "never\n"
               "      reached before the program terminates.\n\n"
             : "",
-        DMS(afl->fsrv.mem_limit << 20), afl->fsrv.mem_limit - 1);
+        stringify_mem_size(val_buf, sizeof(val_buf), afl->fsrv.mem_limit << 20),
+        afl->fsrv.mem_limit - 1);
 
   }
 
@@ -372,12 +379,15 @@ void init_cmplog_forkserver(afl_state_t *afl) {
 
 u8 run_cmplog_target(afl_state_t *afl, u32 timeout) {
 
-  static struct itimerval it;
-  static u32              prev_timed_out = 0;
-  static u64              exec_ms = 0;
+  struct timeval it;
+  int            status = 0;
+  int            sret;
+  u64            exec_ms;
 
-  int status = 0;
   u32 tb4;
+  s32 res;
+
+  fd_set readfds;
 
   afl->fsrv.child_timed_out = 0;
 
@@ -388,185 +398,80 @@ u8 run_cmplog_target(afl_state_t *afl, u32 timeout) {
   memset(afl->fsrv.trace_bits, 0, MAP_SIZE);
   MEM_BARRIER();
 
-  /* If we're running in "dumb" mode, we can't rely on the fork server
-     logic compiled into the target program, so we will just keep calling
-     execve(). There is a bit of code duplication between here and
-     init_forkserver(), but c'est la vie. */
-
-  if (afl->dumb_mode == 1 || afl->no_forkserver) {
-
-    afl->cmplog_child_pid = fork();
-
-    if (afl->cmplog_child_pid < 0) PFATAL("fork() failed");
-
-    if (!afl->cmplog_child_pid) {
-
-      struct rlimit r;
-
-      if (afl->fsrv.mem_limit) {
-
-        r.rlim_max = r.rlim_cur = ((rlim_t)afl->fsrv.mem_limit) << 20;
-
-#ifdef RLIMIT_AS
-
-        setrlimit(RLIMIT_AS, &r);                          /* Ignore errors */
-
-#else
-
-        setrlimit(RLIMIT_DATA, &r);                        /* Ignore errors */
+  /* Since we always have a forkserver (or a fauxserver) running, we can simply
+  tell them to have at it and read back the pid from it.*/
 
-#endif                                                        /* ^RLIMIT_AS */
-
-      }
-
-      r.rlim_max = r.rlim_cur = 0;
-
-      setrlimit(RLIMIT_CORE, &r);                          /* Ignore errors */
-
-      /* Isolate the process and configure standard descriptors. If
-         afl->fsrv.out_file is specified, stdin is /dev/null; otherwise,
-         afl->fsrv.out_fd is cloned instead. */
-
-      setsid();
-
-      dup2(afl->fsrv.dev_null_fd, 1);
-      dup2(afl->fsrv.dev_null_fd, 2);
-
-      if (afl->fsrv.out_file) {
-
-        dup2(afl->fsrv.dev_null_fd, 0);
-
-      } else {
+  if ((res = write(afl->cmplog_fsrv_ctl_fd, &afl->cmplog_prev_timed_out, 4)) !=
+      4) {
 
-        dup2(afl->fsrv.out_fd, 0);
-        close(afl->fsrv.out_fd);
+    if (afl->stop_soon) return 0;
+    RPFATAL(res,
+            "Unable to request new process from cmplog fork server (OOM?)");
 
-      }
-
-      /* On Linux, would be faster to use O_CLOEXEC. Maybe TODO. */
-
-      close(afl->fsrv.dev_null_fd);
-      close(afl->fsrv.out_dir_fd);
-#ifndef HAVE_ARC4RANDOM
-      close(afl->fsrv.dev_urandom_fd);
-#endif
-      close(fileno(afl->fsrv.plot_file));
-
-      /* Set sane defaults for ASAN if nothing else specified. */
-
-      setenv("ASAN_OPTIONS",
-             "abort_on_error=1:"
-             "detect_leaks=0:"
-             "symbolize=0:"
-             "allocator_may_return_null=1",
-             0);
-
-      setenv("MSAN_OPTIONS", "exit_code=" STRINGIFY(MSAN_ERROR) ":"
-                             "symbolize=0:"
-                             "msan_track_origins=0", 0);
-
-      setenv("___AFL_EINS_ZWEI_POLIZEI___", "1", 1);
-
-      if (!afl->qemu_mode && afl->argv[0] != afl->cmplog_binary) {
-
-        ck_free(afl->argv[0]);
-        afl->argv[0] = afl->cmplog_binary;
-
-      }
-
-      execv(afl->argv[0], afl->argv);
-
-      /* Use a distinctive bitmap value to tell the parent about execv()
-         falling through. */
-
-      *(u32 *)afl->fsrv.trace_bits = EXEC_FAIL_SIG;
-      exit(0);
-
-    }
-
-  } else {
-
-    s32 res;
-
-    /* In non-dumb mode, we have the fork server up and running, so simply
-       tell it to have at it, and then read back PID. */
-
-    if ((res = write(afl->cmplog_fsrv_ctl_fd, &prev_timed_out, 4)) != 4) {
-
-      if (afl->stop_soon) return 0;
-      RPFATAL(res,
-              "Unable to request new process from cmplog fork server (OOM?)");
-
-    }
-
-    if ((res = read(afl->cmplog_fsrv_st_fd, &afl->cmplog_child_pid, 4)) != 4) {
-
-      if (afl->stop_soon) return 0;
-      RPFATAL(res,
-              "Unable to request new process from cmplog fork server (OOM?)");
+  }
 
-    }
+  if ((res = read(afl->cmplog_fsrv_st_fd, &afl->cmplog_child_pid, 4)) != 4) {
 
-    if (afl->cmplog_child_pid <= 0)
-      FATAL("Cmplog fork server is misbehaving (OOM?)");
+    if (afl->stop_soon) return 0;
+    RPFATAL(res,
+            "Unable to request new process from cmplog fork server (OOM?)");
 
   }
 
+  if (afl->cmplog_child_pid <= 0)
+    FATAL("Cmplog fork server is misbehaving (OOM?)");
+
   /* Configure timeout, as requested by user, then wait for child to terminate.
    */
 
-  it.it_value.tv_sec = (timeout / 1000);
-  it.it_value.tv_usec = (timeout % 1000) * 1000;
+  it.tv_sec = (timeout / 1000);
+  it.tv_usec = (timeout % 1000) * 1000;
 
-  setitimer(ITIMER_REAL, &it, NULL);
+  FD_ZERO(&readfds);
+  FD_SET(afl->cmplog_fsrv_st_fd, &readfds);
+  it.tv_sec = ((timeout) / 1000);
+  it.tv_usec = ((timeout) % 1000) * 1000;
 
-  /* The SIGALRM handler simply kills the afl->cmplog_child_pid and sets
-   * afl->fsrv.child_timed_out. */
+  sret = select(afl->cmplog_fsrv_st_fd + 1, &readfds, NULL, NULL, &it);
 
-  if (afl->dumb_mode == 1 || afl->no_forkserver) {
+  if (sret == 0) {
 
-    if (waitpid(afl->cmplog_child_pid, &status, 0) <= 0)
-      PFATAL("waitpid() failed");
+    /* If there was no response from forkserver after timeout seconds,
+    we kill the child. The forkserver should inform us afterwards */
 
-  } else {
+    kill(afl->cmplog_child_pid, SIGKILL);
+    afl->fsrv.child_timed_out = 1;
 
-    s32 res;
-
-    if ((res = read(afl->cmplog_fsrv_st_fd, &status, 4)) != 4) {
-
-      if (afl->stop_soon) return 0;
-      SAYF(
-          "\n" cLRD "[-] " cRST
-          "Unable to communicate with fork server. Some possible reasons:\n\n"
-          "    - You've run out of memory. Use -m to increase the the memory "
-          "limit\n"
-          "      to something higher than %lld.\n"
-          "    - The binary or one of the libraries it uses manages to create\n"
-          "      threads before the forkserver initializes.\n"
-          "    - The binary, at least in some circumstances, exits in a way "
-          "that\n"
-          "      also kills the parent process - raise() could be the "
-          "culprit.\n\n"
-          "If all else fails you can disable the fork server via "
-          "AFL_NO_FORKSRV=1.\n",
-          afl->fsrv.mem_limit);
-      RPFATAL(res, "Unable to communicate with fork server");
+  }
 
-    }
+  if ((res = read(afl->cmplog_fsrv_st_fd, &status, 4)) != 4) {
+
+    if (afl->stop_soon) return 0;
+    SAYF("\n" cLRD "[-] " cRST
+         "Unable to communicate with fork server. Some possible reasons:\n\n"
+         "    - You've run out of memory. Use -m to increase the the memory "
+         "limit\n"
+         "      to something higher than %lld.\n"
+         "    - The binary or one of the libraries it uses manages to create\n"
+         "      threads before the forkserver initializes.\n"
+         "    - The binary, at least in some circumstances, exits in a way "
+         "that\n"
+         "      also kills the parent process - raise() could be the "
+         "culprit.\n\n"
+         "If all else fails you can disable the fork server via "
+         "AFL_NO_FORKSRV=1.\n",
+         afl->fsrv.mem_limit);
+    RPFATAL(res, "Unable to communicate with fork server");
 
   }
 
   if (!WIFSTOPPED(status)) afl->cmplog_child_pid = 0;
 
-  getitimer(ITIMER_REAL, &it);
-  exec_ms =
-      (u64)timeout - (it.it_value.tv_sec * 1000 + it.it_value.tv_usec / 1000);
+  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.it_value.tv_sec = 0;
-  it.it_value.tv_usec = 0;
-
-  setitimer(ITIMER_REAL, &it, NULL);
+  it.tv_sec = 0;
+  it.tv_usec = 0;
 
   ++afl->total_execs;
 
@@ -584,7 +489,7 @@ u8 run_cmplog_target(afl_state_t *afl, u32 timeout) {
   classify_counts((u32 *)afl->fsrv.trace_bits);
 #endif                                                     /* ^WORD_SIZE_64 */
 
-  prev_timed_out = afl->fsrv.child_timed_out;
+  afl->cmplog_prev_timed_out = afl->fsrv.child_timed_out;
 
   /* Report outcome to caller. */
 
diff --git a/src/afl-fuzz-extras.c b/src/afl-fuzz-extras.c
index ff4c0ae2..4dd1647c 100644
--- a/src/afl-fuzz-extras.c
+++ b/src/afl-fuzz-extras.c
@@ -55,6 +55,8 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len,
   u8 *  lptr;
   u32   cur_line = 0;
 
+  u8 val_bufs[2][STRINGIFY_VAL_SIZE_MAX];
+
   f = fopen(fname, "r");
 
   if (!f) PFATAL("Unable to open '%s'", fname);
@@ -170,8 +172,10 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len,
     afl->extras[afl->extras_cnt].len = klen;
 
     if (afl->extras[afl->extras_cnt].len > MAX_DICT_FILE)
-      FATAL("Keyword too big in line %u (%s, limit is %s)", cur_line, DMS(klen),
-            DMS(MAX_DICT_FILE));
+      FATAL(
+          "Keyword too big in line %u (%s, limit is %s)", cur_line,
+          stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), klen),
+          stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), MAX_DICT_FILE));
 
     if (*min_len > klen) *min_len = klen;
     if (*max_len < klen) *max_len = klen;
@@ -193,6 +197,8 @@ void load_extras(afl_state_t *afl, u8 *dir) {
   u32            min_len = MAX_DICT_FILE, max_len = 0, dict_level = 0;
   u8 *           x;
 
+  u8 val_bufs[2][STRINGIFY_VAL_SIZE_MAX];
+
   /* If the name ends with @, extract level and continue. */
 
   if ((x = strchr(dir, '@'))) {
@@ -238,8 +244,10 @@ void load_extras(afl_state_t *afl, u8 *dir) {
     }
 
     if (st.st_size > MAX_DICT_FILE)
-      FATAL("Extra '%s' is too big (%s, limit is %s)", fn, DMS(st.st_size),
-            DMS(MAX_DICT_FILE));
+      FATAL(
+          "Extra '%s' is too big (%s, limit is %s)", fn,
+          stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), st.st_size),
+          stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), MAX_DICT_FILE));
 
     if (min_len > st.st_size) min_len = st.st_size;
     if (max_len < st.st_size) max_len = st.st_size;
@@ -273,11 +281,12 @@ check_and_sort:
         compare_extras_len);
 
   OKF("Loaded %u extra tokens, size range %s to %s.", afl->extras_cnt,
-      DMS(min_len), DMS(max_len));
+      stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), min_len),
+      stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), max_len));
 
   if (max_len > 32)
     WARNF("Some tokens are relatively large (%s) - consider trimming.",
-          DMS(max_len));
+          stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), max_len));
 
   if (afl->extras_cnt > MAX_DET_EXTRAS)
     WARNF("More than %d tokens - will use them probabilistically.",
@@ -378,7 +387,7 @@ void maybe_add_auto(afl_state_t *afl, u8 *mem, u32 len) {
 
   } else {
 
-    i = MAX_AUTO_EXTRAS / 2 + UR(afl, (MAX_AUTO_EXTRAS + 1) / 2);
+    i = MAX_AUTO_EXTRAS / 2 + rand_below(afl, (MAX_AUTO_EXTRAS + 1) / 2);
 
     ck_free(afl->a_extras[i].data);
 
diff --git a/src/afl-fuzz-globals.c b/src/afl-fuzz-globals.c
index efffa749..88633a1b 100644
--- a/src/afl-fuzz-globals.c
+++ b/src/afl-fuzz-globals.c
@@ -30,8 +30,9 @@ s8  interesting_8[] = {INTERESTING_8};
 s16 interesting_16[] = {INTERESTING_8, INTERESTING_16};
 s32 interesting_32[] = {INTERESTING_8, INTERESTING_16, INTERESTING_32};
 
-char *power_names[POWER_SCHEDULES_NUM] = {"explore", "fast",    "coe",  "lin",
-                                          "quad",    "exploit", "mmopt"};
+char *power_names[POWER_SCHEDULES_NUM] = {
+
+    "explore", "fast", "coe", "lin", "quad", "exploit", "mmopt", "rare"};
 
 u8 *doc_path = NULL;                    /* gath to documentation dir        */
 
@@ -78,6 +79,8 @@ list_t afl_states = {.element_prealloc_count = 0};
 
 void afl_state_init(afl_state_t *afl) {
 
+  memset(afl, 0, sizeof(afl_state_t));
+
   afl->w_init = 0.9;
   afl->w_end = 0.3;
   afl->g_max = 5000;
@@ -114,6 +117,29 @@ void afl_state_init(afl_state_t *afl) {
   afl->fsrv.child_pid = -1;
   afl->fsrv.out_dir_fd = -1;
 
+  afl->cmplog_prev_timed_out = 0;
+
+  /* statis file */
+  afl->last_bitmap_cvg = 0;
+  afl->last_stability = 0;
+  afl->last_eps = 0;
+
+  /* plot file saves from last run */
+  afl->plot_prev_qp = 0;
+  afl->plot_prev_pf = 0;
+  afl->plot_prev_pnf = 0;
+  afl->plot_prev_ce = 0;
+  afl->plot_prev_md = 0;
+  afl->plot_prev_qc = 0;
+  afl->plot_prev_uc = 0;
+  afl->plot_prev_uh = 0;
+
+  afl->stats_last_stats_ms = 0;
+  afl->stats_last_plot_ms = 0;
+  afl->stats_last_ms = 0;
+  afl->stats_last_execs = 0;
+  afl->stats_avg_exec = -1;
+
   init_mopt_globals(afl);
 
   list_append(&afl_states, afl);
diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c
index 6b5fa24f..038c4393 100644
--- a/src/afl-fuzz-init.c
+++ b/src/afl-fuzz-init.c
@@ -304,7 +304,7 @@ static void shuffle_ptrs(afl_state_t *afl, void **ptrs, u32 cnt) {
 
   for (i = 0; i < cnt - 2; ++i) {
 
-    u32   j = i + UR(afl, cnt - i);
+    u32   j = i + rand_below(afl, cnt - i);
     void *s = ptrs[i];
     ptrs[i] = ptrs[j];
     ptrs[j] = s;
@@ -323,6 +323,8 @@ void read_testcases(afl_state_t *afl) {
   u32             i;
   u8 *            fn1;
 
+  u8 val_buf[2][STRINGIFY_VAL_SIZE_MAX];
+
   /* Auto-detect non-in-place resumption attempts. */
 
   fn1 = alloc_printf("%s/queue", afl->in_dir);
@@ -389,8 +391,9 @@ void read_testcases(afl_state_t *afl) {
     }
 
     if (st.st_size > MAX_FILE)
-      FATAL("Test case '%s' is too big (%s, limit is %s)", fn2, DMS(st.st_size),
-            DMS(MAX_FILE));
+      FATAL("Test case '%s' is too big (%s, limit is %s)", fn2,
+            stringify_mem_size(val_buf[0], sizeof(val_buf[0]), st.st_size),
+            stringify_mem_size(val_buf[1], sizeof(val_buf[1]), MAX_FILE));
 
     /* Check for metadata that indicates that deterministic fuzzing
        is complete for this entry. We don't want to repeat deterministic
@@ -553,6 +556,8 @@ void perform_dry_run(afl_state_t *afl) {
 
         if (afl->fsrv.mem_limit) {
 
+          u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
+
           SAYF("\n" cLRD "[-] " cRST
                "Oops, the program crashed with one of the test cases provided. "
                "There are\n"
@@ -593,8 +598,9 @@ void perform_dry_run(afl_state_t *afl) {
                "other options\n"
                "      fail, poke <afl-users@googlegroups.com> for "
                "troubleshooting tips.\n",
-               DMS(afl->fsrv.mem_limit << 20), afl->fsrv.mem_limit - 1,
-               doc_path);
+               stringify_mem_size(val_buf, sizeof(val_buf),
+                                  afl->fsrv.mem_limit << 20),
+               afl->fsrv.mem_limit - 1, doc_path);
 
         } else {
 
@@ -797,7 +803,7 @@ void pivot_inputs(afl_state_t *afl) {
 
 u32 find_start_position(afl_state_t *afl) {
 
-  static u8 tmp[4096];                   /* Ought to be enough for anybody. */
+  u8 tmp[4096] = {0};                    /* Ought to be enough for anybody. */
 
   u8 *fn, *off;
   s32 fd, i;
@@ -834,7 +840,7 @@ u32 find_start_position(afl_state_t *afl) {
 
 void find_timeout(afl_state_t *afl) {
 
-  static u8 tmp[4096];                   /* Ought to be enough for anybody. */
+  u8 tmp[4096] = {0};                    /* Ought to be enough for anybody. */
 
   u8 *fn, *off;
   s32 fd, i;
@@ -902,7 +908,7 @@ static u8 delete_files(u8 *path, u8 *prefix) {
 
 double get_runnable_processes(void) {
 
-  static double res;
+  double res = 0;
 
 #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \
     defined(__NetBSD__) || defined(__DragonFly__)
@@ -1049,7 +1055,7 @@ static void handle_existing_out_dir(afl_state_t *afl) {
 
     /* Let's see how much work is at stake. */
 
-    if (!afl->in_place_resume &&
+    if (!afl->in_place_resume && last_update > start_time2 &&
         last_update - start_time2 > OUTPUT_GRACE * 60) {
 
       SAYF("\n" cLRD "[-] " cRST
@@ -1787,7 +1793,7 @@ void fix_up_sync(afl_state_t *afl) {
 
 static void handle_resize(int sig) {
 
-  LIST_FOREACH(&afl_states, afl_state_t, { el->clear_screen; });
+  LIST_FOREACH(&afl_states, afl_state_t, { el->clear_screen = 1; });
 
 }
 
@@ -2008,7 +2014,7 @@ void check_binary(afl_state_t *afl, u8 *fname) {
 
   }
 
-  if (memmem(f_data, f_len, "libasan.so", 10) ||
+  if (memmem(f_data, f_len, "__asan_init", 11) ||
       memmem(f_data, f_len, "__msan_init", 11))
     afl->fsrv.uses_asan = 1;
 
@@ -2125,11 +2131,6 @@ void setup_signal_handlers(void) {
   sigaction(SIGINT, &sa, NULL);
   sigaction(SIGTERM, &sa, NULL);
 
-  /* Exec timeout notifications. */
-
-  sa.sa_handler = handle_timeout;
-  sigaction(SIGALRM, &sa, NULL);
-
   /* Window resize */
 
   sa.sa_handler = handle_resize;
diff --git a/src/afl-fuzz-misc.c b/src/afl-fuzz-misc.c
deleted file mode 100644
index 29e8bd82..00000000
--- a/src/afl-fuzz-misc.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
-   american fuzzy lop++ - misc stuffs from Mordor
-   ----------------------------------------------
-
-   Originally written by Michal Zalewski
-
-   Now maintained by Marc Heuse <mh@mh-sec.de>,
-                        Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
-                        Andrea Fioraldi <andreafioraldi@gmail.com>
-
-   Copyright 2016, 2017 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
-
-   This is the real deal: the program takes an instrumented binary and
-   attempts a variety of basic fuzzing tricks, paying close attention to
-   how they affect the execution path.
-
- */
-
-#include "afl-fuzz.h"
-
-/* Describe integer. Uses 12 cyclic static buffers for return values. The value
-   returned should be five characters or less for all the integers we reasonably
-   expect to see. */
-
-u8 *DI(u64 val) {
-
-  static u8 tmp[12][16];
-  static u8 cur;
-
-  cur = (cur + 1) % 12;
-
-#define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast)    \
-  do {                                                    \
-                                                          \
-    if (val < (_divisor) * (_limit_mult)) {               \
-                                                          \
-      sprintf(tmp[cur], _fmt, ((_cast)val) / (_divisor)); \
-      return tmp[cur];                                    \
-                                                          \
-    }                                                     \
-                                                          \
-  } 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(tmp[cur], "infty");
-  return tmp[cur];
-
-}
-
-/* Describe float. Similar to the above, except with a single
-   static buffer. */
-
-u8 *DF(double val) {
-
-  static u8 tmp[16];
-
-  if (val < 99.995) {
-
-    sprintf(tmp, "%0.02f", val);
-    return tmp;
-
-  }
-
-  if (val < 999.95) {
-
-    sprintf(tmp, "%0.01f", val);
-    return tmp;
-
-  }
-
-  return DI((u64)val);
-
-}
-
-/* Describe integer as memory size. */
-
-u8 *DMS(u64 val) {
-
-  static u8 tmp[12][16];
-  static u8 cur;
-
-  cur = (cur + 1) % 12;
-
-  /* 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(tmp[cur], "infty");
-  return tmp[cur];
-
-}
-
-/* Describe time delta. Returns one static buffer, 34 chars of less. */
-
-u8 *DTD(u64 cur_ms, u64 event_ms) {
-
-  static u8 tmp[64];
-  u64       delta;
-  s32       t_d, t_h, t_m, t_s;
-
-  if (!event_ms) return "none seen yet";
-
-  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;
-
-  sprintf(tmp, "%s days, %d hrs, %d min, %d sec", DI(t_d), t_h, t_m, t_s);
-  return tmp;
-
-}
-
diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c
index 9071404d..0ded4ba1 100644
--- a/src/afl-fuzz-mutators.c
+++ b/src/afl-fuzz-mutators.c
@@ -27,7 +27,7 @@
 
 void load_custom_mutator(afl_state_t *, const char *);
 #ifdef USE_PYTHON
-void load_custom_mutator_py(afl_state_t *, const char *);
+void load_custom_mutator_py(afl_state_t *, char *);
 #endif
 
 void setup_custom_mutator(afl_state_t *afl) {
@@ -59,10 +59,7 @@ void setup_custom_mutator(afl_state_t *afl) {
       FATAL(
           "MOpt and Python mutator are mutually exclusive. We accept pull "
           "requests that integrates MOpt with the optional mutators "
-          "(custom/radamsa/redquenn/...).");
-
-    if (init_py_module(afl, module_name))
-      FATAL("Failed to initialize Python module");
+          "(custom/radamsa/redqueen/...).");
 
     load_custom_mutator_py(afl, module_name);
 
@@ -79,18 +76,13 @@ void destroy_custom_mutator(afl_state_t *afl) {
 
   if (afl->mutator) {
 
+    afl->mutator->afl_custom_deinit(afl->mutator->data);
+
     if (afl->mutator->dh)
       dlclose(afl->mutator->dh);
-    else {
-
-      /* Python mutator */
-#ifdef USE_PYTHON
-      finalize_py_module(afl);
-#endif
-
-    }
 
     ck_free(afl->mutator);
+    afl->mutator = NULL;
 
   }
 
@@ -109,10 +101,13 @@ void load_custom_mutator(afl_state_t *afl, const char *fn) {
   afl->mutator->dh = dh;
 
   /* Mutator */
-  /* "afl_custom_init", optional for backward compatibility */
+  /* "afl_custom_init", required */
   afl->mutator->afl_custom_init = dlsym(dh, "afl_custom_init");
-  if (!afl->mutator->afl_custom_init)
-    WARNF("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.");
 
   /* "afl_custom_fuzz" or "afl_custom_mutator", required */
   afl->mutator->afl_custom_fuzz = dlsym(dh, "afl_custom_fuzz");
@@ -186,25 +181,24 @@ 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, UR(afl, 0xFFFFFFFF));
+    afl->mutator->afl_custom_init(afl, rand_below(afl, 0xFFFFFFFF));
 
 }
 
 u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
 
-  static u8 tmp[64];
-  static u8 clean_trace[MAP_SIZE];
-
   u8  needs_write = 0, fault = 0;
   u32 trim_exec = 0;
   u32 orig_len = q->len;
 
-  afl->stage_name = tmp;
+  u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
+
+  afl->stage_name = afl->stage_name_buf;
   afl->bytes_trim_in += q->len;
 
   /* Initialize trimming in the custom mutator */
   afl->stage_cur = 0;
-  afl->stage_max = afl->mutator->afl_custom_init_trim(afl, in_buf, q->len);
+  afl->stage_max = afl->mutator->afl_custom_init_trim(afl->mutator->data, in_buf, q->len);
 
   if (afl->not_on_tty && afl->debug)
     SAYF("[Custom Trimming] START: Max %d iterations, %u bytes", afl->stage_max,
@@ -212,7 +206,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
 
   while (afl->stage_cur < afl->stage_max) {
 
-    sprintf(tmp, "ptrim %s", DI(trim_exec));
+    sprintf(afl->stage_name_buf, "ptrim %s", u_stringify_int(val_buf, trim_exec));
 
     u32 cksum;
 
@@ -251,7 +245,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
       if (!needs_write) {
 
         needs_write = 1;
-        memcpy(clean_trace, afl->fsrv.trace_bits, MAP_SIZE);
+        memcpy(afl->clean_trace_custom, afl->fsrv.trace_bits, MAP_SIZE);
 
       }
 
@@ -299,7 +293,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
     ck_write(fd, in_buf, q->len, q->fname);
     close(fd);
 
-    memcpy(afl->fsrv.trace_bits, clean_trace, MAP_SIZE);
+    memcpy(afl->fsrv.trace_bits, afl->clean_trace_custom, MAP_SIZE);
     update_bitmap_score(afl, q);
 
   }
@@ -310,54 +304,3 @@ abort_trimming:
   return fault;
 
 }
-
-#ifdef USE_PYTHON
-void load_custom_mutator_py(afl_state_t *afl, const char *module_name) {
-
-  PyObject **py_functions = afl->py_functions;
-
-  afl->mutator = ck_alloc(sizeof(struct custom_mutator));
-
-  afl->mutator->name = module_name;
-  ACTF("Loading Python mutator library from '%s'...", module_name);
-
-  if (py_functions[PY_FUNC_INIT]) afl->mutator->afl_custom_init = init_py;
-
-  /* "afl_custom_fuzz" should not be NULL, but the interface of Python mutator
-     is quite different from the custom mutator. */
-  afl->mutator->afl_custom_fuzz = fuzz_py;
-
-  if (py_functions[PY_FUNC_PRE_SAVE])
-    afl->mutator->afl_custom_pre_save = pre_save_py;
-
-  if (py_functions[PY_FUNC_INIT_TRIM])
-    afl->mutator->afl_custom_init_trim = init_trim_py;
-
-  if (py_functions[PY_FUNC_POST_TRIM])
-    afl->mutator->afl_custom_post_trim = post_trim_py;
-
-  if (py_functions[PY_FUNC_TRIM]) afl->mutator->afl_custom_trim = trim_py;
-
-  if (py_functions[PY_FUNC_HAVOC_MUTATION])
-    afl->mutator->afl_custom_havoc_mutation = havoc_mutation_py;
-
-  if (py_functions[PY_FUNC_HAVOC_MUTATION_PROBABILITY])
-    afl->mutator->afl_custom_havoc_mutation_probability =
-        havoc_mutation_probability_py;
-
-  if (py_functions[PY_FUNC_QUEUE_GET])
-    afl->mutator->afl_custom_queue_get = queue_get_py;
-
-  if (py_functions[PY_FUNC_QUEUE_NEW_ENTRY])
-    afl->mutator->afl_custom_queue_new_entry = queue_new_entry_py;
-
-  OKF("Python mutator '%s' installed successfully.", module_name);
-
-  /* Initialize the custom mutator */
-  if (afl->mutator->afl_custom_init)
-    afl->mutator->afl_custom_init(afl, UR(afl, 0xFFFFFFFF));
-
-}
-
-#endif
-
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index 92210c8b..cc150cfe 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -31,7 +31,7 @@ int select_algorithm(afl_state_t *afl) {
 
   int i_puppet, j_puppet;
 
-  double sele = ((double)(UR(afl, 10000)) * 0.0001);
+  double sele = ((double)(rand_below(afl, 10000)) * 0.0001);
   j_puppet = 0;
   for (i_puppet = 0; i_puppet < operator_num; ++i_puppet) {
 
@@ -67,9 +67,9 @@ static u32 choose_block_len(afl_state_t *afl, u32 limit) {
   u32 min_value, max_value;
   u32 rlim = MIN(afl->queue_cycle, 3);
 
-  if (!afl->run_over10m) rlim = 1;
+  if (unlikely(!afl->run_over10m)) rlim = 1;
 
-  switch (UR(afl, rlim)) {
+  switch (rand_below(afl, rlim)) {
 
     case 0:
       min_value = 1;
@@ -83,7 +83,7 @@ static u32 choose_block_len(afl_state_t *afl, u32 limit) {
 
     default:
 
-      if (UR(afl, 10)) {
+      if (rand_below(afl, 10)) {
 
         min_value = HAVOC_BLK_MEDIUM;
         max_value = HAVOC_BLK_LARGE;
@@ -99,7 +99,7 @@ static u32 choose_block_len(afl_state_t *afl, u32 limit) {
 
   if (min_value >= limit) min_value = 1;
 
-  return min_value + UR(afl, MIN(max_value, limit) - min_value + 1);
+  return min_value + rand_below(afl, MIN(max_value, limit) - min_value + 1);
 
 }
 
@@ -356,7 +356,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
 
 #else
 
-  if (afl->mutator && afl->mutator->afl_custom_queue_get) {
+  if (unlikely(afl->mutator) && unlikely(afl->mutator->afl_custom_queue_get)) {
 
     /* The custom mutator will decide to skip this test case or not. */
 
@@ -365,7 +365,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
 
   }
 
-  if (afl->pending_favored) {
+  if (likely(afl->pending_favored)) {
 
     /* If we have any favored, non-fuzzed new arrivals in the queue,
        possibly skip to them at the expense of already-fuzzed or non-favored
@@ -373,7 +373,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
 
     if (((afl->queue_cur->was_fuzzed > 0 || afl->queue_cur->fuzz_level > 0) ||
          !afl->queue_cur->favored) &&
-        UR(afl, 100) < SKIP_TO_NEW_PROB)
+        rand_below(afl, 100) < SKIP_TO_NEW_PROB)
       return 1;
 
   } else if (!afl->dumb_mode && !afl->queue_cur->favored &&
@@ -387,11 +387,11 @@ u8 fuzz_one_original(afl_state_t *afl) {
     if (afl->queue_cycle > 1 &&
         (afl->queue_cur->fuzz_level == 0 || afl->queue_cur->was_fuzzed)) {
 
-      if (UR(afl, 100) < SKIP_NFAV_NEW_PROB) return 1;
+      if (rand_below(afl, 100) < SKIP_NFAV_NEW_PROB) return 1;
 
     } else {
 
-      if (UR(afl, 100) < SKIP_NFAV_OLD_PROB) return 1;
+      if (rand_below(afl, 100) < SKIP_NFAV_OLD_PROB) return 1;
 
     }
 
@@ -399,7 +399,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
 
 #endif                                                     /* ^IGNORE_FINDS */
 
-  if (afl->not_on_tty) {
+  if (unlikely(afl->not_on_tty)) {
 
     ACTF("Fuzzing test case #%u (%u total, %llu uniq crashes found)...",
          afl->current_entry, afl->queued_paths, afl->unique_crashes);
@@ -411,13 +411,13 @@ u8 fuzz_one_original(afl_state_t *afl) {
 
   fd = open(afl->queue_cur->fname, O_RDONLY);
 
-  if (fd < 0) PFATAL("Unable to open '%s'", afl->queue_cur->fname);
+  if (unlikely(fd < 0)) PFATAL("Unable to open '%s'", afl->queue_cur->fname);
 
   len = afl->queue_cur->len;
 
   orig_in = in_buf = mmap(0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
 
-  if (orig_in == MAP_FAILED)
+  if (unlikely(orig_in == MAP_FAILED))
     PFATAL("Unable to mmap '%s' with len %d", afl->queue_cur->fname, len);
 
   close(fd);
@@ -436,7 +436,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
    * CALIBRATION (only if failed earlier on) *
    *******************************************/
 
-  if (afl->queue_cur->cal_failed) {
+  if (unlikely(afl->queue_cur->cal_failed)) {
 
     u8 res = FAULT_TMOUT;
 
@@ -445,11 +445,12 @@ u8 fuzz_one_original(afl_state_t *afl) {
       res =
           calibrate_case(afl, afl->queue_cur, in_buf, afl->queue_cycle - 1, 0);
 
-      if (res == FAULT_ERROR) FATAL("Unable to execute target application");
+      if (unlikely(res == FAULT_ERROR))
+        FATAL("Unable to execute target application");
 
     }
 
-    if (afl->stop_soon || res != afl->crash_mode) {
+    if (unlikely(afl->stop_soon) || res != afl->crash_mode) {
 
       ++afl->cur_skipped_paths;
       goto abandon_entry;
@@ -466,9 +467,10 @@ u8 fuzz_one_original(afl_state_t *afl) {
 
     u8 res = trim_case(afl, afl->queue_cur, in_buf);
 
-    if (res == FAULT_ERROR) FATAL("Unable to execute target application");
+    if (unlikely(res == FAULT_ERROR))
+      FATAL("Unable to execute target application");
 
-    if (afl->stop_soon) {
+    if (unlikely(afl->stop_soon)) {
 
       ++afl->cur_skipped_paths;
       goto abandon_entry;
@@ -491,9 +493,9 @@ u8 fuzz_one_original(afl_state_t *afl) {
 
   orig_perf = perf_score = calculate_score(afl, afl->queue_cur);
 
-  if (perf_score == 0) goto abandon_entry;
+  if (unlikely(perf_score == 0)) goto abandon_entry;
 
-  if (afl->use_radamsa > 1) goto radamsa_stage;
+  if (unlikely(afl->use_radamsa > 1)) goto radamsa_stage;
 
   if (afl->shm.cmplog_mode) {
 
@@ -1401,7 +1403,7 @@ skip_interest:
          map. */
 
       if ((afl->extras_cnt > MAX_DET_EXTRAS &&
-           UR(afl, afl->extras_cnt) >= MAX_DET_EXTRAS) ||
+           rand_below(afl, afl->extras_cnt) >= MAX_DET_EXTRAS) ||
           afl->extras[j].len > len - i ||
           !memcmp(afl->extras[j].data, out_buf + i, afl->extras[j].len) ||
           !memchr(eff_map + EFF_APOS(i), 1,
@@ -1549,8 +1551,8 @@ custom_mutator_stage:
    * CUSTOM MUTATORS *
    *******************/
 
-  if (!afl->mutator) goto havoc_stage;
-  if (!afl->mutator->afl_custom_fuzz) goto havoc_stage;
+  if (likely(!afl->mutator)) goto havoc_stage;
+  if (likely(!afl->mutator->afl_custom_fuzz)) goto havoc_stage;
 
   afl->stage_name = "custom mutator";
   afl->stage_short = "custom";
@@ -1573,7 +1575,7 @@ custom_mutator_stage:
     /* Pick a random other queue entry for passing to external API */
     do {
 
-      tid = UR(afl, afl->queued_paths);
+      tid = rand_below(afl, afl->queued_paths);
 
     } while (tid == afl->current_entry && afl->queued_paths > 1);
 
@@ -1603,7 +1605,7 @@ custom_mutator_stage:
 
     /* Read the additional testcase into a new buffer. */
     fd = open(target->fname, O_RDONLY);
-    if (fd < 0) PFATAL("Unable to open '%s'", target->fname);
+    if (unlikely(fd < 0)) PFATAL("Unable to open '%s'", target->fname);
     new_buf = ck_alloc_nozero(target->len);
     ck_read(fd, new_buf, target->len, target->fname);
     close(fd);
@@ -1649,7 +1651,7 @@ custom_mutator_stage:
   afl->stage_finds[STAGE_CUSTOM_MUTATOR] += new_hit_cnt - orig_hit_cnt;
   afl->stage_cycles[STAGE_CUSTOM_MUTATOR] += afl->stage_max;
 
-  if (afl->custom_only) {
+  if (likely(afl->custom_only)) {
 
     /* Skip other stages */
     ret_val = 0;
@@ -1679,8 +1681,8 @@ havoc_stage:
 
     perf_score = orig_perf;
 
-    snprintf(afl->stage_name_buf64, 64, "splice %u", splice_cycle);
-    afl->stage_name = afl->stage_name_buf64;
+    snprintf(afl->stage_name_buf, STAGE_BUF_SIZE, "splice %u", splice_cycle);
+    afl->stage_name = afl->stage_name_buf;
     afl->stage_short = "splice";
     afl->stage_max = SPLICE_HAVOC * perf_score / afl->havoc_div / 100;
 
@@ -1713,34 +1715,35 @@ havoc_stage:
 
   for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) {
 
-    u32 use_stacking = 1 << (1 + UR(afl, HAVOC_STACK_POW2));
+    u32 use_stacking = 1 << (1 + rand_below(afl, HAVOC_STACK_POW2));
 
     afl->stage_cur_val = use_stacking;
 
     for (i = 0; i < use_stacking; ++i) {
 
-      if (stacked_custom && UR(afl, 100) < stacked_custom_prob) {
+      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);
 
       }
 
-      switch (UR(afl, 15 + ((afl->extras_cnt + afl->a_extras_cnt) ? 2 : 0))) {
+      switch (rand_below(
+          afl, 15 + ((afl->extras_cnt + afl->a_extras_cnt) ? 2 : 0))) {
 
         case 0:
 
           /* Flip a single bit somewhere. Spooky! */
 
-          FLIP_BIT(out_buf, UR(afl, temp_len << 3));
+          FLIP_BIT(out_buf, rand_below(afl, temp_len << 3));
           break;
 
         case 1:
 
           /* Set byte to interesting value. */
 
-          out_buf[UR(afl, temp_len)] =
-              interesting_8[UR(afl, sizeof(interesting_8))];
+          out_buf[rand_below(afl, temp_len)] =
+              interesting_8[rand_below(afl, sizeof(interesting_8))];
           break;
 
         case 2:
@@ -1749,15 +1752,15 @@ havoc_stage:
 
           if (temp_len < 2) break;
 
-          if (UR(afl, 2)) {
+          if (rand_below(afl, 2)) {
 
-            *(u16 *)(out_buf + UR(afl, temp_len - 1)) =
-                interesting_16[UR(afl, sizeof(interesting_16) >> 1)];
+            *(u16 *)(out_buf + rand_below(afl, temp_len - 1)) =
+                interesting_16[rand_below(afl, sizeof(interesting_16) >> 1)];
 
           } else {
 
-            *(u16 *)(out_buf + UR(afl, temp_len - 1)) =
-                SWAP16(interesting_16[UR(afl, sizeof(interesting_16) >> 1)]);
+            *(u16 *)(out_buf + rand_below(afl, temp_len - 1)) = SWAP16(
+                interesting_16[rand_below(afl, sizeof(interesting_16) >> 1)]);
 
           }
 
@@ -1769,15 +1772,15 @@ havoc_stage:
 
           if (temp_len < 4) break;
 
-          if (UR(afl, 2)) {
+          if (rand_below(afl, 2)) {
 
-            *(u32 *)(out_buf + UR(afl, temp_len - 3)) =
-                interesting_32[UR(afl, sizeof(interesting_32) >> 2)];
+            *(u32 *)(out_buf + rand_below(afl, temp_len - 3)) =
+                interesting_32[rand_below(afl, sizeof(interesting_32) >> 2)];
 
           } else {
 
-            *(u32 *)(out_buf + UR(afl, temp_len - 3)) =
-                SWAP32(interesting_32[UR(afl, sizeof(interesting_32) >> 2)]);
+            *(u32 *)(out_buf + rand_below(afl, temp_len - 3)) = SWAP32(
+                interesting_32[rand_below(afl, sizeof(interesting_32) >> 2)]);
 
           }
 
@@ -1787,14 +1790,14 @@ havoc_stage:
 
           /* Randomly subtract from byte. */
 
-          out_buf[UR(afl, temp_len)] -= 1 + UR(afl, ARITH_MAX);
+          out_buf[rand_below(afl, temp_len)] -= 1 + rand_below(afl, ARITH_MAX);
           break;
 
         case 5:
 
           /* Randomly add to byte. */
 
-          out_buf[UR(afl, temp_len)] += 1 + UR(afl, ARITH_MAX);
+          out_buf[rand_below(afl, temp_len)] += 1 + rand_below(afl, ARITH_MAX);
           break;
 
         case 6:
@@ -1803,16 +1806,16 @@ havoc_stage:
 
           if (temp_len < 2) break;
 
-          if (UR(afl, 2)) {
+          if (rand_below(afl, 2)) {
 
-            u32 pos = UR(afl, temp_len - 1);
+            u32 pos = rand_below(afl, temp_len - 1);
 
-            *(u16 *)(out_buf + pos) -= 1 + UR(afl, ARITH_MAX);
+            *(u16 *)(out_buf + pos) -= 1 + rand_below(afl, ARITH_MAX);
 
           } else {
 
-            u32 pos = UR(afl, temp_len - 1);
-            u16 num = 1 + UR(afl, ARITH_MAX);
+            u32 pos = rand_below(afl, temp_len - 1);
+            u16 num = 1 + rand_below(afl, ARITH_MAX);
 
             *(u16 *)(out_buf + pos) =
                 SWAP16(SWAP16(*(u16 *)(out_buf + pos)) - num);
@@ -1827,16 +1830,16 @@ havoc_stage:
 
           if (temp_len < 2) break;
 
-          if (UR(afl, 2)) {
+          if (rand_below(afl, 2)) {
 
-            u32 pos = UR(afl, temp_len - 1);
+            u32 pos = rand_below(afl, temp_len - 1);
 
-            *(u16 *)(out_buf + pos) += 1 + UR(afl, ARITH_MAX);
+            *(u16 *)(out_buf + pos) += 1 + rand_below(afl, ARITH_MAX);
 
           } else {
 
-            u32 pos = UR(afl, temp_len - 1);
-            u16 num = 1 + UR(afl, ARITH_MAX);
+            u32 pos = rand_below(afl, temp_len - 1);
+            u16 num = 1 + rand_below(afl, ARITH_MAX);
 
             *(u16 *)(out_buf + pos) =
                 SWAP16(SWAP16(*(u16 *)(out_buf + pos)) + num);
@@ -1851,16 +1854,16 @@ havoc_stage:
 
           if (temp_len < 4) break;
 
-          if (UR(afl, 2)) {
+          if (rand_below(afl, 2)) {
 
-            u32 pos = UR(afl, temp_len - 3);
+            u32 pos = rand_below(afl, temp_len - 3);
 
-            *(u32 *)(out_buf + pos) -= 1 + UR(afl, ARITH_MAX);
+            *(u32 *)(out_buf + pos) -= 1 + rand_below(afl, ARITH_MAX);
 
           } else {
 
-            u32 pos = UR(afl, temp_len - 3);
-            u32 num = 1 + UR(afl, ARITH_MAX);
+            u32 pos = rand_below(afl, temp_len - 3);
+            u32 num = 1 + rand_below(afl, ARITH_MAX);
 
             *(u32 *)(out_buf + pos) =
                 SWAP32(SWAP32(*(u32 *)(out_buf + pos)) - num);
@@ -1875,16 +1878,16 @@ havoc_stage:
 
           if (temp_len < 4) break;
 
-          if (UR(afl, 2)) {
+          if (rand_below(afl, 2)) {
 
-            u32 pos = UR(afl, temp_len - 3);
+            u32 pos = rand_below(afl, temp_len - 3);
 
-            *(u32 *)(out_buf + pos) += 1 + UR(afl, ARITH_MAX);
+            *(u32 *)(out_buf + pos) += 1 + rand_below(afl, ARITH_MAX);
 
           } else {
 
-            u32 pos = UR(afl, temp_len - 3);
-            u32 num = 1 + UR(afl, ARITH_MAX);
+            u32 pos = rand_below(afl, temp_len - 3);
+            u32 num = 1 + rand_below(afl, ARITH_MAX);
 
             *(u32 *)(out_buf + pos) =
                 SWAP32(SWAP32(*(u32 *)(out_buf + pos)) + num);
@@ -1899,7 +1902,7 @@ havoc_stage:
              why not. We use XOR with 1-255 to eliminate the
              possibility of a no-op. */
 
-          out_buf[UR(afl, temp_len)] ^= 1 + UR(afl, 255);
+          out_buf[rand_below(afl, temp_len)] ^= 1 + rand_below(afl, 255);
           break;
 
         case 11 ... 12: {
@@ -1916,7 +1919,7 @@ havoc_stage:
 
           del_len = choose_block_len(afl, temp_len - 1);
 
-          del_from = UR(afl, temp_len - del_len + 1);
+          del_from = rand_below(afl, temp_len - del_len + 1);
 
           memmove(out_buf + del_from, out_buf + del_from + del_len,
                   temp_len - del_from - del_len);
@@ -1933,14 +1936,14 @@ havoc_stage:
 
             /* Clone bytes (75%) or insert a block of constant bytes (25%). */
 
-            u8  actually_clone = UR(afl, 4);
+            u8  actually_clone = rand_below(afl, 4);
             u32 clone_from, clone_to, clone_len;
             u8 *new_buf;
 
             if (actually_clone) {
 
               clone_len = choose_block_len(afl, temp_len);
-              clone_from = UR(afl, temp_len - clone_len + 1);
+              clone_from = rand_below(afl, temp_len - clone_len + 1);
 
             } else {
 
@@ -1949,7 +1952,7 @@ havoc_stage:
 
             }
 
-            clone_to = UR(afl, temp_len);
+            clone_to = rand_below(afl, temp_len);
 
             new_buf = ck_alloc_nozero(temp_len + clone_len);
 
@@ -1963,7 +1966,8 @@ havoc_stage:
               memcpy(new_buf + clone_to, out_buf + clone_from, clone_len);
             else
               memset(new_buf + clone_to,
-                     UR(afl, 2) ? UR(afl, 256) : out_buf[UR(afl, temp_len)],
+                     rand_below(afl, 2) ? rand_below(afl, 256)
+                                        : out_buf[rand_below(afl, temp_len)],
                      clone_len);
 
             /* Tail */
@@ -1989,10 +1993,10 @@ havoc_stage:
 
           copy_len = choose_block_len(afl, temp_len - 1);
 
-          copy_from = UR(afl, temp_len - copy_len + 1);
-          copy_to = UR(afl, temp_len - copy_len + 1);
+          copy_from = rand_below(afl, temp_len - copy_len + 1);
+          copy_to = rand_below(afl, temp_len - copy_len + 1);
 
-          if (UR(afl, 4)) {
+          if (rand_below(afl, 4)) {
 
             if (copy_from != copy_to)
               memmove(out_buf + copy_to, out_buf + copy_from, copy_len);
@@ -2000,7 +2004,8 @@ havoc_stage:
           } else
 
             memset(out_buf + copy_to,
-                   UR(afl, 2) ? UR(afl, 256) : out_buf[UR(afl, temp_len)],
+                   rand_below(afl, 2) ? rand_below(afl, 256)
+                                      : out_buf[rand_below(afl, temp_len)],
                    copy_len);
 
           break;
@@ -2014,18 +2019,18 @@ havoc_stage:
 
           /* Overwrite bytes with an extra. */
 
-          if (!afl->extras_cnt || (afl->a_extras_cnt && UR(afl, 2))) {
+          if (!afl->extras_cnt || (afl->a_extras_cnt && rand_below(afl, 2))) {
 
             /* No user-specified extras or odds in our favor. Let's use an
                auto-detected one. */
 
-            u32 use_extra = UR(afl, afl->a_extras_cnt);
+            u32 use_extra = rand_below(afl, afl->a_extras_cnt);
             u32 extra_len = afl->a_extras[use_extra].len;
             u32 insert_at;
 
             if (extra_len > temp_len) break;
 
-            insert_at = UR(afl, temp_len - extra_len + 1);
+            insert_at = rand_below(afl, temp_len - extra_len + 1);
             memcpy(out_buf + insert_at, afl->a_extras[use_extra].data,
                    extra_len);
 
@@ -2033,13 +2038,13 @@ havoc_stage:
 
             /* No auto extras or odds in our favor. Use the dictionary. */
 
-            u32 use_extra = UR(afl, afl->extras_cnt);
+            u32 use_extra = rand_below(afl, afl->extras_cnt);
             u32 extra_len = afl->extras[use_extra].len;
             u32 insert_at;
 
             if (extra_len > temp_len) break;
 
-            insert_at = UR(afl, temp_len - extra_len + 1);
+            insert_at = rand_below(afl, temp_len - extra_len + 1);
             memcpy(out_buf + insert_at, afl->extras[use_extra].data, extra_len);
 
           }
@@ -2050,15 +2055,15 @@ havoc_stage:
 
         case 16: {
 
-          u32 use_extra, extra_len, insert_at = UR(afl, temp_len + 1);
+          u32 use_extra, extra_len, insert_at = rand_below(afl, temp_len + 1);
           u8 *new_buf;
 
           /* Insert an extra. Do the same dice-rolling stuff as for the
              previous case. */
 
-          if (!afl->extras_cnt || (afl->a_extras_cnt && UR(afl, 2))) {
+          if (!afl->extras_cnt || (afl->a_extras_cnt && rand_below(afl, 2))) {
 
-            use_extra = UR(afl, afl->a_extras_cnt);
+            use_extra = rand_below(afl, afl->a_extras_cnt);
             extra_len = afl->a_extras[use_extra].len;
 
             if (temp_len + extra_len >= MAX_FILE) break;
@@ -2074,7 +2079,7 @@ havoc_stage:
 
           } else {
 
-            use_extra = UR(afl, afl->extras_cnt);
+            use_extra = rand_below(afl, afl->extras_cnt);
             extra_len = afl->extras[use_extra].len;
 
             if (temp_len + extra_len >= MAX_FILE) break;
@@ -2182,7 +2187,7 @@ retry_splicing:
 
     do {
 
-      tid = UR(afl, afl->queued_paths);
+      tid = rand_below(afl, afl->queued_paths);
 
     } while (tid == afl->current_entry);
 
@@ -2214,7 +2219,7 @@ retry_splicing:
 
     fd = open(target->fname, O_RDONLY);
 
-    if (fd < 0) PFATAL("Unable to open '%s'", target->fname);
+    if (unlikely(fd < 0)) PFATAL("Unable to open '%s'", target->fname);
 
     new_buf = ck_alloc_nozero(target->len);
 
@@ -2237,7 +2242,7 @@ retry_splicing:
 
     /* Split somewhere between the first and last differing byte. */
 
-    split_at = f_diff + UR(afl, l_diff - f_diff);
+    split_at = f_diff + rand_below(afl, l_diff - f_diff);
 
     /* Do the thing. */
 
@@ -2263,7 +2268,7 @@ retry_splicing:
 
 radamsa_stage:
 
-  if (!afl->use_radamsa || !afl->radamsa_mutate_ptr) goto abandon_entry;
+  if (likely(!afl->use_radamsa || !afl->radamsa_mutate_ptr)) goto abandon_entry;
 
   afl->stage_name = "radamsa";
   afl->stage_short = "radamsa";
@@ -2391,7 +2396,7 @@ u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
        cases. */
 
     if ((afl->queue_cur->was_fuzzed || !afl->queue_cur->favored) &&
-        UR(afl, 100) < SKIP_TO_NEW_PROB)
+        rand_below(afl, 100) < SKIP_TO_NEW_PROB)
       return 1;
 
   } else if (!afl->dumb_mode && !afl->queue_cur->favored &&
@@ -2404,11 +2409,11 @@ u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
 
     if (afl->queue_cycle > 1 && !afl->queue_cur->was_fuzzed) {
 
-      if (UR(afl, 100) < SKIP_NFAV_NEW_PROB) return 1;
+      if (rand_below(afl, 100) < SKIP_NFAV_NEW_PROB) return 1;
 
     } else {
 
-      if (UR(afl, 100) < SKIP_NFAV_OLD_PROB) return 1;
+      if (rand_below(afl, 100) < SKIP_NFAV_OLD_PROB) return 1;
 
     }
 
@@ -3407,7 +3412,7 @@ skip_interest:
          map. */
 
       if ((afl->extras_cnt > MAX_DET_EXTRAS &&
-           UR(afl, afl->extras_cnt) >= MAX_DET_EXTRAS) ||
+           rand_below(afl, afl->extras_cnt) >= MAX_DET_EXTRAS) ||
           afl->extras[j].len > len - i ||
           !memcmp(afl->extras[j].data, out_buf + i, afl->extras[j].len) ||
           !memchr(eff_map + EFF_APOS(i), 1,
@@ -3573,9 +3578,9 @@ pacemaker_fuzzing:
 
     perf_score = orig_perf;
 
-    snprintf(afl->stage_name_buf64, 64, MOpt_globals.splice_stageformat,
-             splice_cycle);
-    afl->stage_name = afl->stage_name_buf64;
+    snprintf(afl->stage_name_buf, STAGE_BUF_SIZE,
+             MOpt_globals.splice_stageformat, splice_cycle);
+    afl->stage_name = afl->stage_name_buf;
     afl->stage_short = MOpt_globals.splice_stagenameshort;
     afl->stage_max = SPLICE_HAVOC * perf_score / afl->havoc_div / 100;
 
@@ -3594,7 +3599,8 @@ pacemaker_fuzzing:
         afl->orig_hit_cnt_puppet = afl->queued_paths + afl->unique_crashes;
         afl->last_limit_time_start = get_cur_time();
         afl->SPLICE_CYCLES_puppet =
-            (UR(afl, SPLICE_CYCLES_puppet_up - SPLICE_CYCLES_puppet_low + 1) +
+            (rand_below(
+                 afl, SPLICE_CYCLES_puppet_up - SPLICE_CYCLES_puppet_low + 1) +
              SPLICE_CYCLES_puppet_low);
 
       }
@@ -3623,9 +3629,9 @@ pacemaker_fuzzing:
       } else {
 
         perf_score = orig_perf;
-        snprintf(afl->stage_name_buf64, 64, MOpt_globals.splice_stageformat,
-                 splice_cycle);
-        afl->stage_name = afl->stage_name_buf64;
+        snprintf(afl->stage_name_buf, STAGE_BUF_SIZE,
+                 MOpt_globals.splice_stageformat, splice_cycle);
+        afl->stage_name = afl->stage_name_buf;
         afl->stage_short = MOpt_globals.splice_stagenameshort;
         afl->stage_max = SPLICE_HAVOC * perf_score / afl->havoc_div / 100;
 
@@ -3642,7 +3648,7 @@ pacemaker_fuzzing:
       for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max;
            ++afl->stage_cur) {
 
-        u32 use_stacking = 1 << (1 + UR(afl, HAVOC_STACK_POW2));
+        u32 use_stacking = 1 << (1 + rand_below(afl, HAVOC_STACK_POW2));
 
         afl->stage_cur_val = use_stacking;
 
@@ -3658,13 +3664,13 @@ pacemaker_fuzzing:
 
             case 0:
               /* Flip a single bit somewhere. Spooky! */
-              FLIP_BIT(out_buf, UR(afl, temp_len << 3));
+              FLIP_BIT(out_buf, rand_below(afl, temp_len << 3));
               MOpt_globals.cycles_v2[STAGE_FLIP1] += 1;
               break;
 
             case 1:
               if (temp_len < 2) break;
-              temp_len_puppet = UR(afl, (temp_len << 3) - 1);
+              temp_len_puppet = rand_below(afl, (temp_len << 3) - 1);
               FLIP_BIT(out_buf, temp_len_puppet);
               FLIP_BIT(out_buf, temp_len_puppet + 1);
               MOpt_globals.cycles_v2[STAGE_FLIP2] += 1;
@@ -3672,7 +3678,7 @@ pacemaker_fuzzing:
 
             case 2:
               if (temp_len < 2) break;
-              temp_len_puppet = UR(afl, (temp_len << 3) - 3);
+              temp_len_puppet = rand_below(afl, (temp_len << 3) - 3);
               FLIP_BIT(out_buf, temp_len_puppet);
               FLIP_BIT(out_buf, temp_len_puppet + 1);
               FLIP_BIT(out_buf, temp_len_puppet + 2);
@@ -3682,55 +3688,57 @@ pacemaker_fuzzing:
 
             case 3:
               if (temp_len < 4) break;
-              out_buf[UR(afl, temp_len)] ^= 0xFF;
+              out_buf[rand_below(afl, temp_len)] ^= 0xFF;
               MOpt_globals.cycles_v2[STAGE_FLIP8] += 1;
               break;
 
             case 4:
               if (temp_len < 8) break;
-              *(u16 *)(out_buf + UR(afl, temp_len - 1)) ^= 0xFFFF;
+              *(u16 *)(out_buf + rand_below(afl, temp_len - 1)) ^= 0xFFFF;
               MOpt_globals.cycles_v2[STAGE_FLIP16] += 1;
               break;
 
             case 5:
               if (temp_len < 8) break;
-              *(u32 *)(out_buf + UR(afl, temp_len - 3)) ^= 0xFFFFFFFF;
+              *(u32 *)(out_buf + rand_below(afl, temp_len - 3)) ^= 0xFFFFFFFF;
               MOpt_globals.cycles_v2[STAGE_FLIP32] += 1;
               break;
 
             case 6:
-              out_buf[UR(afl, temp_len)] -= 1 + UR(afl, ARITH_MAX);
-              out_buf[UR(afl, temp_len)] += 1 + UR(afl, ARITH_MAX);
+              out_buf[rand_below(afl, temp_len)] -=
+                  1 + rand_below(afl, ARITH_MAX);
+              out_buf[rand_below(afl, temp_len)] +=
+                  1 + rand_below(afl, ARITH_MAX);
               MOpt_globals.cycles_v2[STAGE_ARITH8] += 1;
               break;
 
             case 7:
               /* Randomly subtract from word, random endian. */
               if (temp_len < 8) break;
-              if (UR(afl, 2)) {
+              if (rand_below(afl, 2)) {
 
-                u32 pos = UR(afl, temp_len - 1);
-                *(u16 *)(out_buf + pos) -= 1 + UR(afl, ARITH_MAX);
+                u32 pos = rand_below(afl, temp_len - 1);
+                *(u16 *)(out_buf + pos) -= 1 + rand_below(afl, ARITH_MAX);
 
               } else {
 
-                u32 pos = UR(afl, temp_len - 1);
-                u16 num = 1 + UR(afl, ARITH_MAX);
+                u32 pos = rand_below(afl, temp_len - 1);
+                u16 num = 1 + rand_below(afl, ARITH_MAX);
                 *(u16 *)(out_buf + pos) =
                     SWAP16(SWAP16(*(u16 *)(out_buf + pos)) - num);
 
               }
 
               /* Randomly add to word, random endian. */
-              if (UR(afl, 2)) {
+              if (rand_below(afl, 2)) {
 
-                u32 pos = UR(afl, temp_len - 1);
-                *(u16 *)(out_buf + pos) += 1 + UR(afl, ARITH_MAX);
+                u32 pos = rand_below(afl, temp_len - 1);
+                *(u16 *)(out_buf + pos) += 1 + rand_below(afl, ARITH_MAX);
 
               } else {
 
-                u32 pos = UR(afl, temp_len - 1);
-                u16 num = 1 + UR(afl, ARITH_MAX);
+                u32 pos = rand_below(afl, temp_len - 1);
+                u16 num = 1 + rand_below(afl, ARITH_MAX);
                 *(u16 *)(out_buf + pos) =
                     SWAP16(SWAP16(*(u16 *)(out_buf + pos)) + num);
 
@@ -3742,15 +3750,15 @@ pacemaker_fuzzing:
             case 8:
               /* Randomly subtract from dword, random endian. */
               if (temp_len < 8) break;
-              if (UR(afl, 2)) {
+              if (rand_below(afl, 2)) {
 
-                u32 pos = UR(afl, temp_len - 3);
-                *(u32 *)(out_buf + pos) -= 1 + UR(afl, ARITH_MAX);
+                u32 pos = rand_below(afl, temp_len - 3);
+                *(u32 *)(out_buf + pos) -= 1 + rand_below(afl, ARITH_MAX);
 
               } else {
 
-                u32 pos = UR(afl, temp_len - 3);
-                u32 num = 1 + UR(afl, ARITH_MAX);
+                u32 pos = rand_below(afl, temp_len - 3);
+                u32 num = 1 + rand_below(afl, ARITH_MAX);
                 *(u32 *)(out_buf + pos) =
                     SWAP32(SWAP32(*(u32 *)(out_buf + pos)) - num);
 
@@ -3758,15 +3766,15 @@ pacemaker_fuzzing:
 
               /* Randomly add to dword, random endian. */
               // if (temp_len < 4) break;
-              if (UR(afl, 2)) {
+              if (rand_below(afl, 2)) {
 
-                u32 pos = UR(afl, temp_len - 3);
-                *(u32 *)(out_buf + pos) += 1 + UR(afl, ARITH_MAX);
+                u32 pos = rand_below(afl, temp_len - 3);
+                *(u32 *)(out_buf + pos) += 1 + rand_below(afl, ARITH_MAX);
 
               } else {
 
-                u32 pos = UR(afl, temp_len - 3);
-                u32 num = 1 + UR(afl, ARITH_MAX);
+                u32 pos = rand_below(afl, temp_len - 3);
+                u32 num = 1 + rand_below(afl, ARITH_MAX);
                 *(u32 *)(out_buf + pos) =
                     SWAP32(SWAP32(*(u32 *)(out_buf + pos)) + num);
 
@@ -3778,23 +3786,25 @@ pacemaker_fuzzing:
             case 9:
               /* Set byte to interesting value. */
               if (temp_len < 4) break;
-              out_buf[UR(afl, temp_len)] =
-                  interesting_8[UR(afl, sizeof(interesting_8))];
+              out_buf[rand_below(afl, temp_len)] =
+                  interesting_8[rand_below(afl, sizeof(interesting_8))];
               MOpt_globals.cycles_v2[STAGE_INTEREST8] += 1;
               break;
 
             case 10:
               /* Set word to interesting value, randomly choosing endian. */
               if (temp_len < 8) break;
-              if (UR(afl, 2)) {
+              if (rand_below(afl, 2)) {
 
-                *(u16 *)(out_buf + UR(afl, temp_len - 1)) =
-                    interesting_16[UR(afl, sizeof(interesting_16) >> 1)];
+                *(u16 *)(out_buf + rand_below(afl, temp_len - 1)) =
+                    interesting_16[rand_below(afl,
+                                              sizeof(interesting_16) >> 1)];
 
               } else {
 
-                *(u16 *)(out_buf + UR(afl, temp_len - 1)) = SWAP16(
-                    interesting_16[UR(afl, sizeof(interesting_16) >> 1)]);
+                *(u16 *)(out_buf + rand_below(afl, temp_len - 1)) =
+                    SWAP16(interesting_16[rand_below(
+                        afl, sizeof(interesting_16) >> 1)]);
 
               }
 
@@ -3806,15 +3816,17 @@ pacemaker_fuzzing:
 
               if (temp_len < 8) break;
 
-              if (UR(afl, 2)) {
+              if (rand_below(afl, 2)) {
 
-                *(u32 *)(out_buf + UR(afl, temp_len - 3)) =
-                    interesting_32[UR(afl, sizeof(interesting_32) >> 2)];
+                *(u32 *)(out_buf + rand_below(afl, temp_len - 3)) =
+                    interesting_32[rand_below(afl,
+                                              sizeof(interesting_32) >> 2)];
 
               } else {
 
-                *(u32 *)(out_buf + UR(afl, temp_len - 3)) = SWAP32(
-                    interesting_32[UR(afl, sizeof(interesting_32) >> 2)]);
+                *(u32 *)(out_buf + rand_below(afl, temp_len - 3)) =
+                    SWAP32(interesting_32[rand_below(
+                        afl, sizeof(interesting_32) >> 2)]);
 
               }
 
@@ -3827,7 +3839,7 @@ pacemaker_fuzzing:
                  why not. We use XOR with 1-255 to eliminate the
                  possibility of a no-op. */
 
-              out_buf[UR(afl, temp_len)] ^= 1 + UR(afl, 255);
+              out_buf[rand_below(afl, temp_len)] ^= 1 + rand_below(afl, 255);
               MOpt_globals.cycles_v2[STAGE_RANDOMBYTE] += 1;
               break;
 
@@ -3845,7 +3857,7 @@ pacemaker_fuzzing:
 
               del_len = choose_block_len(afl, temp_len - 1);
 
-              del_from = UR(afl, temp_len - del_len + 1);
+              del_from = rand_below(afl, temp_len - del_len + 1);
 
               memmove(out_buf + del_from, out_buf + del_from + del_len,
                       temp_len - del_from - del_len);
@@ -3863,14 +3875,14 @@ pacemaker_fuzzing:
                 /* Clone bytes (75%) or insert a block of constant bytes (25%).
                  */
 
-                u8  actually_clone = UR(afl, 4);
+                u8  actually_clone = rand_below(afl, 4);
                 u32 clone_from, clone_to, clone_len;
                 u8 *new_buf;
 
                 if (actually_clone) {
 
                   clone_len = choose_block_len(afl, temp_len);
-                  clone_from = UR(afl, temp_len - clone_len + 1);
+                  clone_from = rand_below(afl, temp_len - clone_len + 1);
 
                 } else {
 
@@ -3879,7 +3891,7 @@ pacemaker_fuzzing:
 
                 }
 
-                clone_to = UR(afl, temp_len);
+                clone_to = rand_below(afl, temp_len);
 
                 new_buf = ck_alloc_nozero(temp_len + clone_len);
 
@@ -3893,7 +3905,9 @@ pacemaker_fuzzing:
                   memcpy(new_buf + clone_to, out_buf + clone_from, clone_len);
                 else
                   memset(new_buf + clone_to,
-                         UR(afl, 2) ? UR(afl, 256) : out_buf[UR(afl, temp_len)],
+                         rand_below(afl, 2)
+                             ? rand_below(afl, 256)
+                             : out_buf[rand_below(afl, temp_len)],
                          clone_len);
 
                 /* Tail */
@@ -3920,10 +3934,10 @@ pacemaker_fuzzing:
 
               copy_len = choose_block_len(afl, temp_len - 1);
 
-              copy_from = UR(afl, temp_len - copy_len + 1);
-              copy_to = UR(afl, temp_len - copy_len + 1);
+              copy_from = rand_below(afl, temp_len - copy_len + 1);
+              copy_to = rand_below(afl, temp_len - copy_len + 1);
 
-              if (UR(afl, 4)) {
+              if (rand_below(afl, 4)) {
 
                 if (copy_from != copy_to)
                   memmove(out_buf + copy_to, out_buf + copy_from, copy_len);
@@ -3931,7 +3945,8 @@ pacemaker_fuzzing:
               } else
 
                 memset(out_buf + copy_to,
-                       UR(afl, 2) ? UR(afl, 256) : out_buf[UR(afl, temp_len)],
+                       rand_below(afl, 2) ? rand_below(afl, 256)
+                                          : out_buf[rand_below(afl, temp_len)],
                        copy_len);
               MOpt_globals.cycles_v2[STAGE_OverWrite75] += 1;
               break;
@@ -4041,7 +4056,7 @@ pacemaker_fuzzing:
 
         do {
 
-          tid = UR(afl, afl->queued_paths);
+          tid = rand_below(afl, afl->queued_paths);
 
         } while (tid == afl->current_entry);
 
@@ -4096,7 +4111,7 @@ pacemaker_fuzzing:
 
         /* Split somewhere between the first and last differing byte. */
 
-        split_at = f_diff + UR(afl, l_diff - f_diff);
+        split_at = f_diff + rand_below(afl, l_diff - f_diff);
 
         /* Do the thing. */
 
@@ -4120,7 +4135,8 @@ pacemaker_fuzzing:
 
       if (splice_cycle >= afl->SPLICE_CYCLES_puppet)
         afl->SPLICE_CYCLES_puppet =
-            (UR(afl, SPLICE_CYCLES_puppet_up - SPLICE_CYCLES_puppet_low + 1) +
+            (rand_below(
+                 afl, SPLICE_CYCLES_puppet_up - SPLICE_CYCLES_puppet_low + 1) +
              SPLICE_CYCLES_puppet_low);
 
       afl->splicing_with = -1;
diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c
index 595c1ed0..d3027d2b 100644
--- a/src/afl-fuzz-python.c
+++ b/src/afl-fuzz-python.c
@@ -28,9 +28,84 @@
 /* Python stuff */
 #ifdef USE_PYTHON
 
-int init_py_module(afl_state_t *afl, u8 *module_name) {
+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) {
+
+  size_t    mutated_size;
+  PyObject *py_args, *py_value;
+  py_args = PyTuple_New(3);
+
+  /* buf */
+  py_value = PyByteArray_FromStringAndSize(*buf, buf_size);
+  if (!py_value) {
+
+    Py_DECREF(py_args);
+    FATAL("Failed to convert arguments");
+
+  }
+
+  PyTuple_SetItem(py_args, 0, py_value);
+
+  /* add_buf */
+  py_value = PyByteArray_FromStringAndSize(add_buf, add_buf_size);
+  if (!py_value) {
+
+    Py_DECREF(py_args);
+    FATAL("Failed to convert arguments");
+
+  }
+
+  PyTuple_SetItem(py_args, 1, py_value);
+
+  /* max_size */
+#if PY_MAJOR_VERSION >= 3
+  py_value = PyLong_FromLong(max_size);
+#else
+  py_value = PyInt_FromLong(max_size);
+#endif
+  if (!py_value) {
+
+    Py_DECREF(py_args);
+    FATAL("Failed to convert arguments");
+
+  }
+
+  PyTuple_SetItem(py_args, 2, py_value);
+
+  py_value = PyObject_CallObject(((py_mutator_t *)py_mutator)->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);
+    Py_DECREF(py_value);
+    return mutated_size;
+
+  } else {
+
+    PyErr_Print();
+    FATAL("Call failed");
+
+  }
+
+}
 
-  if (!module_name) return 1;
+
+static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
+
+  if (!module_name) return NULL;
+
+  py_mutator_t *py = calloc(1, sizeof(py_mutator_t));
+  if (!py) PFATAL("Could not allocate memory for python mutator!");
 
   Py_Initialize();
 
@@ -40,17 +115,18 @@ int init_py_module(afl_state_t *afl, u8 *module_name) {
   PyObject *py_name = PyString_FromString(module_name);
 #endif
 
-  afl->py_module = PyImport_Import(py_name);
+  py->py_module = PyImport_Import(py_name);
   Py_DECREF(py_name);
 
-  PyObject * py_module = afl->py_module;
-  PyObject **py_functions = afl->py_functions;
+  PyObject * py_module = py->py_module;
+  PyObject **py_functions = py->py_functions;
 
-  if (afl->py_module != NULL) {
+  if (py_module != NULL) {
 
     u8 py_notrim = 0, py_idx;
-    py_functions[PY_FUNC_INIT] = PyObject_GetAttrString(afl->py_module, "init");
-    py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(afl->py_module, "fuzz");
+    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");
     py_functions[PY_FUNC_INIT_TRIM] =
@@ -96,7 +172,7 @@ int init_py_module(afl_state_t *afl, u8 *module_name) {
                   "Cannot find/call function with index %d in external "
                   "Python module.\n",
                   py_idx);
-          return 1;
+          return NULL;
 
         }
 
@@ -119,23 +195,27 @@ int init_py_module(afl_state_t *afl, u8 *module_name) {
 
     PyErr_Print();
     fprintf(stderr, "Failed to load \"%s\"\n", module_name);
-    return 1;
+    return NULL;
 
   }
 
-  return 0;
+  return py;
 
 }
 
-void finalize_py_module(afl_state_t *afl) {
+void finalize_py_module(void *py_mutator) {
+
+  py_mutator_t *py = (py_mutator_t *)py_mutator;
 
-  if (afl->py_module != NULL) {
+  if (py->py_module != NULL) {
+
+    deinit_py(py_mutator);
 
     u32 i;
     for (i = 0; i < PY_FUNC_COUNT; ++i)
-      Py_XDECREF(afl->py_functions[i]);
+      Py_XDECREF(py->py_functions[i]);
 
-    Py_DECREF(afl->py_module);
+    Py_DECREF(py->py_module);
 
   }
 
@@ -143,7 +223,7 @@ void finalize_py_module(afl_state_t *afl) {
 
 }
 
-void init_py(afl_state_t *afl, unsigned int seed) {
+static void init_py(afl_state_t *afl, py_mutator_t *py_mutator, unsigned int seed) {
 
   PyObject *py_args, *py_value;
 
@@ -158,14 +238,13 @@ void init_py(afl_state_t *afl, unsigned int seed) {
   if (!py_value) {
 
     Py_DECREF(py_args);
-    fprintf(stderr, "Cannot convert argument\n");
-    return;
+    FATAL("Cannot convert argument in python init.");
 
   }
 
   PyTuple_SetItem(py_args, 0, py_value);
 
-  py_value = PyObject_CallObject(afl->py_functions[PY_FUNC_INIT], py_args);
+  py_value = PyObject_CallObject(py_mutator->py_functions[PY_FUNC_INIT], py_args);
 
   Py_DECREF(py_args);
 
@@ -173,79 +252,90 @@ void init_py(afl_state_t *afl, unsigned int seed) {
 
     PyErr_Print();
     fprintf(stderr, "Call failed\n");
-    return;
+    FATAL("Custom py mutator INIT failed.");
 
   }
 
 }
 
-size_t fuzz_py(afl_state_t *afl, u8 **buf, size_t buf_size, u8 *add_buf,
-               size_t add_buf_size, size_t max_size) {
+void deinit_py(void *py_mutator) {
 
-  size_t    mutated_size;
   PyObject *py_args, *py_value;
-  py_args = PyTuple_New(3);
 
-  /* buf */
-  py_value = PyByteArray_FromStringAndSize(*buf, buf_size);
-  if (!py_value) {
+  py_args = PyTuple_New(0);
+  py_value = PyObject_CallObject(
+      ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_DEINIT], py_args);
+  Py_DECREF(py_args);
 
-    Py_DECREF(py_args);
-    FATAL("Failed to convert arguments");
+  if (py_value != NULL) {
+
+    Py_DECREF(py_value);
+
+  } else {
+
+    PyErr_Print();
+    FATAL("Call failed");
 
   }
 
-  PyTuple_SetItem(py_args, 0, py_value);
+}
 
-  /* add_buf */
-  py_value = PyByteArray_FromStringAndSize(add_buf, add_buf_size);
-  if (!py_value) {
+void load_custom_mutator_py(afl_state_t *afl, char *module_name) {
 
-    Py_DECREF(py_args);
-    FATAL("Failed to convert arguments");
+  afl->mutator = ck_alloc(sizeof(struct custom_mutator));
 
+  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.");
   }
 
-  PyTuple_SetItem(py_args, 1, py_value);
+  PyObject **py_functions = py_mutator->py_functions;
 
-  /* max_size */
-#if PY_MAJOR_VERSION >= 3
-  py_value = PyLong_FromLong(max_size);
-#else
-  py_value = PyInt_FromLong(max_size);
-#endif
-  if (!py_value) {
+  if (py_functions[PY_FUNC_INIT]) afl->mutator->afl_custom_init = unsupported;
 
-    Py_DECREF(py_args);
-    FATAL("Failed to convert arguments");
+  if (py_functions[PY_FUNC_DEINIT]) afl->mutator->afl_custom_deinit = deinit_py;
 
-  }
+  /* "afl_custom_fuzz" should not be NULL, but the interface of Python mutator
+     is quite different from the custom mutator. */
+  afl->mutator->afl_custom_fuzz = fuzz_py;
 
-  PyTuple_SetItem(py_args, 2, py_value);
+  if (py_functions[PY_FUNC_PRE_SAVE])
+    afl->mutator->afl_custom_pre_save = pre_save_py;
 
-  py_value = PyObject_CallObject(afl->py_functions[PY_FUNC_FUZZ], py_args);
+  if (py_functions[PY_FUNC_INIT_TRIM])
+    afl->mutator->afl_custom_init_trim = init_trim_py;
 
-  Py_DECREF(py_args);
+  if (py_functions[PY_FUNC_POST_TRIM])
+    afl->mutator->afl_custom_post_trim = post_trim_py;
 
-  if (py_value != NULL) {
+  if (py_functions[PY_FUNC_TRIM]) afl->mutator->afl_custom_trim = trim_py;
 
-    mutated_size = PyByteArray_Size(py_value);
-    if (buf_size < mutated_size) *buf = ck_realloc(*buf, mutated_size);
+  if (py_functions[PY_FUNC_HAVOC_MUTATION])
+    afl->mutator->afl_custom_havoc_mutation = havoc_mutation_py;
 
-    memcpy(*buf, PyByteArray_AsString(py_value), mutated_size);
-    Py_DECREF(py_value);
-    return mutated_size;
+  if (py_functions[PY_FUNC_HAVOC_MUTATION_PROBABILITY])
+    afl->mutator->afl_custom_havoc_mutation_probability =
+        havoc_mutation_probability_py;
 
-  } else {
+  if (py_functions[PY_FUNC_QUEUE_GET])
+    afl->mutator->afl_custom_queue_get = queue_get_py;
 
-    PyErr_Print();
-    FATAL("Call failed");
+  if (py_functions[PY_FUNC_QUEUE_NEW_ENTRY])
+    afl->mutator->afl_custom_queue_new_entry = queue_new_entry_py;
 
-  }
+  OKF("Python mutator '%s' installed successfully.", module_name);
+
+  /* Initialize the custom mutator */
+  init_py(afl, py_mutator, rand_below(afl, 0xFFFFFFFF));
 
 }
 
-size_t pre_save_py(afl_state_t *afl, u8 *buf, size_t buf_size, u8 **out_buf) {
+
+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;
@@ -260,7 +350,7 @@ size_t pre_save_py(afl_state_t *afl, u8 *buf, size_t buf_size, u8 **out_buf) {
 
   PyTuple_SetItem(py_args, 0, py_value);
 
-  py_value = PyObject_CallObject(afl->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);
 
@@ -281,7 +371,7 @@ size_t pre_save_py(afl_state_t *afl, u8 *buf, size_t buf_size, u8 **out_buf) {
 
 }
 
-u32 init_trim_py(afl_state_t *afl, u8 *buf, size_t buf_size) {
+u32 init_trim_py(void *py_mutator, u8 *buf, size_t buf_size) {
 
   PyObject *py_args, *py_value;
 
@@ -296,7 +386,7 @@ u32 init_trim_py(afl_state_t *afl, u8 *buf, size_t buf_size) {
 
   PyTuple_SetItem(py_args, 0, py_value);
 
-  py_value = PyObject_CallObject(afl->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) {
@@ -318,7 +408,7 @@ u32 init_trim_py(afl_state_t *afl, u8 *buf, size_t buf_size) {
 
 }
 
-u32 post_trim_py(afl_state_t *afl, u8 success) {
+u32 post_trim_py(void *py_mutator, u8 success) {
 
   PyObject *py_args, *py_value;
 
@@ -334,7 +424,7 @@ u32 post_trim_py(afl_state_t *afl, u8 success) {
 
   PyTuple_SetItem(py_args, 0, py_value);
 
-  py_value = PyObject_CallObject(afl->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) {
@@ -356,12 +446,12 @@ u32 post_trim_py(afl_state_t *afl, u8 success) {
 
 }
 
-void trim_py(afl_state_t *afl, u8 **out_buf, size_t *out_buf_size) {
+void trim_py(void *py_mutator, u8 **out_buf, size_t *out_buf_size) {
 
   PyObject *py_args, *py_value;
 
   py_args = PyTuple_New(0);
-  py_value = PyObject_CallObject(afl->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) {
@@ -380,7 +470,7 @@ void trim_py(afl_state_t *afl, u8 **out_buf, size_t *out_buf_size) {
 
 }
 
-size_t havoc_mutation_py(afl_state_t *afl, u8 **buf, size_t buf_size,
+size_t havoc_mutation_py(void *py_mutator, u8 **buf, size_t buf_size,
                          size_t max_size) {
 
   size_t    mutated_size;
@@ -414,7 +504,7 @@ size_t havoc_mutation_py(afl_state_t *afl, u8 **buf, size_t buf_size,
   PyTuple_SetItem(py_args, 1, py_value);
 
   py_value =
-      PyObject_CallObject(afl->py_functions[PY_FUNC_HAVOC_MUTATION], py_args);
+      PyObject_CallObject(((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_HAVOC_MUTATION], py_args);
 
   Py_DECREF(py_args);
 
@@ -437,13 +527,13 @@ size_t havoc_mutation_py(afl_state_t *afl, u8 **buf, size_t buf_size,
 
 }
 
-u8 havoc_mutation_probability_py(afl_state_t *afl) {
+u8 havoc_mutation_probability_py(void *py_mutator) {
 
   PyObject *py_args, *py_value;
 
   py_args = PyTuple_New(0);
   py_value = PyObject_CallObject(
-      afl->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) {
@@ -461,7 +551,7 @@ u8 havoc_mutation_probability_py(afl_state_t *afl) {
 
 }
 
-u8 queue_get_py(afl_state_t *afl, const u8 *filename) {
+u8 queue_get_py(void *py_mutator, const u8 *filename) {
 
   PyObject *py_args, *py_value;
 
@@ -483,7 +573,7 @@ u8 queue_get_py(afl_state_t *afl, const u8 *filename) {
   PyTuple_SetItem(py_args, 0, py_value);
 
   // Call Python function
-  py_value = PyObject_CallObject(afl->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) {
@@ -509,7 +599,7 @@ u8 queue_get_py(afl_state_t *afl, const u8 *filename) {
 
 }
 
-void queue_new_entry_py(afl_state_t *afl, const u8 *filename_new_queue,
+void queue_new_entry_py(void *py_mutator, const u8 *filename_new_queue,
                         const u8 *filename_orig_queue) {
 
   PyObject *py_args, *py_value;
@@ -553,7 +643,7 @@ void queue_new_entry_py(afl_state_t *afl, const u8 *filename_new_queue,
 
   // Call
   py_value =
-      PyObject_CallObject(afl->py_functions[PY_FUNC_QUEUE_NEW_ENTRY], py_args);
+      PyObject_CallObject(((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_QUEUE_NEW_ENTRY], py_args);
   Py_DECREF(py_args);
 
   if (py_value == NULL) {
diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c
index cfeab798..f49e1f1e 100644
--- a/src/afl-fuzz-queue.c
+++ b/src/afl-fuzz-queue.c
@@ -185,12 +185,16 @@ void destroy_queue(afl_state_t *afl) {
 void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
 
   u32 i;
-  u64 fav_factor = q->exec_us * q->len;
+  u64 fav_factor;
   u64 fuzz_p2 = next_p2(q->n_fuzz);
 
+  if (afl->schedule == MMOPT || afl->schedule == RARE)
+    fav_factor = q->len << 2;
+  else
+    fav_factor = q->exec_us * q->len;
+
   /* For every byte set in afl->fsrv.trace_bits[], see if there is a previous
      winner, and how it compares to us. */
-
   for (i = 0; i < MAP_SIZE; ++i)
 
     if (afl->fsrv.trace_bits[i]) {
@@ -198,20 +202,20 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
       if (afl->top_rated[i]) {
 
         /* 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_fav_factor =
-            afl->top_rated[i]->exec_us * afl->top_rated[i]->len;
 
-        if (fuzz_p2 > top_rated_fuzz_p2) {
+        if (afl->schedule == MMOPT || afl->schedule == RARE)
+          top_rated_fav_factor = afl->top_rated[i]->len << 2;
+        else
+          top_rated_fav_factor =
+              afl->top_rated[i]->exec_us * afl->top_rated[i]->len;
 
+        if (fuzz_p2 > top_rated_fuzz_p2)
           continue;
-
-        } else if (fuzz_p2 == top_rated_fuzz_p2) {
-
+        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;
 
@@ -254,7 +258,7 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
 void cull_queue(afl_state_t *afl) {
 
   struct queue_entry *q;
-  static u8           temp_v[MAP_SIZE >> 3];
+  u8                  temp_v[MAP_SIZE >> 3];
   u32                 i;
 
   if (afl->dumb_mode || !afl->score_changed) return;
@@ -328,7 +332,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) {
+  if (afl->schedule != MMOPT && afl->schedule != RARE) {
 
     if (q->exec_us * 0.1 > avg_exec_us)
       perf_score = 10;
@@ -448,8 +452,29 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) {
       break;
 
     case MMOPT:
+      /* -- this was a more complex setup, which is good, but competed with
+         -- rare. the simpler algo however is good when rare is not.
+        // the newer the entry, the higher the pref_score
+        perf_score *= (1 + (double)((double)q->depth /
+        (double)afl->queued_paths));
+        // with special focus on the last 8 entries
+        if (afl->max_depth - q->depth < 8) perf_score *= (1 + ((8 -
+        (afl->max_depth - q->depth)) / 5));
+      */
+      // put focus on the last 5 entries
+      if (afl->max_depth - q->depth < 5) perf_score *= 2;
+
+      break;
+
+    case RARE:
 
-      if (afl->max_depth - q->depth < 5) perf_score *= 1.5;
+      // increase the score for every bitmap byte for which this entry
+      // is the top contender
+      perf_score += (q->tc_ref * 10);
+      // the more often fuzz result paths are equal to this queue entry,
+      // reduce its value
+      perf_score *=
+          (1 - (double)((double)q->n_fuzz / (double)afl->total_execs));
 
       break;
 
diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c
index c910e75e..b069fa77 100644
--- a/src/afl-fuzz-redqueen.c
+++ b/src/afl-fuzz-redqueen.c
@@ -97,7 +97,7 @@ static void rand_replace(afl_state_t *afl, u8 *buf, u32 len) {
 
   u32 i;
   for (i = 0; i < len; ++i)
-    buf[i] = UR(afl, 256);
+    buf[i] = rand_below(afl, 256);
 
 }
 
diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c
index cdec75e8..8c4b5941 100644
--- a/src/afl-fuzz-run.c
+++ b/src/afl-fuzz-run.c
@@ -28,14 +28,7 @@
 #include <signal.h>
 
 /* Execute target application, monitoring for timeouts. Return status
-   information. The called program will update afl->fsrv.trace_bits[]. */
-
-void timeout_handle(union sigval timer_data) {
-
-  pid_t child_pid = timer_data.sival_int;
-  if (child_pid > 0) kill(child_pid, SIGKILL);
-
-}
+   information. The called program will update afl->fsrv.trace_bits. */
 
 u8 run_target(afl_state_t *afl, u32 timeout) {
 
@@ -44,11 +37,9 @@ u8 run_target(afl_state_t *afl, u32 timeout) {
 
   fd_set readfds;
 
-  static struct timeval it;
-  static u32            prev_timed_out = 0;
-
-  int status = 0;
-  u32 tb4;
+  struct timeval it;
+  int            status = 0;
+  u32            tb4;
 
   afl->fsrv.child_timed_out = 0;
 
@@ -63,7 +54,7 @@ u8 run_target(afl_state_t *afl, u32 timeout) {
   /* we have the fork server (or faux server) up and running, so simply
       tell it to have at it, and then read back PID. */
 
-  if ((res = write(afl->fsrv.fsrv_ctl_fd, &prev_timed_out, 4)) != 4) {
+  if ((res = write(afl->fsrv.fsrv_ctl_fd, &afl->fsrv.prev_timed_out, 4)) != 4) {
 
     if (afl->stop_soon) return 0;
     RPFATAL(res, "Unable to request new process from fork server (OOM?)");
@@ -144,7 +135,7 @@ u8 run_target(afl_state_t *afl, u32 timeout) {
   classify_counts((u32 *)afl->fsrv.trace_bits);
 #endif                                                     /* ^WORD_SIZE_64 */
 
-  prev_timed_out = afl->fsrv.child_timed_out;
+  afl->fsrv.prev_timed_out = afl->fsrv.child_timed_out;
 
   /* Report outcome to caller. */
 
@@ -299,8 +290,6 @@ static void write_with_gap(afl_state_t *afl, void *mem, u32 len, u32 skip_at,
 u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
                   u32 handicap, u8 from_queue) {
 
-  static u8 first_trace[MAP_SIZE];
-
   u8 fault = 0, new_bits = 0, var_detected = 0,
      first_run = (q->exec_cksum == 0);
 
@@ -331,7 +320,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
       afl->shm.cmplog_mode)
     init_cmplog_forkserver(afl);
 
-  if (q->exec_cksum) memcpy(first_trace, afl->fsrv.trace_bits, MAP_SIZE);
+  if (q->exec_cksum) memcpy(afl->first_trace, afl->fsrv.trace_bits, MAP_SIZE);
 
   start_us = get_cur_time_us();
 
@@ -372,7 +361,8 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
 
         for (i = 0; i < MAP_SIZE; ++i) {
 
-          if (!afl->var_bytes[i] && first_trace[i] != afl->fsrv.trace_bits[i]) {
+          if (!afl->var_bytes[i] &&
+              afl->first_trace[i] != afl->fsrv.trace_bits[i]) {
 
             afl->var_bytes[i] = 1;
             afl->stage_max = CAL_CYCLES_LONG;
@@ -386,7 +376,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
       } else {
 
         q->exec_cksum = cksum;
-        memcpy(first_trace, afl->fsrv.trace_bits, MAP_SIZE);
+        memcpy(afl->first_trace, afl->fsrv.trace_bits, MAP_SIZE);
 
       }
 
@@ -471,8 +461,6 @@ void sync_fuzzers(afl_state_t *afl) {
 
   while ((sd_ent = readdir(sd))) {
 
-    static u8 stage_tmp[128];
-
     DIR *          qd;
     struct dirent *qd_ent;
     u8 *           qd_path, *qd_synced_path;
@@ -511,8 +499,9 @@ void sync_fuzzers(afl_state_t *afl) {
 
     /* Show stats */
 
-    sprintf(stage_tmp, "sync %u", ++sync_cnt);
-    afl->stage_name = stage_tmp;
+    snprintf(afl->stage_name_buf, STAGE_BUF_SIZE, "sync %u", ++sync_cnt);
+
+    afl->stage_name = afl->stage_name_buf;
     afl->stage_cur = 0;
     afl->stage_max = 0;
 
@@ -608,21 +597,20 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
   if (afl->mutator && afl->mutator->afl_custom_trim)
     return trim_case_custom(afl, q, in_buf);
 
-  static u8 tmp[64];
-  static u8 clean_trace[MAP_SIZE];
-
   u8  needs_write = 0, fault = 0;
   u32 trim_exec = 0;
   u32 remove_len;
   u32 len_p2;
 
+  u8 val_bufs[2][STRINGIFY_VAL_SIZE_MAX];
+
   /* Although the trimmer will be less useful when variable behavior is
      detected, it will still work to some extent, so we don't check for
      this. */
 
   if (q->len < 5) return 0;
 
-  afl->stage_name = tmp;
+  afl->stage_name = afl->stage_name_buf;
   afl->bytes_trim_in += q->len;
 
   /* Select initial chunk len, starting with large steps. */
@@ -638,7 +626,9 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
 
     u32 remove_pos = remove_len;
 
-    sprintf(tmp, "trim %s/%s", DI(remove_len), DI(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));
 
     afl->stage_cur = 0;
     afl->stage_max = q->len / remove_len;
@@ -680,7 +670,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
         if (!needs_write) {
 
           needs_write = 1;
-          memcpy(clean_trace, afl->fsrv.trace_bits, MAP_SIZE);
+          memcpy(afl->clean_trace, afl->fsrv.trace_bits, MAP_SIZE);
 
         }
 
@@ -722,7 +712,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
     ck_write(fd, in_buf, q->len, q->fname);
     close(fd);
 
-    memcpy(afl->fsrv.trace_bits, clean_trace, MAP_SIZE);
+    memcpy(afl->fsrv.trace_bits, afl->clean_trace, MAP_SIZE);
     update_bitmap_score(afl, q);
 
   }
diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c
index 63cca14d..dc16df8f 100644
--- a/src/afl-fuzz-stats.c
+++ b/src/afl-fuzz-stats.c
@@ -30,12 +30,12 @@
 void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
                       double eps) {
 
-  static double        last_bcvg, last_stab, last_eps;
-  static struct rusage rus;
+  struct rusage rus;
 
-  u8 *  fn = alloc_printf("%s/fuzzer_stats", afl->out_dir);
-  s32   fd;
-  FILE *f;
+  unsigned long long int cur_time = get_cur_time();
+  u8 *                   fn = alloc_printf("%s/fuzzer_stats", afl->out_dir);
+  s32                    fd;
+  FILE *                 f;
 
   fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600);
 
@@ -52,15 +52,15 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
 
   if (!bitmap_cvg && !stability && !eps) {
 
-    bitmap_cvg = last_bcvg;
-    stability = last_stab;
-    eps = last_eps;
+    bitmap_cvg = afl->last_bitmap_cvg;
+    stability = afl->last_stability;
+    eps = afl->last_eps;
 
   } else {
 
-    last_bcvg = bitmap_cvg;
-    last_stab = stability;
-    last_eps = eps;
+    afl->last_bitmap_cvg = bitmap_cvg;
+    afl->last_stability = stability;
+    afl->last_eps = eps;
 
   }
 
@@ -70,8 +70,10 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
       f,
       "start_time        : %llu\n"
       "last_update       : %llu\n"
+      "run_time          : %llu\n"
       "fuzzer_pid        : %d\n"
       "cycles_done       : %llu\n"
+      "cycles_wo_finds   : %llu\n"
       "execs_done        : %llu\n"
       "execs_per_sec     : %0.02f\n"
       //          "real_execs_per_sec: %0.02f\n"  // damn the name is too long
@@ -100,10 +102,11 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
       "\n"
       "target_mode       : %s%s%s%s%s%s%s%s\n"
       "command_line      : %s\n",
-      afl->start_time / 1000, get_cur_time() / 1000, getpid(),
-      afl->queue_cycle ? (afl->queue_cycle - 1) : 0, afl->total_execs,
-      /*eps,*/ afl->total_execs /
-          ((double)(get_cur_time() - afl->start_time) / 1000),
+      afl->start_time / 1000, cur_time / 1000,
+      (cur_time - afl->start_time) / 1000, getpid(),
+      afl->queue_cycle ? (afl->queue_cycle - 1) : 0, afl->cycles_wo_finds,
+      afl->total_execs,
+      afl->total_execs / ((double)(get_cur_time() - afl->start_time) / 1000),
       afl->queued_paths, afl->queued_favored, afl->queued_discovered,
       afl->queued_imported, afl->max_depth, afl->current_entry,
       afl->pending_favored, afl->pending_not_fuzzed, afl->queued_variable,
@@ -137,23 +140,24 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
 
 void maybe_update_plot_file(afl_state_t *afl, double bitmap_cvg, double eps) {
 
-  static u32 prev_qp, prev_pf, prev_pnf, prev_ce, prev_md;
-  static u64 prev_qc, prev_uc, prev_uh;
-
-  if (prev_qp == afl->queued_paths && prev_pf == afl->pending_favored &&
-      prev_pnf == afl->pending_not_fuzzed && prev_ce == afl->current_entry &&
-      prev_qc == afl->queue_cycle && prev_uc == afl->unique_crashes &&
-      prev_uh == afl->unique_hangs && prev_md == afl->max_depth)
+  if (afl->plot_prev_qp == afl->queued_paths &&
+      afl->plot_prev_pf == afl->pending_favored &&
+      afl->plot_prev_pnf == afl->pending_not_fuzzed &&
+      afl->plot_prev_ce == afl->current_entry &&
+      afl->plot_prev_qc == afl->queue_cycle &&
+      afl->plot_prev_uc == afl->unique_crashes &&
+      afl->plot_prev_uh == afl->unique_hangs &&
+      afl->plot_prev_md == afl->max_depth)
     return;
 
-  prev_qp = afl->queued_paths;
-  prev_pf = afl->pending_favored;
-  prev_pnf = afl->pending_not_fuzzed;
-  prev_ce = afl->current_entry;
-  prev_qc = afl->queue_cycle;
-  prev_uc = afl->unique_crashes;
-  prev_uh = afl->unique_hangs;
-  prev_md = afl->max_depth;
+  afl->plot_prev_qp = afl->queued_paths;
+  afl->plot_prev_pf = afl->pending_favored;
+  afl->plot_prev_pnf = afl->pending_not_fuzzed;
+  afl->plot_prev_ce = afl->current_entry;
+  afl->plot_prev_qc = afl->queue_cycle;
+  afl->plot_prev_uc = afl->unique_crashes;
+  afl->plot_prev_uh = afl->unique_hangs;
+  afl->plot_prev_md = afl->max_depth;
 
   /* Fields in the file:
 
@@ -192,21 +196,25 @@ static void check_term_size(afl_state_t *afl) {
 
 void show_stats(afl_state_t *afl) {
 
-  static u64    last_stats_ms, last_plot_ms, last_ms, last_execs;
-  static double avg_exec;
-  double        t_byte_ratio, stab_ratio;
+  double t_byte_ratio, stab_ratio;
 
   u64 cur_ms;
   u32 t_bytes, t_bits;
 
   u32 banner_len, banner_pad;
   u8  tmp[256];
+  u8  time_tmp[64];
+
+  u8 val_buf[8][STRINGIFY_VAL_SIZE_MAX];
+#define IB(i) (val_buf[(i)])
 
   cur_ms = get_cur_time();
 
   /* If not enough time has passed since last UI update, bail out. */
 
-  if (cur_ms - last_ms < 1000 / UI_TARGET_HZ && !afl->force_ui_update) return;
+  if (cur_ms - afl->stats_last_ms < 1000 / UI_TARGET_HZ &&
+      !afl->force_ui_update)
+    return;
 
   /* Check if we're past the 10 minute mark. */
 
@@ -214,31 +222,33 @@ void show_stats(afl_state_t *afl) {
 
   /* Calculate smoothed exec speed stats. */
 
-  if (!last_execs) {
+  if (!afl->stats_last_execs) {
 
-    avg_exec = ((double)afl->total_execs) * 1000 / (cur_ms - afl->start_time);
+    afl->stats_avg_exec =
+        ((double)afl->total_execs) * 1000 / (cur_ms - afl->start_time);
 
   } else {
 
-    double cur_avg =
-        ((double)(afl->total_execs - last_execs)) * 1000 / (cur_ms - last_ms);
+    double cur_avg = ((double)(afl->total_execs - afl->stats_last_execs)) *
+                     1000 / (cur_ms - afl->stats_last_ms);
 
     /* If there is a dramatic (5x+) jump in speed, reset the indicator
        more quickly. */
 
-    if (cur_avg * 5 < avg_exec || cur_avg / 5 > avg_exec) avg_exec = cur_avg;
+    if (cur_avg * 5 < afl->stats_avg_exec || cur_avg / 5 > afl->stats_avg_exec)
+      afl->stats_avg_exec = cur_avg;
 
-    avg_exec = avg_exec * (1.0 - 1.0 / AVG_SMOOTHING) +
-               cur_avg * (1.0 / AVG_SMOOTHING);
+    afl->stats_avg_exec = afl->stats_avg_exec * (1.0 - 1.0 / AVG_SMOOTHING) +
+                          cur_avg * (1.0 / AVG_SMOOTHING);
 
   }
 
-  last_ms = cur_ms;
-  last_execs = afl->total_execs;
+  afl->stats_last_ms = cur_ms;
+  afl->stats_last_execs = afl->total_execs;
 
   /* Tell the callers when to contact us (as measured in execs). */
 
-  afl->stats_update_freq = avg_exec / (UI_TARGET_HZ * 10);
+  afl->stats_update_freq = afl->stats_avg_exec / (UI_TARGET_HZ * 10);
   if (!afl->stats_update_freq) afl->stats_update_freq = 1;
 
   /* Do some bitmap stats. */
@@ -253,10 +263,10 @@ void show_stats(afl_state_t *afl) {
 
   /* Roughly every minute, update fuzzer stats and save auto tokens. */
 
-  if (cur_ms - last_stats_ms > STATS_UPDATE_SEC * 1000) {
+  if (cur_ms - afl->stats_last_stats_ms > STATS_UPDATE_SEC * 1000) {
 
-    last_stats_ms = cur_ms;
-    write_stats_file(afl, t_byte_ratio, stab_ratio, avg_exec);
+    afl->stats_last_stats_ms = cur_ms;
+    write_stats_file(afl, t_byte_ratio, stab_ratio, afl->stats_avg_exec);
     save_auto(afl);
     write_bitmap(afl);
 
@@ -264,10 +274,10 @@ void show_stats(afl_state_t *afl) {
 
   /* Every now and then, write plot data. */
 
-  if (cur_ms - last_plot_ms > PLOT_UPDATE_SEC * 1000) {
+  if (cur_ms - afl->stats_last_plot_ms > PLOT_UPDATE_SEC * 1000) {
 
-    last_plot_ms = cur_ms;
-    maybe_update_plot_file(afl, t_byte_ratio, avg_exec);
+    afl->stats_last_plot_ms = cur_ms;
+    maybe_update_plot_file(afl, t_byte_ratio, afl->stats_avg_exec);
 
   }
 
@@ -384,9 +394,10 @@ void show_stats(afl_state_t *afl) {
 
   }
 
+  u_stringify_time_diff(time_tmp, cur_ms, afl->start_time);
   SAYF(bV bSTOP "        run time : " cRST "%-33s " bSTG bV bSTOP
                 "  cycles done : %s%-5s " bSTG              bV "\n",
-       DTD(cur_ms, afl->start_time), tmp, DI(afl->queue_cycle - 1));
+       time_tmp, tmp, u_stringify_int(IB(0), afl->queue_cycle - 1));
 
   /* We want to warn people about not seeing new paths after a full cycle,
      except when resuming fuzzing or running in non-instrumented mode. */
@@ -395,8 +406,9 @@ void show_stats(afl_state_t *afl) {
       (afl->last_path_time || afl->resuming_fuzz || afl->queue_cycle == 1 ||
        afl->in_bitmap || afl->crash_mode)) {
 
-    SAYF(bV bSTOP "   last new path : " cRST "%-33s ",
-         DTD(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 {
 
@@ -413,25 +425,26 @@ void show_stats(afl_state_t *afl) {
   }
 
   SAYF(bSTG bV bSTOP "  total paths : " cRST "%-5s " bSTG bV "\n",
-       DI(afl->queued_paths));
+       u_stringify_int(IB(0), afl->queued_paths));
 
   /* Highlight crashes in red if found, denote going over the KEEP_UNIQUE_CRASH
      limit with a '+' appended to the count. */
 
-  sprintf(tmp, "%s%s", DI(afl->unique_crashes),
+  sprintf(tmp, "%s%s", u_stringify_int(IB(0), afl->unique_crashes),
           (afl->unique_crashes >= KEEP_UNIQUE_CRASH) ? "+" : "");
 
+  u_stringify_time_diff(time_tmp, cur_ms, afl->last_crash_time);
   SAYF(bV bSTOP " last uniq crash : " cRST "%-33s " bSTG bV bSTOP
                 " uniq crashes : %s%-6s" bSTG               bV "\n",
-       DTD(cur_ms, afl->last_crash_time), afl->unique_crashes ? cLRD : cRST,
-       tmp);
+       time_tmp, afl->unique_crashes ? cLRD : cRST, tmp);
 
-  sprintf(tmp, "%s%s", DI(afl->unique_hangs),
+  sprintf(tmp, "%s%s", u_stringify_int(IB(0), afl->unique_hangs),
           (afl->unique_hangs >= KEEP_UNIQUE_HANG) ? "+" : "");
 
+  u_stringify_time_diff(time_tmp, cur_ms, afl->last_hang_time);
   SAYF(bV bSTOP "  last uniq hang : " cRST "%-33s " bSTG bV bSTOP
                 "   uniq hangs : " cRST "%-6s" bSTG         bV "\n",
-       DTD(cur_ms, afl->last_hang_time), tmp);
+       time_tmp, tmp);
 
   SAYF(bVR bH bSTOP            cCYA
        " cycle progress " bSTG bH10 bH5 bH2 bH2 bHB bH bSTOP cCYA
@@ -441,7 +454,7 @@ void show_stats(afl_state_t *afl) {
      together, but then cram them into a fixed-width field - so we need to
      put them in a temporary buffer first. */
 
-  sprintf(tmp, "%s%s%u (%0.01f%%)", DI(afl->current_entry),
+  sprintf(tmp, "%s%s%u (%0.01f%%)", u_stringify_int(IB(0), afl->current_entry),
           afl->queue_cur->favored ? "." : "*", afl->queue_cur->fuzz_level,
           ((double)afl->current_entry * 100) / afl->queued_paths);
 
@@ -455,7 +468,7 @@ void show_stats(afl_state_t *afl) {
                          : ((t_bytes < 200 && !afl->dumb_mode) ? cPIN : cRST),
        tmp);
 
-  sprintf(tmp, "%s (%0.02f%%)", DI(afl->cur_skipped_paths),
+  sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->cur_skipped_paths),
           ((double)afl->cur_skipped_paths * 100) / afl->queued_paths);
 
   SAYF(bV bSTOP " paths timed out : " cRST "%-16s " bSTG bV, tmp);
@@ -468,7 +481,7 @@ void show_stats(afl_state_t *afl) {
        " stage progress " bSTG bH10 bH5 bH2 bH2 bX bH bSTOP cCYA
        " findings in depth " bSTG bH10 bH5 bH2 bH2 bVL "\n");
 
-  sprintf(tmp, "%s (%0.02f%%)", DI(afl->queued_favored),
+  sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->queued_favored),
           ((double)afl->queued_favored) * 100 / afl->queued_paths);
 
   /* Yeah... it's still going on... halp? */
@@ -479,59 +492,65 @@ void show_stats(afl_state_t *afl) {
 
   if (!afl->stage_max) {
 
-    sprintf(tmp, "%s/-", DI(afl->stage_cur));
+    sprintf(tmp, "%s/-", u_stringify_int(IB(0), afl->stage_cur));
 
   } else {
 
-    sprintf(tmp, "%s/%s (%0.02f%%)", DI(afl->stage_cur), DI(afl->stage_max),
+    sprintf(tmp, "%s/%s (%0.02f%%)", u_stringify_int(IB(0), afl->stage_cur),
+            u_stringify_int(IB(1), afl->stage_max),
             ((double)afl->stage_cur) * 100 / afl->stage_max);
 
   }
 
   SAYF(bV bSTOP " stage execs : " cRST "%-21s" bSTG bV bSTOP, tmp);
 
-  sprintf(tmp, "%s (%0.02f%%)", DI(afl->queued_with_cov),
+  sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->queued_with_cov),
           ((double)afl->queued_with_cov) * 100 / afl->queued_paths);
 
   SAYF("  new edges on : " cRST "%-22s" bSTG bV "\n", tmp);
 
-  sprintf(tmp, "%s (%s%s unique)", DI(afl->total_crashes),
-          DI(afl->unique_crashes),
+  sprintf(tmp, "%s (%s%s unique)", u_stringify_int(IB(0), afl->total_crashes),
+          u_stringify_int(IB(1), afl->unique_crashes),
           (afl->unique_crashes >= KEEP_UNIQUE_CRASH) ? "+" : "");
 
   if (afl->crash_mode) {
 
     SAYF(bV bSTOP " total execs : " cRST "%-20s " bSTG bV bSTOP
                   "   new crashes : %s%-22s" bSTG         bV "\n",
-         DI(afl->total_execs), afl->unique_crashes ? cLRD : cRST, tmp);
+         u_stringify_int(IB(0), afl->total_execs),
+         afl->unique_crashes ? cLRD : cRST, tmp);
 
   } else {
 
     SAYF(bV bSTOP " total execs : " cRST "%-20s " bSTG bV bSTOP
                   " total crashes : %s%-22s" bSTG         bV "\n",
-         DI(afl->total_execs), afl->unique_crashes ? cLRD : cRST, tmp);
+         u_stringify_int(IB(0), afl->total_execs),
+         afl->unique_crashes ? cLRD : cRST, tmp);
 
   }
 
   /* Show a warning about slow execution. */
 
-  if (avg_exec < 100) {
+  if (afl->stats_avg_exec < 100) {
 
-    sprintf(tmp, "%s/sec (%s)", DF(avg_exec),
-            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", DF(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)", DI(afl->total_tmouts),
-          DI(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);
 
@@ -547,70 +566,80 @@ void show_stats(afl_state_t *afl) {
 
   } else {
 
-    sprintf(
-        tmp, "%s/%s, %s/%s, %s/%s", DI(afl->stage_finds[STAGE_FLIP1]),
-        DI(afl->stage_cycles[STAGE_FLIP1]), DI(afl->stage_finds[STAGE_FLIP2]),
-        DI(afl->stage_cycles[STAGE_FLIP2]), DI(afl->stage_finds[STAGE_FLIP4]),
-        DI(afl->stage_cycles[STAGE_FLIP4]));
+    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]));
 
   }
 
   SAYF(bV bSTOP "   bit flips : " cRST "%-36s " bSTG bV bSTOP
                 "    levels : " cRST "%-10s" bSTG       bV "\n",
-       tmp, DI(afl->max_depth));
+       tmp, u_stringify_int(IB(0), afl->max_depth));
 
   if (!afl->skip_deterministic)
-    sprintf(
-        tmp, "%s/%s, %s/%s, %s/%s", DI(afl->stage_finds[STAGE_FLIP8]),
-        DI(afl->stage_cycles[STAGE_FLIP8]), DI(afl->stage_finds[STAGE_FLIP16]),
-        DI(afl->stage_cycles[STAGE_FLIP16]), DI(afl->stage_finds[STAGE_FLIP32]),
-        DI(afl->stage_cycles[STAGE_FLIP32]));
+    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]));
 
   SAYF(bV bSTOP "  byte flips : " cRST "%-36s " bSTG bV bSTOP
                 "   pending : " cRST "%-10s" bSTG       bV "\n",
-       tmp, DI(afl->pending_not_fuzzed));
+       tmp, u_stringify_int(IB(0), afl->pending_not_fuzzed));
 
   if (!afl->skip_deterministic)
-    sprintf(tmp, "%s/%s, %s/%s, %s/%s", DI(afl->stage_finds[STAGE_ARITH8]),
-            DI(afl->stage_cycles[STAGE_ARITH8]),
-            DI(afl->stage_finds[STAGE_ARITH16]),
-            DI(afl->stage_cycles[STAGE_ARITH16]),
-            DI(afl->stage_finds[STAGE_ARITH32]),
-            DI(afl->stage_cycles[STAGE_ARITH32]));
+    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]));
 
   SAYF(bV bSTOP " arithmetics : " cRST "%-36s " bSTG bV bSTOP
                 "  pend fav : " cRST "%-10s" bSTG       bV "\n",
-       tmp, DI(afl->pending_favored));
+       tmp, u_stringify_int(IB(0), afl->pending_favored));
 
   if (!afl->skip_deterministic)
-    sprintf(tmp, "%s/%s, %s/%s, %s/%s", DI(afl->stage_finds[STAGE_INTEREST8]),
-            DI(afl->stage_cycles[STAGE_INTEREST8]),
-            DI(afl->stage_finds[STAGE_INTEREST16]),
-            DI(afl->stage_cycles[STAGE_INTEREST16]),
-            DI(afl->stage_finds[STAGE_INTEREST32]),
-            DI(afl->stage_cycles[STAGE_INTEREST32]));
+    sprintf(tmp, "%s/%s, %s/%s, %s/%s",
+            u_stringify_int(IB(0), afl->stage_finds[STAGE_INTEREST8]),
+            u_stringify_int(IB(1), afl->stage_cycles[STAGE_INTEREST8]),
+            u_stringify_int(IB(2), afl->stage_finds[STAGE_INTEREST16]),
+            u_stringify_int(IB(3), afl->stage_cycles[STAGE_INTEREST16]),
+            u_stringify_int(IB(4), afl->stage_finds[STAGE_INTEREST32]),
+            u_stringify_int(IB(5), afl->stage_cycles[STAGE_INTEREST32]));
 
   SAYF(bV bSTOP "  known ints : " cRST "%-36s " bSTG bV bSTOP
                 " own finds : " cRST "%-10s" bSTG       bV "\n",
-       tmp, DI(afl->queued_discovered));
+       tmp, u_stringify_int(IB(0), afl->queued_discovered));
 
   if (!afl->skip_deterministic)
-    sprintf(tmp, "%s/%s, %s/%s, %s/%s", DI(afl->stage_finds[STAGE_EXTRAS_UO]),
-            DI(afl->stage_cycles[STAGE_EXTRAS_UO]),
-            DI(afl->stage_finds[STAGE_EXTRAS_UI]),
-            DI(afl->stage_cycles[STAGE_EXTRAS_UI]),
-            DI(afl->stage_finds[STAGE_EXTRAS_AO]),
-            DI(afl->stage_cycles[STAGE_EXTRAS_AO]));
+    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]));
 
   SAYF(bV bSTOP "  dictionary : " cRST "%-36s " bSTG bV bSTOP
                 "  imported : " cRST "%-10s" bSTG       bV "\n",
-       tmp, afl->sync_id ? DI(afl->queued_imported) : (u8 *)"n/a");
+       tmp,
+       afl->sync_id ? u_stringify_int(IB(0), afl->queued_imported) : (u8 *)"n/a");
 
-  sprintf(
-      tmp, "%s/%s, %s/%s, %s/%s", DI(afl->stage_finds[STAGE_HAVOC]),
-      DI(afl->stage_cycles[STAGE_HAVOC]), DI(afl->stage_finds[STAGE_SPLICE]),
-      DI(afl->stage_cycles[STAGE_SPLICE]), DI(afl->stage_finds[STAGE_RADAMSA]),
-      DI(afl->stage_cycles[STAGE_RADAMSA]));
+  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]));
 
   SAYF(bV bSTOP "   havoc/rad : " cRST "%-36s " bSTG bV bSTOP, tmp);
 
@@ -631,23 +660,25 @@ void show_stats(afl_state_t *afl) {
   if (afl->shm.cmplog_mode) {
 
     sprintf(tmp, "%s/%s, %s/%s, %s/%s, %s/%s",
-            DI(afl->stage_finds[STAGE_PYTHON]),
-            DI(afl->stage_cycles[STAGE_PYTHON]),
-            DI(afl->stage_finds[STAGE_CUSTOM_MUTATOR]),
-            DI(afl->stage_cycles[STAGE_CUSTOM_MUTATOR]),
-            DI(afl->stage_finds[STAGE_COLORIZATION]),
-            DI(afl->stage_cycles[STAGE_COLORIZATION]),
-            DI(afl->stage_finds[STAGE_ITS]), DI(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);
 
   } else {
 
-    sprintf(tmp, "%s/%s, %s/%s", DI(afl->stage_finds[STAGE_PYTHON]),
-            DI(afl->stage_cycles[STAGE_PYTHON]),
-            DI(afl->stage_finds[STAGE_CUSTOM_MUTATOR]),
-            DI(afl->stage_cycles[STAGE_CUSTOM_MUTATOR]));
+    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]));
 
     SAYF(bV bSTOP "   py/custom : " cRST "%-36s " bSTG bVR bH20 bH2 bH bRB "\n",
          tmp);
@@ -663,7 +694,7 @@ void show_stats(afl_state_t *afl) {
     sprintf(tmp, "%0.02f%%/%s, ",
             ((double)(afl->bytes_trim_in - afl->bytes_trim_out)) * 100 /
                 afl->bytes_trim_in,
-            DI(afl->trim_execs));
+            u_stringify_int(IB(0), afl->trim_execs));
 
   }
 
@@ -688,8 +719,9 @@ void show_stats(afl_state_t *afl) {
 
   if (afl->mutator) {
 
-    sprintf(tmp, "%s/%s", DI(afl->stage_finds[STAGE_CUSTOM_MUTATOR]),
-            DI(afl->stage_cycles[STAGE_CUSTOM_MUTATOR]));
+    sprintf(tmp, "%s/%s",
+            u_stringify_int(IB(0), afl->stage_finds[STAGE_CUSTOM_MUTATOR]),
+            u_stringify_int(IB(1), afl->stage_cycles[STAGE_CUSTOM_MUTATOR]));
     SAYF(bV bSTOP " custom mut. : " cRST "%-36s " bSTG bV RESET_G1, tmp);
 
   } else {
@@ -744,6 +776,8 @@ void show_stats(afl_state_t *afl) {
   /* Last line */
   SAYF(SET_G1 "\n" bSTG bLB bH30 bH20 bH2 bRB bSTOP cRST RESET_G1);
 
+#undef IB
+
   /* Hallelujah! */
 
   fflush(0);
@@ -762,6 +796,9 @@ void show_init_stats(afl_state_t *afl) {
   u64                 avg_us = 0;
   u32                 max_len = 0;
 
+  u8 val_bufs[4][STRINGIFY_VAL_SIZE_MAX];
+#define IB(i) val_bufs[(i)], sizeof(val_bufs[(i)])
+
   if (afl->total_cal_cycles) avg_us = afl->total_cal_us / afl->total_cal_cycles;
 
   while (q) {
@@ -797,10 +834,10 @@ void show_init_stats(afl_state_t *afl) {
 
     if (max_len > 50 * 1024)
       WARNF(cLRD "Some test cases are huge (%s) - see %s/perf_tips.md!",
-            DMS(max_len), doc_path);
+            stringify_mem_size(IB(0), max_len), doc_path);
     else if (max_len > 10 * 1024)
-      WARNF("Some test cases are big (%s) - see %s/perf_tips.md.", DMS(max_len),
-            doc_path);
+      WARNF("Some test cases are big (%s) - see %s/perf_tips.md.",
+            stringify_mem_size(IB(0), max_len), doc_path);
 
     if (afl->useless_at_start && !afl->in_bitmap)
       WARNF(cLRD "Some test cases look useless. Consider using a smaller set.");
@@ -824,7 +861,8 @@ void show_init_stats(afl_state_t *afl) {
       max_bits,
       ((double)afl->total_bitmap_size) /
           (afl->total_bitmap_entries ? afl->total_bitmap_entries : 1),
-      DI(min_us), DI(max_us), DI(avg_us));
+      stringify_int(IB(0), min_us), stringify_int(IB(1), max_us),
+      stringify_int(IB(2), avg_us));
 
   if (!afl->timeout_given) {
 
@@ -868,6 +906,7 @@ void show_init_stats(afl_state_t *afl) {
     afl->hang_tmout = MIN(EXEC_TIMEOUT, afl->fsrv.exec_tmout * 2 + 100);
 
   OKF("All set and ready to roll!");
+#undef IB
 
 }
 
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index 10fee76c..ba56ff67 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -96,8 +96,8 @@ static void usage(afl_state_t *afl, u8 *argv0, int more_help) {
       "Execution control settings:\n"
       "  -p schedule   - power schedules recompute a seed's performance "
       "score.\n"
-      "                  <explore (default), fast, coe, lin, quad, exploit, "
-      "mmopt>\n"
+      "                  <explore(default), fast, coe, lin, quad, exploit, "
+      "mmopt, rare>\n"
       "                  see docs/power_schedules.md\n"
       "  -f file       - location read by the fuzzed program (stdin)\n"
       "  -t msec       - timeout for each run (auto-scaled, 50-%d ms)\n"
@@ -230,8 +230,7 @@ int main(int argc, char **argv_orig, char **envp) {
   u64    prev_queued = 0;
   u32    sync_interval_cnt = 0, seek_to, show_help = 0;
   u8 *   extras_dir = 0;
-  u8     mem_limit_given = 0;
-  u8     exit_1 = !!get_afl_env("AFL_BENCH_JUST_ONE");
+  u8     mem_limit_given = 0, exit_1 = 0;
   char **use_argv;
 
   struct timeval  tv;
@@ -246,11 +245,12 @@ int main(int argc, char **argv_orig, char **envp) {
   afl_fsrv_init(&afl->fsrv);
 
   read_afl_environment(afl, envp);
+  exit_1 = !!afl->afl_env.afl_bench_just_one;
 
   SAYF(cCYA "afl-fuzz" VERSION cRST
             " based on afl by Michal Zalewski and a big online community\n");
 
-  doc_path = access(DOC_PATH, F_OK) ? (u8 *)"docs" : doc_path;
+  doc_path = access(DOC_PATH, F_OK) != 0 ? (u8 *)"docs" : (u8 *)DOC_PATH;
 
   gettimeofday(&tv, &tz);
   afl->init_seed = tv.tv_sec ^ tv.tv_usec ^ getpid();
@@ -304,6 +304,10 @@ int main(int argc, char **argv_orig, char **envp) {
 
           afl->schedule = MMOPT;
 
+        } else if (!stricmp(optarg, "rare")) {
+
+          afl->schedule = RARE;
+
         } else if (!stricmp(optarg, "explore") || !stricmp(optarg, "default") ||
 
                    !stricmp(optarg, "normal") || !stricmp(optarg, "afl")) {
@@ -760,8 +764,9 @@ int main(int argc, char **argv_orig, char **envp) {
     case LIN: OKF("Using linear power schedule (LIN)"); break;
     case QUAD: OKF("Using quadratic power schedule (QUAD)"); break;
     case MMOPT: OKF("Using modified MOpt power schedule (MMOPT)"); break;
+    case RARE: OKF("Using rare edge focus power schedule (RARE)"); break;
     case EXPLORE:
-      OKF("Using exploration-based constant power schedule (EXPLORE)");
+      OKF("Using exploration-based constant power schedule (EXPLORE, default)");
       break;
     default: FATAL("Unknown power schedule"); break;
 
@@ -1046,9 +1051,9 @@ int main(int argc, char **argv_orig, char **envp) {
 
       }
 
-      show_stats(afl);
+      // show_stats(afl);
 
-      if (afl->not_on_tty) {
+      if (unlikely(afl->not_on_tty)) {
 
         ACTF("Entering queue cycle %llu.", afl->queue_cycle);
         fflush(stdout);
@@ -1119,7 +1124,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
   }
 
-  if (afl->queue_cur) show_stats(afl);
+  // if (afl->queue_cur) show_stats(afl);
 
   /*
    * ATTENTION - the following 10 lines were copied from a PR to Google's afl
@@ -1144,12 +1149,12 @@ int main(int argc, char **argv_orig, char **envp) {
   }
 
   write_bitmap(afl);
-  write_stats_file(afl, 0, 0, 0);
   maybe_update_plot_file(afl, 0, 0);
   save_auto(afl);
 
 stop_fuzzing:
 
+  write_stats_file(afl, 0, 0, 0);
   afl->force_ui_update = 1;  // ensure the screen is reprinted
   show_stats(afl);           // print the screen one last time
 
diff --git a/src/afl-gotcpu.c b/src/afl-gotcpu.c
index 70ed4dbc..6c2fa147 100644
--- a/src/afl-gotcpu.c
+++ b/src/afl-gotcpu.c
@@ -90,7 +90,7 @@ static u64 get_cpu_usage_us(void) {
 
 static u32 measure_preemption(u32 target_ms) {
 
-  static volatile u32 v1, v2;
+  volatile u32 v1, v2 = 0;
 
   u64 st_t, en_t, st_c, en_c, real_delta, slice_delta;
   s32 loop_repeats = 0;
diff --git a/src/afl-showmap.c b/src/afl-showmap.c
index 0051bbec..caacefe4 100644
--- a/src/afl-showmap.c
+++ b/src/afl-showmap.c
@@ -263,9 +263,8 @@ static void write_to_testcase(afl_forkserver_t *fsrv, void *mem, u32 len) {
 static u8 run_target_forkserver(afl_forkserver_t *fsrv, char **argv, u8 *mem,
                                 u32 len) {
 
-  static struct itimerval it;
-  static u32              prev_timed_out = 0;
-  int                     status = 0;
+  struct itimerval it;
+  int              status = 0;
 
   memset(fsrv->trace_bits, 0, MAP_SIZE);
   MEM_BARRIER();
@@ -277,7 +276,7 @@ static u8 run_target_forkserver(afl_forkserver_t *fsrv, char **argv, u8 *mem,
   /* we have the fork server up and running, so simply
      tell it to have at it, and then read back PID. */
 
-  if ((res = write(fsrv->fsrv_ctl_fd, &prev_timed_out, 4)) != 4) {
+  if ((res = write(fsrv->fsrv_ctl_fd, &fsrv->prev_timed_out, 4)) != 4) {
 
     if (stop_soon) return 0;
     RPFATAL(res, "Unable to request new process from fork server (OOM?)");
@@ -579,11 +578,6 @@ static void setup_signal_handlers(void) {
   sigaction(SIGINT, &sa, NULL);
   sigaction(SIGTERM, &sa, NULL);
 
-  /* Exec timeout notifications. */
-
-  sa.sa_handler = handle_timeout;
-  sigaction(SIGALRM, &sa, NULL);
-
 }
 
 /* Show banner. */
diff --git a/src/afl-tmin.c b/src/afl-tmin.c
index 17e9af5a..2275aef5 100644
--- a/src/afl-tmin.c
+++ b/src/afl-tmin.c
@@ -247,160 +247,14 @@ static void write_to_testcase(afl_forkserver_t *fsrv, void *mem, u32 len) {
 
 }
 
-/* Handle timeout signal. */
-/*
-static void handle_timeout(int sig) {
-
-  if (child_pid > 0) {
-
-  child_timed_out = 1;
-    kill(child_pid, SIGKILL);
-
-  } else if (child_pid == -1 && forksrv_pid > 0) {
-
-    child_timed_out = 1;
-    kill(forksrv_pid, SIGKILL);
-
-  }
-
-}
-
-*/
-
-/* start the app and it's forkserver */
-/*
-static void init_forkserver(char **argv) {
-
-  static struct itimerval it;
-  int st_pipe[2], ctl_pipe[2];
-  int status = 0;
-  s32 rlen;
-
-  ACTF("Spinning up the fork server...");
-  if (pipe(st_pipe) || pipe(ctl_pipe)) PFATAL("pipe() failed");
-
-  forksrv_pid = fork();
-
-  if (forksrv_pid < 0) PFATAL("fork() failed");
-
-  if (!forksrv_pid) {
-
-    struct rlimit r;
-
-    if (dup2(use_stdin ? out_fd : dev_null_fd, 0) < 0 ||
-        dup2(dev_null_fd, 1) < 0 ||
-        dup2(dev_null_fd, 2) < 0) {
-
-      *(u32*)trace_bits = EXEC_FAIL_SIG;
-      PFATAL("dup2() failed");
-
-    }
-
-    close(dev_null_fd);
-    close(out_fd);
-
-    setsid();
-
-    if (mem_limit) {
-
-      r.rlim_max = r.rlim_cur = ((rlim_t)mem_limit) << 20;
-
-#ifdef RLIMIT_AS
-
-      setrlimit(RLIMIT_AS, &r); // Ignore errors
-
-#else
-
-      setrlimit(RLIMIT_DATA, &r); // Ignore errors
-
-#endif // ^RLIMIT_AS
-
-    }
-
-    r.rlim_max = r.rlim_cur = 0;
-    setrlimit(RLIMIT_CORE, &r); // Ignore errors
-
-    // Set up control and status pipes, close the unneeded original fds.
-
-    if (dup2(ctl_pipe[0], FORKSRV_FD) < 0) PFATAL("dup2() failed");
-    if (dup2(st_pipe[1], FORKSRV_FD + 1) < 0) PFATAL("dup2() failed");
-
-    close(ctl_pipe[0]);
-    close(ctl_pipe[1]);
-    close(st_pipe[0]);
-    close(st_pipe[1]);
-
-    execv(fsrv->target_path, argv);
-
-    *(u32*)trace_bits = EXEC_FAIL_SIG;
-    exit(0);
-
-  }
-
-  // Close the unneeded endpoints.
-
-  close(ctl_pipe[0]);
-  close(st_pipe[1]);
-
-  fsrv_ctl_fd = ctl_pipe[1];
-  fsrv_st_fd  = st_pipe[0];
-
-  // Configure timeout, wait for child, cancel timeout.
-
-  if (exec_tmout) {
-
-    child_timed_out = 0;
-    it.it_value.tv_sec = (exec_tmout * FORK_WAIT_MULT / 1000);
-    it.it_value.tv_usec = ((exec_tmout * FORK_WAIT_MULT) % 1000) * 1000;
-
-  }
-
-  setitimer(ITIMER_REAL, &it, NULL);
-
-  rlen = read(fsrv_st_fd, &status, 4);
-
-  it.it_value.tv_sec = 0;
-  it.it_value.tv_usec = 0;
-  setitimer(ITIMER_REAL, &it, NULL);
-
-  // If we have a four-byte "hello" message from the server, we're all set.
-  // Otherwise, try to figure out what went wrong.
-
-  if (rlen == 4) {
-
-    ACTF("All right - fork server is up.");
-    return;
-
-  }
-
-  if (waitpid(forksrv_pid, &status, 0) <= 0)
-    PFATAL("waitpid() failed");
-
-  u8 child_crashed;
-
-  if (WIFSIGNALED(status))
-    child_crashed = 1;
-
-  if (child_timed_out)
-    SAYF(cLRD "\n+++ Program timed off +++\n" cRST);
-  else if (stop_soon)
-    SAYF(cLRD "\n+++ Program aborted by user +++\n" cRST);
-  else if (child_crashed)
-    SAYF(cLRD "\n+++ Program killed by signal %u +++\n" cRST, WTERMSIG(status));
-
-}
-
-*/
-
 /* Execute target application. Returns 0 if the changes are a dud, or
    1 if they should be kept. */
 
 static u8 run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len,
                      u8 first_run) {
 
-  static struct itimerval it;
-  static u32              prev_timed_out = 0;
-  int                     status = 0;
+  struct itimerval it;
+  int              status = 0;
 
   u32 cksum;
 
@@ -416,7 +270,7 @@ static u8 run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len,
   /* we have the fork server up and running, so simply
      tell it to have at it, and then read back PID. */
 
-  if ((res = write(fsrv->fsrv_ctl_fd, &prev_timed_out, 4)) != 4) {
+  if ((res = write(fsrv->fsrv_ctl_fd, &fsrv->prev_timed_out, 4)) != 4) {
 
     if (stop_soon) return 0;
     RPFATAL(res, "Unable to request new process from fork server (OOM?)");
@@ -962,11 +816,6 @@ static void setup_signal_handlers(void) {
   sigaction(SIGINT, &sa, NULL);
   sigaction(SIGTERM, &sa, NULL);
 
-  /* Exec timeout notifications. */
-
-  sa.sa_handler = handle_timeout;
-  sigaction(SIGALRM, &sa, NULL);
-
 }
 
 /* Display usage hints. */
diff --git a/test/checkcommit.sh b/test/checkcommit.sh
new file mode 100755
index 00000000..27d08d36
--- /dev/null
+++ b/test/checkcommit.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+CMDLINE="/prg/tests/normal/tiff-4.0.4/tools/thumbnail @@ /dev/null"
+INDIR="/prg/tests/normal/tiff-4.0.4/in-small"
+
+test -z "$1" -o -n "$4" && { 
+  echo "Syntax: $0 commit-id <indir> \"<cmdline>\""
+  echo
+  echo "Switches to the defined commit ID, compiles with profiling and runs"
+  echo "afl-fuzz on a defind target and input directory, saving timing,"
+  echo "fuzzer_stats and profiling output to \"<commit-id>.out\""
+  echo "Honors CFLAGS and LDFLAGS"
+  echo
+  echo "Defaults:"
+  echo "  indir: \"$INDIR\""
+  echo "  cmdline: \"$CMDLINE\""
+  exit 1
+}
+
+C=$1
+test -n "$2" && INDIR=$2
+test -n "$3" && CMDLINE=$3
+
+git checkout "$C" || { echo "CHECKOUT FAIL $C" > $C.out ; exit 1 ; }
+export AFL_BENCH_JUST_ONE=1
+test -z "$CFLAGS" && CFLAGS="-O3 -funroll-loops"
+export CFLAGS="$CFLAGS -pg"
+export LDFLAGS="$LDFLAGS -pg"
+make >/dev/null 2>&1 || echo ERROR: BUILD FAILURE 
+test -x ./afl-fuzz || { echo "BUILD FAIL $C" > $C.out ; make clean ; exit 1 ; }
+
+START=`date +%s`
+echo $START > $C.out
+time nice -n -20 ./afl-fuzz -i "$INDIR" -s 123 -o out-profile -- $CMDLINE 2>> $C.out
+STOP=`date +%s`
+echo $STOP >> $C.out
+echo RUNTIME: `expr $STOP - $START` >> $C.out
+cat out-profile/fuzzer_stats >> $C.out
+gprof ./afl-fuzz gmon.out >> $C.out
+
+make clean >/dev/null 2>&1
+rm -rf out-profile gmon.out
diff --git a/test/test.sh b/test/test.sh
index 49dfb1a9..8434aaf1 100755
--- a/test/test.sh
+++ b/test/test.sh
@@ -3,10 +3,10 @@
 #
 # Ensure we have: test, type, diff, grep -qE
 #
-test -z "" 2> /dev/null || { echo Error: test command not found ; exit 1 ; }
+test -z "" 2>/dev/null || { echo Error: test command not found ; exit 1 ; }
 GREP=`type grep > /dev/null 2>&1 && echo OK`
 test "$GREP" = OK || { echo Error: grep command not found ; exit 1 ; }
-echo foobar | grep -qE 'asd|oob' 2> /dev/null || { echo Error: grep command does not support -q and/or -E option ; exit 1 ; }
+echo foobar | grep -qE 'asd|oob' 2>/dev/null || { echo Error: grep command does not support -q and/or -E option ; exit 1 ; }
 echo 1 > test.1
 echo 1 > test.2
 OK=OK
@@ -163,7 +163,7 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc
     {
       ../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -- ./test-instr.plain >>errors 2>&1
     } >>errors 2>&1
-    test -n "$( ls out/queue/id:000002* 2> /dev/null )" && {
+    test -n "$( ls out/queue/id:000002* 2>/dev/null )" && {
       $ECHO "$GREEN[+] afl-fuzz is working correctly with ${AFL_GCC}"
     } || {
       echo CUT------------------------------------------------------------------CUT
@@ -200,7 +200,7 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc
     }
     fi
     ../afl-tmin -m ${MEM_LIMIT} -i in/in2 -o in2/in2 -- ./test-instr.plain > /dev/null 2>&1
-    SIZE=`ls -l in2/in2 2> /dev/null | awk '{print$5}'`
+    SIZE=`ls -l in2/in2 2>/dev/null | awk '{print$5}'`
     test "$SIZE" = 1 && $ECHO "$GREEN[+] afl-tmin correctly minimized the testcase"
     test "$SIZE" = 1 || {
        $ECHO "$RED[!] afl-tmin did incorrectly minimize the testcase to $SIZE"
@@ -223,7 +223,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
   # on FreeBSD need to set AFL_CC
   test `uname -s` = 'FreeBSD' && {
     if type clang >/dev/null; then
-      export AFL_CC=`type clang | awk '{print $NF}'`
+      export AFL_CC=`command -v clang`
     else
       export AFL_CC=`$LLVM_CONFIG --bindir`/clang
     fi
@@ -286,7 +286,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
     {
       ../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -- ./test-instr.plain >>errors 2>&1
     } >>errors 2>&1
-    test -n "$( ls out/queue/id:000002* 2> /dev/null )" && {
+    test -n "$( ls out/queue/id:000002* 2>/dev/null )" && {
       $ECHO "$GREEN[+] afl-fuzz is working correctly with llvm_mode"
     } || {
       echo CUT------------------------------------------------------------------CUT
@@ -324,7 +324,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
       }
       fi
       ../afl-tmin -m ${MEM_LIMIT} -i in/in2 -o in2/in2 -- ./test-instr.plain > /dev/null 2>&1
-      SIZE=`ls -l in2/in2 2> /dev/null | awk '{print$5}'`
+      SIZE=`ls -l in2/in2 2>/dev/null | awk '{print$5}'`
       test "$SIZE" = 1 && $ECHO "$GREEN[+] afl-tmin correctly minimized the testcase"
       test "$SIZE" = 1 || {
          $ECHO "$RED[!] afl-tmin did incorrectly minimize the testcase to $SIZE"
@@ -337,13 +337,13 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
   rm -f test-instr.plain
 
   # now for the special llvm_mode things
-  AFL_LLVM_INSTRIM=1 AFL_LLVM_INSTRIM_LOOPHEAD=1 ../afl-clang-fast -o test-instr.instrim ../test-instr.c > /dev/null 2> test.out
+  AFL_LLVM_INSTRIM=1 AFL_LLVM_INSTRIM_LOOPHEAD=1 ../afl-clang-fast -o test-instr.instrim ../test-instr.c > /dev/null 2>test.out
   test -e test-instr.instrim && {
     TUPLES=`echo 0|../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-instr.instrim 2>&1 | grep Captur | awk '{print$3}'`
     test "$TUPLES" -gt 2 -a "$TUPLES" -lt 5 && {
-      $ECHO "$GREEN[+] llvm_mode Instrim reported $TUPLES instrumented locations which is fine"
+      $ECHO "$GREEN[+] llvm_mode InsTrim reported $TUPLES instrumented locations which is fine"
     } || {
-      $ECHO "$RED[!] llvm_mode Instrim instrumentation produces weird numbers: $TUPLES"
+      $ECHO "$RED[!] llvm_mode InsTrim instrumentation produces weird numbers: $TUPLES"
       CODE=1
     }
     rm -f test-instr.instrim test.out
@@ -351,7 +351,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
     $ECHO "$RED[!] llvm_mode InsTrim compilation failed"
     CODE=1
   }
-  AFL_DEBUG=1 AFL_LLVM_LAF_SPLIT_SWITCHES=1 AFL_LLVM_LAF_TRANSFORM_COMPARES=1 AFL_LLVM_LAF_SPLIT_COMPARES=1 ../afl-clang-fast -o test-compcov.compcov test-compcov.c > /dev/null 2> test.out
+  AFL_DEBUG=1 AFL_LLVM_LAF_SPLIT_SWITCHES=1 AFL_LLVM_LAF_TRANSFORM_COMPARES=1 AFL_LLVM_LAF_SPLIT_COMPARES=1 ../afl-clang-fast -o test-compcov.compcov test-compcov.c > test.out 2>&1
   test -e test-compcov.compcov && {
     grep -Eq " [3-9][0-9] location" test.out && {
       $ECHO "$GREEN[+] llvm_mode laf-intel/compcov feature works correctly"
@@ -401,7 +401,7 @@ test -e ../afl-clang-lto -a -e ../afl-llvm-lto-instrumentation.so && {
   # on FreeBSD need to set AFL_CC
   test `uname -s` = 'FreeBSD' && {
     if type clang >/dev/null; then
-      export AFL_CC=`type clang | awk '{print $NF}'`
+      export AFL_CC=`command -v clang`
     else
       export AFL_CC=`$LLVM_CONFIG --bindir`/clang
     fi
@@ -471,7 +471,7 @@ test -e ../afl-clang-lto -a -e ../afl-llvm-lto-instrumentation.so && {
 }
 
 $ECHO "$BLUE[*] Testing: gcc_plugin"
-export AFL_CC=`type gcc | awk '{print $NF}'`
+export AFL_CC=`command -v gcc`
 test -e ../afl-gcc-fast -a -e ../afl-gcc-rt.o && {
   ../afl-gcc-fast -o test-instr.plain.gccpi ../test-instr.c > /dev/null 2>&1
   AFL_HARDEN=1 ../afl-gcc-fast -o test-compcov.harden.gccpi test-compcov.c > /dev/null 2>&1
@@ -533,7 +533,7 @@ test -e ../afl-gcc-fast -a -e ../afl-gcc-rt.o && {
     {
       ../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -- ./test-instr.plain.gccpi >>errors 2>&1
     } >>errors 2>&1
-    test -n "$( ls out/queue/id:000002* 2> /dev/null )" && {
+    test -n "$( ls out/queue/id:000002* 2>/dev/null )" && {
       $ECHO "$GREEN[+] afl-fuzz is working correctly with gcc_plugin"
     } || {
       echo CUT------------------------------------------------------------------CUT
@@ -598,7 +598,7 @@ test -e ../libdislocator.so && {
   {
     ulimit -c 1
     # DYLD_INSERT_LIBRARIES and DYLD_FORCE_FLAT_NAMESPACE is used on Darwin/MacOSX
-    LD_PRELOAD=../libdislocator.so DYLD_INSERT_LIBRARIES=../libdislocator.so DYLD_FORCE_FLAT_NAMESPACE=1 ./test-compcov BUFFEROVERFLOW > test.out 2> /dev/null
+    LD_PRELOAD=../libdislocator.so DYLD_INSERT_LIBRARIES=../libdislocator.so DYLD_FORCE_FLAT_NAMESPACE=1 ./test-compcov BUFFEROVERFLOW > test.out 2>/dev/null
   } > /dev/null 2>&1
   grep -q BUFFEROVERFLOW test.out > /dev/null 2>&1 && {
     $ECHO "$RED[!] libdislocator did not detect the memory corruption"
@@ -617,7 +617,7 @@ test -e ../libradamsa.so && {
 
   test `uname -s` = 'FreeBSD' && {
     if type clang >/dev/null; then
-      export AFL_CC=`type clang | awk '{print $NF}'`
+      export AFL_CC=`command -v clang`
     else
       export AFL_CC=`$LLVM_CONFIG --bindir`/clang
     fi
@@ -632,7 +632,7 @@ test -e ../libradamsa.so && {
     {
       ../afl-fuzz -RR -V10 -m ${MEM_LIMIT} -i in -o out -- ./test-instr.plain
     } >>errors 2>&1
-    test -n "$( ls out/queue/id:000001* 2> /dev/null )" && {
+    test -n "$( ls out/queue/id:000001* 2>/dev/null )" && {
       $ECHO "$GREEN[+] libradamsa performs good - and very slow - mutations"
     } || {
       echo CUT------------------------------------------------------------------CUT
@@ -663,7 +663,7 @@ test -e ../afl-qemu-trace && {
       {
         ../afl-fuzz -m ${MEM_LIMIT} -V10 -Q -i in -o out -- ./test-instr >>errors 2>&1
       } >>errors 2>&1
-      test -n "$( ls out/queue/id:000002* 2> /dev/null )" && {
+      test -n "$( ls out/queue/id:000002* 2>/dev/null )" && {
         $ECHO "$GREEN[+] afl-fuzz is working correctly with qemu_mode"
         RUNTIME=`grep execs_done out/fuzzer_stats | awk '{print$3}'`
       } || {
@@ -678,13 +678,13 @@ test -e ../afl-qemu-trace && {
       $ECHO "$GREY[*] running afl-fuzz for qemu_mode AFL_ENTRYPOINT, this will take approx 6 seconds"
       {
         {
-          export AFL_ENTRYPOINT=`expr 0x4$(nm test-instr | grep "T main" | awk '{print $1}' | sed 's/^.......//')`
-          $ECHO AFL_ENTRYPOINT=$AFL_ENTRYPOINT - $(m test-instr | grep "T main") - $(file ./test-instr)
+          export AFL_ENTRYPOINT=`expr 0x4$(nm test-instr | grep "T main" | awk '{print $1}' | sed 's/^.......//' )`
+          $ECHO AFL_ENTRYPOINT=$AFL_ENTRYPOINT - $(nm test-instr | grep "T main") - $(file ./test-instr)
           ../afl-fuzz -m ${MEM_LIMIT} -V2 -Q -i in -o out -- ./test-instr
           unset AFL_ENTRYPOINT
         } >>errors 2>&1
       } >>errors 2>&1
-      test -n "$( ls out/queue/id:000001* 2> /dev/null )" && {
+      test -n "$( ls out/queue/id:000001* 2>/dev/null )" && {
         $ECHO "$GREEN[+] afl-fuzz is working correctly with qemu_mode AFL_ENTRYPOINT"
         RUNTIME=`grep execs_done out/fuzzer_stats | awk '{print$3}'`
       } || {
@@ -706,7 +706,7 @@ test -e ../afl-qemu-trace && {
             unset AFL_PRELOAD
             unset AFL_COMPCOV_LEVEL
           } >>errors 2>&1
-          test -n "$( ls out/queue/id:000001* 2> /dev/null )" && {
+          test -n "$( ls out/queue/id:000001* 2>/dev/null )" && {
             $ECHO "$GREEN[+] afl-fuzz is working correctly with qemu_mode compcov"
           } || {
             echo CUT------------------------------------------------------------------CUT
@@ -727,14 +727,15 @@ test -e ../afl-qemu-trace && {
       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"
         {
-          export AFL_QEMU_PERSISTENT_ADDR=`expr 0x4$(nm test-instr | grep "T main" | awk '{print $1}' | sed 's/^.......//')`
+          export AFL_QEMU_PERSISTENT_ADDR=`expr 0x4$(nm test-instr | grep "T main" | awk '{print $1}' | sed 's/^.......//' )`
           export AFL_QEMU_PERSISTENT_GPR=1
           $ECHO "Info: AFL_QEMU_PERSISTENT_ADDR=$AFL_QEMU_PERSISTENT_ADDR <= $(nm test-instr | grep "T main" | awk '{print $1}')"
+          env|grep AFL_|sort
           file test-instr
           ../afl-fuzz -m ${MEM_LIMIT} -V10 -Q -i in -o out -- ./test-instr
           unset AFL_QEMU_PERSISTENT_ADDR
         } >>errors 2>&1
-        test -n "$( ls out/queue/id:000002* 2> /dev/null )" && {
+        test -n "$( ls out/queue/id:000002* 2>/dev/null )" && {
           $ECHO "$GREEN[+] afl-fuzz is working correctly with persistent qemu_mode"
           RUNTIMEP=`grep execs_done out/fuzzer_stats | awk '{print$3}'`
           test -n "$RUNTIME" -a -n "$RUNTIMEP" && {
@@ -835,12 +836,12 @@ test -d ../unicorn_mode/unicornafl && {
   test -e ../unicorn_mode/samples/simple/simple_target.bin -a -e ../unicorn_mode/samples/compcov_x64/compcov_target.bin && {
     {
       # travis workaround
-      PY=`type python | awk '{print $NF}'`
+      PY=`command -v python`
       test "$PY" = "/opt/pyenv/shims/python" -a -x /usr/bin/python && PY=/usr/bin/python
       mkdir -p in
       echo 0 > in/in
       $ECHO "$GREY[*] Using python binary $PY"
-      if ! $PY -c 'import unicornafl' 2> /dev/null ; then
+      if ! $PY -c 'import unicornafl' 2>/dev/null ; then
         $ECHO "$YELLOW[-] we cannot test unicorn_mode because it is not present"
         INCOMPLETE=1
       else
@@ -849,7 +850,7 @@ test -d ../unicorn_mode/unicornafl && {
         {
           ../afl-fuzz -m ${MEM_LIMIT} -V25 -U -i in -o out -d -- "$PY" ../unicorn_mode/samples/simple/simple_test_harness.py @@ >>errors 2>&1
         } >>errors 2>&1
-        test -n "$( ls out/queue/id:000002* 2> /dev/null )" && {
+        test -n "$( ls out/queue/id:000002* 2>/dev/null )" && {
           $ECHO "$GREEN[+] afl-fuzz is working correctly with unicorn_mode"
         } || {
           echo CUT------------------------------------------------------------------CUT
@@ -869,7 +870,7 @@ test -d ../unicorn_mode/unicornafl && {
           ../afl-fuzz -m ${MEM_LIMIT} -V35 -U -i in -o out -d -- "$PY" ../unicorn_mode/samples/compcov_x64/compcov_test_harness.py @@ >>errors 2>&1
           unset AFL_COMPCOV_LEVEL
         } >>errors 2>&1
-        test -n "$( ls out/queue/id:000001* 2> /dev/null )" && {
+        test -n "$( ls out/queue/id:000001* 2>/dev/null )" && {
           $ECHO "$GREEN[+] afl-fuzz is working correctly with unicorn_mode compcov"
         } || {
           echo CUT------------------------------------------------------------------CUT
diff --git a/unicorn_mode/build_unicorn_support.sh b/unicorn_mode/build_unicorn_support.sh
index 7b82055c..a8999dca 100755
--- a/unicorn_mode/build_unicorn_support.sh
+++ b/unicorn_mode/build_unicorn_support.sh
@@ -75,6 +75,7 @@ fi
 if [ "$PLT" = "Darwin" ]; then
   CORES=`sysctl -n hw.ncpu`
   TARCMD=tar
+  PYTHONBIN=python3
 fi
 
 if [ "$PLT" = "FreeBSD" ]; then
@@ -90,26 +91,27 @@ if [ "$PLT" = "NetBSD" ] || [ "$PLT" = "OpenBSD" ]; then
   TARCMD=gtar
 fi
 
+PREREQ_NOTFOUND=
 for i in $PYTHONBIN automake autoconf git $MAKECMD $TARCMD; do
 
-  T=`which "$i" 2>/dev/null`
+  T=`command -v "$i" 2>/dev/null`
 
   if [ "$T" = "" ]; then
 
     echo "[-] Error: '$i' not found. Run 'sudo apt-get install $i' or similar."
-    exit 1
+    PREREQ_NOTFOUND=1
 
   fi
 
 done
 
-if ! which $EASY_INSTALL > /dev/null; then
+if ! type $EASY_INSTALL > /dev/null; then
 
   # work around for unusual installs
   if [ '!' -e /usr/lib/python2.7/dist-packages/easy_install.py ] && [ '!' -e /usr/local/lib/python2.7/dist-packages/easy_install.py ] && [ '!' -e /usr/pkg/lib/python2.7/dist-packages/easy_install.py ]; then
 
     echo "[-] Error: Python setup-tools not found. Run 'sudo apt-get install python-setuptools'."
-    exit 1
+    PREREQ_NOTFOUND=1
 
   fi
 
@@ -118,10 +120,14 @@ fi
 if echo "$CC" | grep -qF /afl-; then
 
   echo "[-] Error: do not use afl-gcc or afl-clang to compile this tool."
-  exit 1
+  PREREQ_NOTFOUND=1
 
 fi
 
+if [ "$PREREQ_NOTFOUND" = "1" ]; then
+  exit 1
+fi
+
 echo "[+] All checks passed!"
 
 echo "[*] Making sure unicornafl is checked out"
@@ -176,7 +182,7 @@ cd ../samples/simple || exit 1
 
 # Run afl-showmap on the sample application. If anything comes out then it must have worked!
 unset AFL_INST_RATIO
-echo 0 | ../../../afl-showmap -U -m none -q -o .test-instr0 -- $PYTHONBIN simple_test_harness.py ./sample_inputs/sample1.bin || exit 1
+echo 0 | ../../../afl-showmap -U -m none -t 2000 -q -o .test-instr0 -- $PYTHONBIN simple_test_harness.py ./sample_inputs/sample1.bin || exit 1
 
 if [ -s .test-instr0 ]
 then