about summary refs log tree commit diff
diff options
context:
space:
mode:
authorvan Hauser <vh@thc.org>2023-08-09 18:29:25 +0000
committerGitHub <noreply@github.com>2023-08-09 18:29:25 +0000
commitfa44d8f79f03c0aab3cfea93c37b70edc367c1bb (patch)
treef39de203508117dcb50b66baa8fd335a887a9c54
parent18d9234dfe4b6db32a2da335834908e49300e5cd (diff)
parent55d696fbae435e0e69adf75cb2df1361186fb999 (diff)
downloadafl++-fa44d8f79f03c0aab3cfea93c37b70edc367c1bb.tar.gz
Merge pull request #1831 from AFLplusplus/dev
push to stable
-rw-r--r--GNUmakefile12
-rw-r--r--GNUmakefile.gcc_plugin10
-rw-r--r--GNUmakefile.llvm8
-rw-r--r--README.md3
-rw-r--r--custom_mutators/aflpp/standalone/aflpp-standalone.c1
-rw-r--r--docs/Changelog.md4
-rw-r--r--docs/afl-fuzz_approach.md4
-rw-r--r--docs/env_variables.md6
-rw-r--r--include/afl-fuzz.h6
-rw-r--r--include/afl-mutations.h21
-rw-r--r--include/config.h8
-rw-r--r--include/envs.h5
-rw-r--r--include/forkserver.h3
-rw-r--r--nyx_mode/LIBNYX_VERSION2
-rw-r--r--nyx_mode/PACKER_VERSION2
m---------nyx_mode/QEMU-Nyx0
-rw-r--r--nyx_mode/QEMU_NYX_VERSION2
-rw-r--r--nyx_mode/README.md27
m---------nyx_mode/libnyx0
m---------nyx_mode/packer0
-rw-r--r--src/afl-forkserver.c63
-rw-r--r--src/afl-fuzz-bitmap.c3
-rw-r--r--src/afl-fuzz-init.c105
-rw-r--r--src/afl-fuzz-one.c2
-rw-r--r--src/afl-fuzz-redqueen.c336
-rw-r--r--src/afl-fuzz-state.c7
-rw-r--r--src/afl-fuzz-stats.c9
-rw-r--r--src/afl-fuzz.c60
-rw-r--r--src/afl-showmap.c1
-rw-r--r--test/unittests/unit_rand.c1
30 files changed, 479 insertions, 232 deletions
diff --git a/GNUmakefile b/GNUmakefile
index 71011858..88816e85 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -91,9 +91,9 @@ ifneq "$(SYS)" "Darwin"
   #ifeq "$(HAVE_MARCHNATIVE)" "1"
   #  SPECIAL_PERFORMANCE += -march=native
   #endif
- ifndef DEBUG
-   CFLAGS_OPT += -D_FORTIFY_SOURCE=1
- endif
+ #ifndef DEBUG
+ #  CFLAGS_OPT += -D_FORTIFY_SOURCE=1
+ #endif
 else
   # On some odd MacOS system configurations, the Xcode sdk path is not set correctly
   SDK_LD = -L$(shell xcrun --show-sdk-path)/usr/lib
@@ -255,17 +255,17 @@ endif
 
 ifneq "$(findstring FreeBSD, $(SYS))" ""
   override CFLAGS  += -pthread
-  override LDFLAGS += -lpthread
+  override LDFLAGS += -lpthread -lm
 endif
 
 ifneq "$(findstring NetBSD, $(SYS))" ""
   override CFLAGS  += -pthread
-  override LDFLAGS += -lpthread
+  override LDFLAGS += -lpthread -lm
 endif
 
 ifneq "$(findstring OpenBSD, $(SYS))" ""
   override CFLAGS  += -pthread
-  override LDFLAGS += -lpthread
+  override LDFLAGS += -lpthread -lm
 endif
 
 COMM_HDR    = include/alloc-inl.h include/config.h include/debug.h include/types.h
diff --git a/GNUmakefile.gcc_plugin b/GNUmakefile.gcc_plugin
index 41face4c..16c98399 100644
--- a/GNUmakefile.gcc_plugin
+++ b/GNUmakefile.gcc_plugin
@@ -28,15 +28,17 @@ MAN_PATH    ?= $(PREFIX)/share/man/man8
 
 VERSION     = $(shell grep '^$(HASH)define VERSION ' ./config.h | cut -d '"' -f2)
 
-CFLAGS          ?= -O3 -g -funroll-loops -D_FORTIFY_SOURCE=1
+CFLAGS          ?= -O3 -g -funroll-loops
+# -D_FORTIFY_SOURCE=1
 CFLAGS_SAFE     := -Wall -Iinclude -Wno-pointer-sign \
                    -DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \
                    -DGCC_VERSION=\"$(GCCVER)\" -DGCC_BINDIR=\"$(GCCBINDIR)\" \
                    -Wno-unused-function
 override CFLAGS += $(CFLAGS_SAFE)
 
-CXXFLAGS    ?= -O3 -g -funroll-loops -D_FORTIFY_SOURCE=1
-CXXEFLAGS   := $(CXXFLAGS) -Wall -std=c++11
+CXXFLAGS    ?= -O3 -g -funroll-loops
+# -D_FORTIFY_SOURCE=1
+CXXEFLAGS   := $(CXXFLAGS) $(CPPFLAGS) -Wall -std=c++11
 
 CC          ?= gcc
 CXX         ?= g++
@@ -59,7 +61,7 @@ ifeq "$(findstring Foundation,$(shell $(CC) --version))" ""
 endif
 
 PLUGIN_BASE = "$(shell $(CC) -print-file-name=plugin)"
-PLUGIN_FLAGS = -fPIC -fno-rtti -I$(PLUGIN_BASE)/include -I$(PLUGIN_BASE)
+PLUGIN_FLAGS = -fPIC -fno-rtti -fno-exceptions -I$(PLUGIN_BASE)/include -I$(PLUGIN_BASE)
 HASH=\#
 
 GCCVER    = $(shell $(CC) --version 2>/dev/null | awk 'NR == 1 {print $$NF}')
diff --git a/GNUmakefile.llvm b/GNUmakefile.llvm
index f298060e..65786d8b 100644
--- a/GNUmakefile.llvm
+++ b/GNUmakefile.llvm
@@ -262,7 +262,8 @@ else
         AFL_CLANG_DEBUG_PREFIX =
 endif
 
-CFLAGS          ?= -O3 -funroll-loops -fPIC -D_FORTIFY_SOURCE=1
+CFLAGS          ?= -O3 -funroll-loops -fPIC
+# -D_FORTIFY_SOURCE=1
 CFLAGS_SAFE     := -Wall -g -Wno-cast-qual -Wno-variadic-macros -Wno-pointer-sign \
                    -I ./include/ -I ./instrumentation/ \
                    -DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \
@@ -287,7 +288,8 @@ ifdef AFL_TRACE_PC
   $(info Compile option AFL_TRACE_PC is deprecated, just set AFL_LLVM_INSTRUMENT=PCGUARD to activate when compiling targets )
 endif
 
-CXXFLAGS          ?= -O3 -funroll-loops -fPIC -D_FORTIFY_SOURCE=1
+CXXFLAGS          ?= -O3 -funroll-loops -fPIC
+# -D_FORTIFY_SOURCE=1
 override CXXFLAGS += -Wall -g -I ./include/ \
                      -DVERSION=\"$(VERSION)\" -Wno-variadic-macros -Wno-deprecated-copy-with-dtor \
                      -DLLVM_MINOR=$(LLVM_MINOR) -DLLVM_MAJOR=$(LLVM_MAJOR)
@@ -298,7 +300,7 @@ endif
 ifneq "$(LLVM_CONFIG)" ""
   CLANG_CFL += -I$(shell dirname $(LLVM_CONFIG))/../include
 endif
-CLANG_CPPFL  = `$(LLVM_CONFIG) --cxxflags` -fno-rtti -fPIC $(CXXFLAGS) -Wno-deprecated-declarations
+CLANG_CPPFL  = `$(LLVM_CONFIG) --cxxflags` -fno-rtti -fno-exceptions -fPIC $(CXXFLAGS) $(CPPFLAGS) -Wno-deprecated-declarations
 CLANG_LFL    = `$(LLVM_CONFIG) --ldflags` $(LDFLAGS)
 
 # wasm fuzzing: disable thread-local storage and unset LLVM debug flag
diff --git a/README.md b/README.md
index 05c662c1..b73cf2c1 100644
--- a/README.md
+++ b/README.md
@@ -15,6 +15,7 @@ AFL++ is maintained by:
 * Andrea Fioraldi <andreafioraldi@gmail.com>
 * Dominik Maier <mail@dmnk.co>
 * Heiko "hexcoder-" Eißfeldt <heiko.eissfeldt@hexco.de>
+* frida_mode is maintained by @Worksbutnottested
 * Documentation: Jana Aydinbas <jana.aydinbas@gmail.com>
 
 Originally developed by Michał "lcamtuf" Zalewski.
@@ -228,7 +229,7 @@ Thank you! (For people sending pull requests - please add yourself to this list
     Thomas Rooijakkers                    David Carlier
     Ruben ten Hove                        Joey Jiao
     fuzzah                                @intrigus-lgtm
-    Yaakov Saxon
+    Yaakov Saxon                          Sergej Schumilo
   ```
 
 </details>
diff --git a/custom_mutators/aflpp/standalone/aflpp-standalone.c b/custom_mutators/aflpp/standalone/aflpp-standalone.c
index 91bac4a8..361feaba 100644
--- a/custom_mutators/aflpp/standalone/aflpp-standalone.c
+++ b/custom_mutators/aflpp/standalone/aflpp-standalone.c
@@ -39,6 +39,7 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
   data->afl = calloc(1, sizeof(afl_state_t));
   data->afl->queue_cycle = 1;
   data->afl->fsrv.dev_urandom_fd = open("/dev/urandom", O_RDONLY);
+  if (data->afl->fsrv.dev_urandom_fd < 0) { PFATAL("Unable to open /dev/urandom"); }
   rand_set_seed(data->afl, getpid());
 
   return data;
diff --git a/docs/Changelog.md b/docs/Changelog.md
index d61ce8ec..76f98547 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -15,6 +15,10 @@
       command line tool! See custom_mutators/aflpp/standalone/
     - display the state of the fuzzing run in the UI :-)
     - fix timeout setting if '+' is used or a session is restarted
+    - -l X option to enable base64 transformation solving
+    - allow to disable CMPLOG with '-c -' (e.g. afl.rs enforces '-c 0' on
+      every instance which is counterproductive).
+
   - afl-cmin/afl-cmin.bash:
     - fixed a bug inherited from vanilla AFL where a coverage of
       map[123] = 11 would be the same as map[1123] = 1
diff --git a/docs/afl-fuzz_approach.md b/docs/afl-fuzz_approach.md
index cb173f10..7d18b178 100644
--- a/docs/afl-fuzz_approach.md
+++ b/docs/afl-fuzz_approach.md
@@ -419,8 +419,8 @@ the process. Be sure to consult this file especially if any UI elements are
 highlighted in red.
 
 The fuzzing process will continue until you press Ctrl-C. At a minimum, you want
-to allow the fuzzer to complete one queue cycle, which may take anywhere from a
-couple of hours to a week or so.
+to allow the fuzzer to at least one queue cycle without any new finds, which may
+take anywhere from a couple of hours to a week or so.
 
 There are three subdirectories created within the output directory and updated
 in real-time:
diff --git a/docs/env_variables.md b/docs/env_variables.md
index 0f0869d2..affc9e3c 100644
--- a/docs/env_variables.md
+++ b/docs/env_variables.md
@@ -365,6 +365,9 @@ checks or alter some of the more exotic semantics of the tool:
   - `AFL_EXIT_ON_SEED_ISSUES` will restore the vanilla afl-fuzz behavior which
     does not allow crashes or timeout seeds in the initial -i corpus.
 
+  - `AFL_CRASHING_SEEDS_AS_NEW_CRASH` will treat crashing seeds as new crash. these 
+    crashes will be written to crashes folder as op:dry_run, and orig:<seed_file_name>.
+
   - `AFL_EXIT_ON_TIME` causes afl-fuzz to terminate if no new paths were found
     within a specified period of time (in seconds). May be convenient for some
     types of automated jobs.
@@ -585,7 +588,8 @@ checks or alter some of the more exotic semantics of the tool:
     Note that this is not a compile time option but a runtime option :-)
 
   - Set `AFL_PIZZA_MODE` to 1 to enable the April 1st stats menu, set to -1
-    to disable although it is 1st of April.
+    to disable although it is 1st of April. 0 is the default and means enable
+    on the 1st of April automatically.
 
   - If you need a specific interval to update fuzzer_stats file, you can
     set `AFL_FUZZER_STATS_UPDATE_INTERVAL` to the interval in seconds you'd
diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h
index 27668da0..ef84a18c 100644
--- a/include/afl-fuzz.h
+++ b/include/afl-fuzz.h
@@ -1,3 +1,4 @@
+
 /*
    american fuzzy lop++ - fuzzer header
    ------------------------------------
@@ -401,7 +402,7 @@ typedef struct afl_env_vars {
       afl_exit_on_seed_issues, afl_try_affinity, afl_ignore_problems,
       afl_keep_timeouts, afl_no_crash_readme, afl_ignore_timeouts,
       afl_no_startup_calibration, afl_no_warn_instability,
-      afl_post_process_keep_original;
+      afl_post_process_keep_original, afl_crashing_seeds_as_new_crash;
 
   u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path,
       *afl_hang_tmout, *afl_forksrv_init_tmout, *afl_preload,
@@ -674,7 +675,8 @@ typedef struct afl_state {
   u32 cmplog_max_filesize;
   u32 cmplog_lvl;
   u32 colorize_success;
-  u8  cmplog_enable_arith, cmplog_enable_transform, cmplog_random_colorization;
+  u8  cmplog_enable_arith, cmplog_enable_transform,
+      cmplog_enable_xtreme_transform, cmplog_random_colorization;
 
   struct afl_pass_stat *pass_stats;
   struct cmp_map       *orig_cmp_map;
diff --git a/include/afl-mutations.h b/include/afl-mutations.h
index 0a9bbbf4..98ba6fcf 100644
--- a/include/afl-mutations.h
+++ b/include/afl-mutations.h
@@ -25,13 +25,14 @@
      u32 max_len - the maximum size the mutated buffer may grow to
 */
 
-#ifndef _ANDROID_ASHMEM_H
-  #define AFL_MUTATIONS_H
+#ifndef AFL_MUTATIONS_H
+#define AFL_MUTATIONS_H
 
-  #include <stdbool.h>
-  #include "afl-fuzz.h"
+#include <stdbool.h>
+#include <inttypes.h>
+#include "afl-fuzz.h"
 
-  #define MUT_STRATEGY_ARRAY_SIZE 256
+#define MUT_STRATEGY_ARRAY_SIZE 256
 
 enum {
 
@@ -77,7 +78,7 @@ enum {
 
 };
 
-  #define MUT_TXT_ARRAY_SIZE 200
+#define MUT_TXT_ARRAY_SIZE 200
 u32 text_array[MUT_TXT_ARRAY_SIZE] = {MUT_FLIPBIT,
                                       MUT_FLIPBIT,
                                       MUT_FLIPBIT,
@@ -279,7 +280,7 @@ u32 text_array[MUT_TXT_ARRAY_SIZE] = {MUT_FLIPBIT,
                                       MUT_SPLICE_INSERT,
                                       MUT_SPLICE_INSERT};
 
-  #define MUT_BIN_ARRAY_SIZE 256
+#define MUT_BIN_ARRAY_SIZE 256
 u32 binary_array[MUT_BIN_ARRAY_SIZE] = {MUT_FLIPBIT,
                                         MUT_FLIPBIT,
                                         MUT_FLIPBIT,
@@ -537,7 +538,7 @@ u32 binary_array[MUT_BIN_ARRAY_SIZE] = {MUT_FLIPBIT,
                                         MUT_SPLICE_INSERT,
                                         MUT_SPLICE_INSERT};
 
-  #define MUT_NORMAL_ARRAY_SIZE 77
+#define MUT_NORMAL_ARRAY_SIZE 77
 u32 normal_splice_array[MUT_NORMAL_ARRAY_SIZE] = {MUT_FLIPBIT,
                                                   MUT_FLIPBIT,
                                                   MUT_FLIPBIT,
@@ -616,7 +617,7 @@ u32 normal_splice_array[MUT_NORMAL_ARRAY_SIZE] = {MUT_FLIPBIT,
                                                   MUT_SPLICE_INSERT,
                                                   MUT_SPLICE_INSERT};
 
-  #define MUT_SPLICE_ARRAY_SIZE 81
+#define MUT_SPLICE_ARRAY_SIZE 81
 u32 full_splice_array[MUT_SPLICE_ARRAY_SIZE] = {MUT_FLIPBIT,
                                                 MUT_FLIPBIT,
                                                 MUT_FLIPBIT,
@@ -2456,7 +2457,7 @@ inline u32 afl_mutate(afl_state_t *afl, u8 *buf, u32 len, u32 steps,
         }
 
         char buf[20];
-        snprintf(buf, sizeof(buf), "%ld", val);
+        snprintf(buf, sizeof(buf), "%" PRId64, val);
         u32 old_len = off2 - off;
         u32 new_len = strlen(buf);
 
diff --git a/include/config.h b/include/config.h
index 7c29a674..df545583 100644
--- a/include/config.h
+++ b/include/config.h
@@ -60,10 +60,6 @@
  *
  */
 
-/* if TRANSFORM is enabled with '-l T', this additionally enables base64
-   encoding/decoding */
-// #define CMPLOG_SOLVE_TRANSFORM_BASE64
-
 /* If a redqueen pass finds more than one solution, try to combine them? */
 #define CMPLOG_COMBINE
 
@@ -71,10 +67,10 @@
 #define CMPLOG_CORPUS_PERCENT 5U
 
 /* Number of potential positions from which we decide if cmplog becomes
-   useless, default 8096 */
+   useless, default 12288 */
 #define CMPLOG_POSITIONS_MAX (12 * 1024)
 
-/* Maximum allowed fails per CMP value. Default: 128 */
+/* Maximum allowed fails per CMP value. Default: 96 */
 #define CMPLOG_FAIL_MAX 96
 
 /* -------------------------------------*/
diff --git a/include/envs.h b/include/envs.h
index edfd06e4..0007d5a8 100644
--- a/include/envs.h
+++ b/include/envs.h
@@ -35,6 +35,7 @@ static char *afl_environment_variables[] = {
     "AFL_COMPCOV_BINNAME",
     "AFL_COMPCOV_LEVEL",
     "AFL_CRASH_EXITCODE",
+    "AFL_CRASHING_SEEDS_AS_NEW_CRASH",
     "AFL_CUSTOM_MUTATOR_LIBRARY",
     "AFL_CUSTOM_MUTATOR_ONLY",
     "AFL_CUSTOM_INFO_PROGRAM",
@@ -189,6 +190,10 @@ static char *afl_environment_variables[] = {
     "AFL_MAX_DET_EXTRAS",
     "AFL_NO_X86",  // not really an env but we dont want to warn on it
     "AFL_NOOPT",
+    "AFL_NYX_AUX_SIZE",
+    "AFL_NYX_DISABLE_SNAPSHOT_MODE",
+    "AFL_NYX_LOG",
+    "AFL_NYX_REUSE_SNAPSHOT",
     "AFL_PASSTHROUGH",
     "AFL_PATH",
     "AFL_PERFORMANCE_FILE",
diff --git a/include/forkserver.h b/include/forkserver.h
index f5069ce2..5e498c56 100644
--- a/include/forkserver.h
+++ b/include/forkserver.h
@@ -86,6 +86,8 @@ typedef struct {
                                  uint32_t size);
 
   bool (*nyx_remove_work_dir)(const char *workdir);
+  bool (*nyx_config_set_aux_buffer_size)(void    *config,
+                                         uint32_t aux_buffer_size);
 
 } nyx_plugin_handler_t;
 
@@ -197,6 +199,7 @@ typedef struct afl_forkserver {
   char                 *nyx_aux_string;
   bool                  nyx_use_tmp_workdir;
   char                 *nyx_tmp_workdir_path;
+  s32                   nyx_log_fd;
 #endif
 
 } afl_forkserver_t;
diff --git a/nyx_mode/LIBNYX_VERSION b/nyx_mode/LIBNYX_VERSION
index ed88ec10..a4ffd230 100644
--- a/nyx_mode/LIBNYX_VERSION
+++ b/nyx_mode/LIBNYX_VERSION
@@ -1 +1 @@
-c8a72dc
+8291ef4
diff --git a/nyx_mode/PACKER_VERSION b/nyx_mode/PACKER_VERSION
index 7db88233..cc20a3b6 100644
--- a/nyx_mode/PACKER_VERSION
+++ b/nyx_mode/PACKER_VERSION
@@ -1 +1 @@
-202bace
+bcf3e24
diff --git a/nyx_mode/QEMU-Nyx b/nyx_mode/QEMU-Nyx
-Subproject 60c216bc9e4c79834716d4099993d8397a3a8fd
+Subproject 874fa033d117a3e9931245cb9e82836a4abc042
diff --git a/nyx_mode/QEMU_NYX_VERSION b/nyx_mode/QEMU_NYX_VERSION
index 98cb134f..d0a435a4 100644
--- a/nyx_mode/QEMU_NYX_VERSION
+++ b/nyx_mode/QEMU_NYX_VERSION
@@ -1 +1 @@
-60c216bc9e
+874fa033d1
diff --git a/nyx_mode/README.md b/nyx_mode/README.md
index eee7d363..aee9879e 100644
--- a/nyx_mode/README.md
+++ b/nyx_mode/README.md
@@ -150,12 +150,12 @@ afl-cmin -i in_dir -o out_dir -X -- ./PACKAGE-DIRECTORY
 
 On each program startup of one the AFL++ tools in Nyx mode, a Nyx VM is spawned, and a bootstrapping procedure is performed inside the VM to prepare the target environment. As a consequence, due to the bootstrapping procedure, the launch performance is much slower compared to other modes. However, this can be optimized by reusing an existing fuzzing snapshot to avoid the slow re-execution of the bootstrap procedure. 
 
-A fuzzing snapshot is automatically created and stored in the output directory at `out_dir/workdir/snapshot/` by the first parent process of `afl-fuzz` if parallel mode is used. To enable this feature, set the path to an existing snapshot directory in the `NYX_REUSE_SNAPSHOT` environment variable and use the tools as usual:
+A fuzzing snapshot is automatically created and stored in the output directory at `out_dir/workdir/snapshot/` by the first parent process of `afl-fuzz` if parallel mode is used. To enable this feature, set the path to an existing snapshot directory in the `AFL_NYX_REUSE_SNAPSHOT` environment variable and use the tools as usual:
 
 ```shell 
 afl-fuzz -i ./in_dir -o ./out_dir -Y -M 0 ./PACKAGE-DIRECTORY
 
-NYX_REUSE_SNAPSHOT=./out_dir/workdir/snapshot/ afl-analyze -i in_file -X  -- ./PACKAGE-DIRECTORY
+AFL_NYX_REUSE_SNAPSHOT=./out_dir/workdir/snapshot/ afl-analyze -i in_file -X  -- ./PACKAGE-DIRECTORY
 ```
 
 
@@ -311,7 +311,28 @@ command:
 ```
 
 If you want to disable fast snapshots (except for crashes), you can simply set
-the `NYX_DISABLE_SNAPSHOT_MODE` environment variable.
+the `AFL_NYX_DISABLE_SNAPSHOT_MODE` environment variable.
+
+### Nyx crash reports
+
+If the Nyx agent detects a crash in the target application, it can pass 
+additional information on that crash to AFL++ (assuming that the agent
+implements this feature). For each saved crashing input AFL++ will also create
+an additional file in the `crashes` directory with a `.log` file extension.
+Crash reports generated by the default agent shipped with the Nyx packer will
+contain information such as the faulting address and signal number.
+Additionally, if the target is compiled with AddressSanitizer, the crash report
+will also contain the entire ASan report. 
+
+From a technical perspective, the crash report is passed from QEMU-Nyx to AFL++
+via a shared memory region called Nyx Auxiliary Buffer which is by default 4096
+bytes in size. In this shared memory region a specific amount is reserved for
+the header (1408 bytes) and the remaining bytes can be used to transfer crash
+reports (also the `hprintf` feature utilizes the very same shared memory for 
+transferring data). By default a crash report will be truncated to 2688 bytes.
+However, if you want to increase the size of the shared memory region, you can
+set the `AFL_NYX_AUX_SIZE` environment variable to a higher value (keep in
+mind that this value must be a multiple of 4096).
 
 ### Run AFL++Nyx with a custom agent
 
diff --git a/nyx_mode/libnyx b/nyx_mode/libnyx
-Subproject 2da7f08b6e0267ccfe64e1320b24cdb29223459
+Subproject 8291ef4cb4f1d4bfe3026fe198167fd5c98e3a1
diff --git a/nyx_mode/packer b/nyx_mode/packer
-Subproject 202bace888d237e4e8f4507d0eba6791a811554
+Subproject bcf3e248b660764f48af54232a3388389a2dfc2
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index ba7cdd66..9da096f7 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -129,6 +129,10 @@ nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary) {
   plugin->nyx_remove_work_dir = dlsym(handle, "nyx_remove_work_dir");
   if (plugin->nyx_remove_work_dir == NULL) { goto fail; }
 
+  plugin->nyx_config_set_aux_buffer_size =
+      dlsym(handle, "nyx_config_set_aux_buffer_size");
+  if (plugin->nyx_config_set_aux_buffer_size == NULL) { goto fail; }
+
   OKF("libnyx plugin is ready!");
   return plugin;
 
@@ -160,6 +164,8 @@ void afl_nyx_runner_kill(afl_forkserver_t *fsrv) {
 
     }
 
+    if (fsrv->nyx_log_fd >= 0) { close(fsrv->nyx_log_fd); }
+
   }
 
 }
@@ -214,6 +220,7 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
   fsrv->nyx_bind_cpu_id = 0xFFFFFFFF;
   fsrv->nyx_use_tmp_workdir = false;
   fsrv->nyx_tmp_workdir_path = NULL;
+  fsrv->nyx_log_fd = -1;
 #endif
 
   // this structure needs default so we initialize it if this was not done
@@ -571,6 +578,22 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
     fsrv->nyx_handlers->nyx_config_set_input_buffer_write_protection(nyx_config,
                                                                      true);
 
+    char *nyx_log_path = getenv("AFL_NYX_LOG");
+    if (nyx_log_path) {
+
+      fsrv->nyx_log_fd =
+          open(nyx_log_path, O_CREAT | O_TRUNC | O_WRONLY, DEFAULT_PERMISSION);
+      if (fsrv->nyx_log_fd < 0) {
+
+        NYX_PRE_FATAL(fsrv, "AFL_NYX_LOG path could not be written");
+
+      }
+
+      fsrv->nyx_handlers->nyx_config_set_hprintf_fd(nyx_config,
+                                                    fsrv->nyx_log_fd);
+
+    }
+
     if (fsrv->nyx_standalone) {
 
       fsrv->nyx_handlers->nyx_config_set_process_role(nyx_config, StandAlone);
@@ -589,23 +612,36 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
 
     }
 
-    if (getenv("NYX_REUSE_SNAPSHOT") != NULL) {
+    if (getenv("AFL_NYX_AUX_SIZE") != NULL) {
+
+      if (fsrv->nyx_handlers->nyx_config_set_aux_buffer_size(
+              nyx_config, atoi(getenv("AFL_NYX_AUX_SIZE"))) != 1) {
+
+        NYX_PRE_FATAL(fsrv,
+                      "Invalid AFL_NYX_AUX_SIZE value set (must be a multiple "
+                      "of 4096) ...");
+
+      }
+
+    }
+
+    if (getenv("AFL_NYX_REUSE_SNAPSHOT") != NULL) {
 
-      if (access(getenv("NYX_REUSE_SNAPSHOT"), F_OK) == -1) {
+      if (access(getenv("AFL_NYX_REUSE_SNAPSHOT"), F_OK) == -1) {
 
-        NYX_PRE_FATAL(fsrv, "NYX_REUSE_SNAPSHOT path does not exist");
+        NYX_PRE_FATAL(fsrv, "AFL_NYX_REUSE_SNAPSHOT path does not exist");
 
       }
 
       /* stupid sanity check to avoid passing an empty or invalid snapshot
        * directory */
       char *snapshot_file_path =
-          alloc_printf("%s/global.state", getenv("NYX_REUSE_SNAPSHOT"));
+          alloc_printf("%s/global.state", getenv("AFL_NYX_REUSE_SNAPSHOT"));
       if (access(snapshot_file_path, R_OK) == -1) {
 
-        NYX_PRE_FATAL(
-            fsrv,
-            "NYX_REUSE_SNAPSHOT path does not contain a valid Nyx snapshot");
+        NYX_PRE_FATAL(fsrv,
+                      "AFL_NYX_REUSE_SNAPSHOT path does not contain a valid "
+                      "Nyx snapshot");
 
       }
 
@@ -617,13 +653,14 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
       char *workdir_snapshot_path =
           alloc_printf("%s/workdir/snapshot", outdir_path_absolute);
       char *reuse_snapshot_path_real =
-          realpath(getenv("NYX_REUSE_SNAPSHOT"), NULL);
+          realpath(getenv("AFL_NYX_REUSE_SNAPSHOT"), NULL);
 
       if (strcmp(workdir_snapshot_path, reuse_snapshot_path_real) == 0) {
 
-        NYX_PRE_FATAL(fsrv,
-                      "NYX_REUSE_SNAPSHOT path is located in current workdir "
-                      "(use another output directory)");
+        NYX_PRE_FATAL(
+            fsrv,
+            "AFL_NYX_REUSE_SNAPSHOT path is located in current workdir "
+            "(use another output directory)");
 
       }
 
@@ -631,7 +668,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
       ck_free(workdir_snapshot_path);
 
       fsrv->nyx_handlers->nyx_config_set_reuse_snapshot_path(
-          nyx_config, getenv("NYX_REUSE_SNAPSHOT"));
+          nyx_config, getenv("AFL_NYX_REUSE_SNAPSHOT"));
 
     }
 
@@ -653,7 +690,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
         fsrv->nyx_handlers->nyx_get_bitmap_buffer(fsrv->nyx_runner);
 
     fsrv->nyx_handlers->nyx_option_set_reload_mode(
-        fsrv->nyx_runner, getenv("NYX_DISABLE_SNAPSHOT_MODE") == NULL);
+        fsrv->nyx_runner, getenv("AFL_NYX_DISABLE_SNAPSHOT_MODE") == NULL);
     fsrv->nyx_handlers->nyx_option_apply(fsrv->nyx_runner);
 
     fsrv->nyx_handlers->nyx_option_set_timeout(fsrv->nyx_runner, 2, 0);
diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c
index fb8a1d4b..87157cad 100644
--- a/src/afl-fuzz-bitmap.c
+++ b/src/afl-fuzz-bitmap.c
@@ -533,7 +533,8 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
     close(fd);
     add_to_queue(afl, queue_fn, len, 0);
 
-    if (unlikely(afl->fuzz_mode) && likely(afl->switch_fuzz_mode)) {
+    if (unlikely(afl->fuzz_mode) &&
+        likely(afl->switch_fuzz_mode && !afl->non_instrumented_mode)) {
 
       if (afl->afl_env.afl_no_ui) {
 
diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c
index 24fd7077..5a530821 100644
--- a/src/afl-fuzz-init.c
+++ b/src/afl-fuzz-init.c
@@ -1058,7 +1058,19 @@ void perform_dry_run(afl_state_t *afl) {
 
         } else {
 
-          WARNF("Test case '%s' results in a crash, skipping", fn);
+          if (afl->afl_env.afl_crashing_seeds_as_new_crash) {
+
+            WARNF(
+                "Test case '%s' results in a crash, "
+                "as AFL_CRASHING_SEEDS_AS_NEW_CRASH is set, "
+                "saving as a new crash",
+                fn);
+
+          } else {
+
+            WARNF("Test case '%s' results in a crash, skipping", fn);
+
+          }
 
         }
 
@@ -1078,36 +1090,95 @@ void perform_dry_run(afl_state_t *afl) {
 
         }
 
-        q->disabled = 1;
-        q->perf_score = 0;
+        /* Crashing seeds will be regarded as new crashes on startup */
+        if (afl->afl_env.afl_crashing_seeds_as_new_crash) {
 
-        u32 i = 0;
-        while (unlikely(i < afl->queued_items && afl->queue_buf[i] &&
-                        afl->queue_buf[i]->disabled)) {
+          ++afl->total_crashes;
 
-          ++i;
+          if (likely(!afl->non_instrumented_mode)) {
 
-        }
+            classify_counts(&afl->fsrv);
+
+            simplify_trace(afl, afl->fsrv.trace_bits);
+
+            if (!has_new_bits(afl, afl->virgin_crash)) { break; }
+
+          }
+
+          if (unlikely(!afl->saved_crashes) &&
+              (afl->afl_env.afl_no_crash_readme != 1)) {
+
+            write_crash_readme(afl);
+
+          }
+
+          u8  crash_fn[PATH_MAX];
+          u8 *use_name = strstr(q->fname, ",orig:");
+
+          afl->stage_name = "dry_run";
+          afl->stage_short = "dry_run";
+
+#ifndef SIMPLE_FILES
 
-        if (i < afl->queued_items && afl->queue_buf[i]) {
+          snprintf(crash_fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s",
+                   afl->out_dir, afl->saved_crashes, afl->fsrv.last_kill_signal,
+                   describe_op(afl, 0,
+                               NAME_MAX - strlen("id:000000,sig:00,") -
+                                   strlen(use_name)),
+                   use_name);
 
-          afl->queue = afl->queue_buf[i];
+#else
+
+          snprintf(crash_fn, PATH_MAX, "%s/crashes/id_%06llu_%02u",
+                   afl->out_dir, afl->saved_crashes,
+                   afl->fsrv.last_kill_signal);
+
+#endif
+
+          ++afl->saved_crashes;
+
+          fd = open(crash_fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
+          if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", crash_fn); }
+          ck_write(fd, use_mem, read_len, crash_fn);
+          close(fd);
+
+          afl->last_crash_time = get_cur_time();
+          afl->last_crash_execs = afl->fsrv.total_execs;
 
         } else {
 
-          afl->queue = afl->queue_buf[0];
+          u32 i = 0;
+          while (unlikely(i < afl->queued_items && afl->queue_buf[i] &&
+                          afl->queue_buf[i]->disabled)) {
 
-        }
+            ++i;
+
+          }
+
+          if (i < afl->queued_items && afl->queue_buf[i]) {
 
-        afl->max_depth = 0;
-        for (i = 0; i < afl->queued_items && likely(afl->queue_buf[i]); i++) {
+            afl->queue = afl->queue_buf[i];
 
-          if (!afl->queue_buf[i]->disabled &&
-              afl->queue_buf[i]->depth > afl->max_depth)
-            afl->max_depth = afl->queue_buf[i]->depth;
+          } else {
+
+            afl->queue = afl->queue_buf[0];
+
+          }
+
+          afl->max_depth = 0;
+          for (i = 0; i < afl->queued_items && likely(afl->queue_buf[i]); i++) {
+
+            if (!afl->queue_buf[i]->disabled &&
+                afl->queue_buf[i]->depth > afl->max_depth)
+              afl->max_depth = afl->queue_buf[i]->depth;
+
+          }
 
         }
 
+        q->disabled = 1;
+        q->perf_score = 0;
+
         break;
 
       case FSRV_RUN_ERROR:
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index 8ee50bbf..2ad4697e 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -2995,7 +2995,7 @@ havoc_stage:
           // fprintf(stderr, "val: %u-%u = %ld\n", off, off2, val);
 
           char buf[20];
-          snprintf(buf, sizeof(buf), "%ld", val);
+          snprintf(buf, sizeof(buf), "%" PRId64, val);
 
           // fprintf(stderr, "BEFORE: %s\n", out_buf);
 
diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c
index 73e188e7..db4991db 100644
--- a/src/afl-fuzz-redqueen.c
+++ b/src/afl-fuzz-redqueen.c
@@ -129,7 +129,6 @@ static struct range *pop_biggest_range(struct range **ranges) {
 }
 
 #ifdef _DEBUG
-// static int  logging = 0;
 static void dump(char *txt, u8 *buf, u32 len) {
 
   u32 i;
@@ -140,6 +139,7 @@ static void dump(char *txt, u8 *buf, u32 len) {
 
 }
 
+/*
 static void dump_file(char *path, char *name, u32 counter, u8 *buf, u32 len) {
 
   char fn[4096];
@@ -155,6 +155,8 @@ static void dump_file(char *path, char *name, u32 counter, u8 *buf, u32 len) {
 
 }
 
+*/
+
 #endif
 
 static u8 get_exec_checksum(afl_state_t *afl, u8 *buf, u32 len, u64 *cksum) {
@@ -571,7 +573,6 @@ static u8 its_fuzz(afl_state_t *afl, u8 *buf, u32 len, u8 *status) {
 
 }
 
-// #ifdef CMPLOG_SOLVE_TRANSFORM
 static int strntoll(const char *str, size_t sz, char **end, int base,
                     long long *out) {
 
@@ -656,7 +657,6 @@ static int is_hex(const char *str) {
 
 }
 
-#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64
 // tests 4 bytes at location
 static int is_base64(const char *str) {
 
@@ -732,12 +732,14 @@ static u32 from_base64(u8 *src, u8 *dst, u32 dst_len) {
 
 }
 
-static void to_base64(u8 *src, u8 *dst, u32 dst_len) {
+static u32 to_base64(u8 *src, u8 *dst, u32 dst_len) {
 
   u32 i, j, v;
-  u32 len = (dst_len >> 2) * 3;
+  //  u32 len = (dst_len >> 2) * 3;
+  u32 len = (dst_len / 3) * 4;
+  if (dst_len % 3) len += 4;
 
-  for (i = 0, j = 0; i < len; i += 3, j += 4) {
+  for (i = 0, j = 0; j < len; i += 3, j += 4) {
 
     v = src[i];
     v = i + 1 < len ? v << 8 | src[i + 1] : v << 8;
@@ -745,7 +747,8 @@ static void to_base64(u8 *src, u8 *dst, u32 dst_len) {
 
     dst[j] = base64_encode_table[(v >> 18) & 0x3F];
     dst[j + 1] = base64_encode_table[(v >> 12) & 0x3F];
-    if (i + 1 < len) {
+
+    if (i + 1 < dst_len) {
 
       dst[j + 2] = base64_encode_table[(v >> 6) & 0x3F];
 
@@ -755,7 +758,7 @@ static void to_base64(u8 *src, u8 *dst, u32 dst_len) {
 
     }
 
-    if (i + 2 < len) {
+    if (i + 2 < dst_len) {
 
       dst[j + 3] = base64_encode_table[v & 0x3F];
 
@@ -767,11 +770,10 @@ static void to_base64(u8 *src, u8 *dst, u32 dst_len) {
 
   }
 
-}
-
-#endif
+  dst[len] = 0;
+  return len;
 
-// #endif
+}
 
 static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
                               u64 pattern, u64 repl, u64 o_pattern,
@@ -797,42 +799,54 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
 
   }
 
-  // fprintf(stderr,
-  //         "Encode: %llx->%llx into %llx(<-%llx) at idx=%u "
-  //         "taint_len=%u shape=%u attr=%u\n",
-  //         o_pattern, pattern, repl, changed_val, idx, taint_len,
-  //         hshape, attr);
+  /*
+  fprintf(stderr,
+          "Encode: %llx->%llx into %llx(<-%llx) at idx=%u "
+          "taint_len=%u shape=%u attr=%u\n",
+          o_pattern, pattern, repl, changed_val, idx, taint_len,
+          hshape, attr);
+  */
 
-  // #ifdef CMPLOG_SOLVE_TRANSFORM
   //  reverse atoi()/strnu?toll() is expensive, so we only to it in lvl 3
   if (afl->cmplog_enable_transform && (lvl & LVL3)) {
 
     u8                *endptr;
     u8                 use_num = 0, use_unum = 0;
-    unsigned long long unum;
-    long long          num;
+    unsigned long long unum = 0;
+    long long          num = 0;
+
+    // if (afl->queue_cur->is_ascii) {
+
+    // we first check if our input are ascii numbers that are transformed to
+    // an integer and used for comparison:
 
-    if (afl->queue_cur->is_ascii) {
+    endptr = buf_8;
+    if (strntoll(buf_8, len - idx, (char **)&endptr, 0, &num)) {
 
-      endptr = buf_8;
-      if (strntoll(buf_8, len - idx, (char **)&endptr, 0, &num)) {
+      if (!strntoull(buf_8, len - idx, (char **)&endptr, 0, &unum)) {
 
-        if (!strntoull(buf_8, len - idx, (char **)&endptr, 0, &unum))
-          use_unum = 1;
+        use_unum = 1;
 
-      } else
+      }
+
+    } else {
 
-        use_num = 1;
+      use_num = 1;
 
     }
 
+    //}
+
 #ifdef _DEBUG
     if (idx == 0)
-      fprintf(stderr, "ASCII is=%u use_num=%u use_unum=%u idx=%u %llx==%llx\n",
-              afl->queue_cur->is_ascii, use_num, use_unum, idx, num, pattern);
+      fprintf(stderr,
+              "ASCII is=%u use_num=%u>%lld use_unum=%u>%llu idx=%u "
+              "pattern=0x%llx\n",
+              afl->queue_cur->is_ascii, use_num, num, use_unum, unum, idx,
+              pattern);
 #endif
 
-    // num is likely not pattern as atoi("AAA") will be zero...
+    // atoi("AAA") == 0 so !num means we have to investigate
     if (use_num && ((u64)num == pattern || !num)) {
 
       u8     tmp_buf[32];
@@ -961,10 +975,12 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
       // test for arithmetic, eg. "if ((user_val - 0x1111) == 0x1234) ..."
       s64 diff = pattern - b_val;
       s64 o_diff = o_pattern - o_b_val;
-      /* fprintf(stderr, "DIFF1 idx=%03u shape=%02u %llx-%llx=%lx\n", idx,
-                 hshape, o_pattern, o_b_val, o_diff);
-         fprintf(stderr, "DIFF1 %016llx %llx-%llx=%lx\n", repl, pattern,
-                 b_val, diff); */
+      /*
+             fprintf(stderr, "DIFF1 idx=%03u shape=%02u %llx-%llx=%lx\n", idx,
+                       hshape, o_pattern, o_b_val, o_diff);
+               fprintf(stderr, "DIFF1 %016llx %llx-%llx=%lx\n", repl, pattern,
+                       b_val, diff);
+      */
       if (diff == o_diff && diff) {
 
         // this could be an arithmetic transformation
@@ -1275,7 +1291,6 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
   //       16 = modified float, 32 = modified integer (modified = wont match
   //                                                   in original buffer)
 
-  // #ifdef CMPLOG_SOLVE_ARITHMETIC
   if (!afl->cmplog_enable_arith || lvl < LVL3 || attr == IS_TRANSFORM) {
 
     return 0;
@@ -2009,8 +2024,14 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
   its_len = MIN(its_len, taint_len);
   u32 saved_its_len = its_len;
 
+  // fprintf(stderr, "its_len=%u repl=%s\n", its_len, repl);
+
+  if (its_len <= 1) { return 0; }
+
   if (lvl & LVL3) {
 
+    if (memcmp(changed_val, repl, its_len) != 0) { return 0; }
+
     u32 max_to = MIN(4U, idx);
     if (!(lvl & LVL1) && max_to) { from = 1; }
     to = max_to;
@@ -2021,27 +2042,32 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
   (void)(j);
 
 #ifdef _DEBUG
-  fprintf(stderr, "RTN T idx=%u lvl=%02x is_txt=%u shape=%u/%u ", idx, lvl,
-          o->v0_len >= 0x80 ? 1 : 0, hshape, l0);
-  for (j = 0; j < 8; j++)
-    fprintf(stderr, "%02x", orig_buf[idx + j]);
-  fprintf(stderr, " -> ");
-  for (j = 0; j < 8; j++)
-    fprintf(stderr, "%02x", o_pattern[j]);
-  fprintf(stderr, " <= ");
-  for (j = 0; j < 8; j++)
-    fprintf(stderr, "%02x", repl[j]);
-  fprintf(stderr, "\n");
-  fprintf(stderr, "                ");
-  for (j = 0; j < 8; j++)
-    fprintf(stderr, "%02x", buf[idx + j]);
-  fprintf(stderr, " -> ");
-  for (j = 0; j < 8; j++)
-    fprintf(stderr, "%02x", pattern[j]);
-  fprintf(stderr, " <= ");
-  for (j = 0; j < 8; j++)
-    fprintf(stderr, "%02x", changed_val[j]);
-  fprintf(stderr, "\n");
+  if (idx == 0) {
+
+    fprintf(stderr, "RTN T idx=%u lvl=%02x is_txt=%u shape=%u/%u ", idx, lvl,
+            o->v0_len >= 0x80 ? 1 : 0, hshape, l0);
+    for (j = 0; j < 8; j++)
+      fprintf(stderr, "%02x", orig_buf[idx + j]);
+    fprintf(stderr, " -> ");
+    for (j = 0; j < 8; j++)
+      fprintf(stderr, "%02x", o_pattern[j]);
+    fprintf(stderr, " <= ");
+    for (j = 0; j < 8; j++)
+      fprintf(stderr, "%02x", repl[j]);
+    fprintf(stderr, "\n");
+    fprintf(stderr, "                ");
+    for (j = 0; j < 8; j++)
+      fprintf(stderr, "%02x", buf[idx + j]);
+    fprintf(stderr, " -> ");
+    for (j = 0; j < 8; j++)
+      fprintf(stderr, "%02x", pattern[j]);
+    fprintf(stderr, " <= ");
+    for (j = 0; j < 8; j++)
+      fprintf(stderr, "%02x", changed_val[j]);
+    fprintf(stderr, "\n");
+
+  }
+
 #endif
 
   // Try to match the replace value up to 4 bytes before the current idx.
@@ -2050,6 +2076,9 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
   //     if (memcmp(user_val, "TEST-VALUE") == 0) ...
   // We only do this in lvl 3, otherwise we only do direct matching
 
+  // fprintf(stderr, "XXXX FROMB64 saved_idx=%u its_len=%u from=%u to=%u FROMHEX
+  // repl=%s\n", saved_idx, saved_its_len, from, to, repl);
+
   for (pre = from; pre <= to; pre++) {
 
     if (*status != 1 && (!pre || !memcmp(buf + saved_idx - pre, repl, pre))) {
@@ -2089,9 +2118,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
   if (afl->cmplog_enable_transform && (lvl & LVL3)) {
 
     u32 toupper = 0, tolower = 0, xor = 0, arith = 0, tohex = 0, fromhex = 0;
-#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64
     u32 tob64 = 0, fromb64 = 0;
-#endif
     u32 from_0 = 0, from_x = 0, from_X = 0, from_slash = 0, from_up = 0;
     u32 to_0 = 0, to_x = 0, to_slash = 0, to_up = 0;
     u8  xor_val[32], arith_val[32], tmp[48];
@@ -2144,7 +2171,8 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
 
       }
 
-      if (i < 16 && is_hex(repl + (i << 1))) {
+      if (afl->cmplog_enable_xtreme_transform && i < 16 &&
+          is_hex(repl + (i << 1))) {
 
         ++tohex;
 
@@ -2163,9 +2191,9 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
 
       }
 
-      if ((i % 2)) {
+      if (afl->cmplog_enable_xtreme_transform && (i % 2) == 1) {
 
-        if (len > idx + i + 1 && is_hex(orig_buf + idx + i)) {
+        if (len > idx + i + 1 && is_hex(orig_buf + idx + i - 1)) {
 
           fromhex += 2;
 
@@ -2187,20 +2215,23 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
 
       }
 
-#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64
-      if (i % 3 == 2 && i < 24) {
+      if (afl->cmplog_enable_xtreme_transform) {
 
-        if (is_base64(repl + ((i / 3) << 2))) tob64 += 3;
+        if (i % 3 == 2 && i < 24) {
 
-      }
+          if (is_base64(repl + ((i / 3) << 2))) tob64 += 3;
 
-      if (i % 4 == 3 && i < 24) {
+        }
 
-        if (is_base64(orig_buf + idx + i - 3)) fromb64 += 4;
+        // fprintf(stderr, "X FROMB64 idx=%u i=%u repl=%s\n", saved_idx, i,
+        // repl);
+        if (i % 4 == 3 && i < 24) {
 
-      }
+          if (is_base64(orig_buf + idx + i - 3)) fromb64 += 4;
 
-#endif
+        }
+
+      }
 
       if ((o_pattern[i] ^ orig_buf[idx + i]) == xor_val[i] && xor_val[i]) {
 
@@ -2229,45 +2260,70 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
       }
 
 #ifdef _DEBUG
-      fprintf(stderr,
-              "RTN idx=%u loop=%u xor=%u arith=%u tolower=%u toupper=%u "
-              "tohex=%u fromhex=%u to_0=%u to_slash=%u to_x=%u "
-              "from_0=%u from_slash=%u from_x=%u\n",
-              idx, i, xor, arith, tolower, toupper, tohex, fromhex, to_0,
-              to_slash, to_x, from_0, from_slash, from_x);
-  #ifdef CMPLOG_SOLVE_TRANSFORM_BASE64
-      fprintf(stderr, "RTN idx=%u loop=%u tob64=%u from64=%u\n", tob64,
-              fromb64);
-  #endif
+      if (idx == 0) {
+
+        fprintf(stderr, "RTN Z %s %s %s %s repl=%s\n", buf, pattern, orig_buf,
+                o_pattern, repl);
+        fprintf(
+            stderr,
+            "RTN Z idx=%u len=%u loop=%u xor=%u arith=%u tolower=%u toupper=%u "
+            "tohex=%u fromhex=%u to_0=%u to_slash=%u to_x=%u "
+            "from_0=%u from_slash=%u from_x=%u\n",
+            idx, its_len, i, xor, arith, tolower, toupper, tohex, fromhex, to_0,
+            to_slash, to_x, from_0, from_slash, from_x);
+        if (afl->cmplog_enable_xtreme_transform) {
+
+          fprintf(stderr, "RTN Z idx=%u loop=%u tob64=%u from64=%u\n", idx, i,
+                  tob64, fromb64);
+
+        }
+
+      }
+
 #endif
 
-#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64
-      // input is base64 and converted to binary? convert repl to base64!
-      if ((i % 4) == 3 && i < 24 && fromb64 > i) {
+      if (afl->cmplog_enable_xtreme_transform) {
 
-        to_base64(repl, tmp, i + 1);
-        memcpy(buf + idx, tmp, i + 1);
-        if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
-        // fprintf(stderr, "RTN ATTEMPT fromb64 %u result %u\n", fromb64,
-        // *status);
+        // input is base64 and converted to binary? convert repl to base64!
+        // fprintf(stderr, "FROMB64 idx=%u i=%u %% 4 == 3 && i < 24 &&
+        // fromb64=%u > i, repl=%s\n", saved_idx, i, fromb64, repl);
+        if ((i % 4) == 3 && i < 24 && fromb64 > i) {
 
-      }
+          for (u32 hlen = i; hlen + saved_idx < len && hlen <= its_len;
+               ++hlen) {
 
-      // input is converted to base64? decode repl with base64!
-      if ((i % 3) == 2 && i < 24 && tob64 > i) {
+            u32 res = to_base64(repl, tmp, hlen);
+            // fprintf(stderr, "FROMB64 GOGO! idx=%u repl=%s tmp[%u]=%s
+            // hlen=%u\n", saved_idx, repl, res, tmp, hlen);
+            if (res + saved_idx < len) {
 
-        u32 olen = from_base64(repl, tmp, i + 1);
-        memcpy(buf + idx, tmp, olen);
-        if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
-        // fprintf(stderr, "RTN ATTEMPT tob64 %u idx=%u result %u\n", tob64,
-        // idx, *status);
+              memcpy(buf + idx, tmp, res);
+              if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
+              // fprintf(stderr, "RTN ATTEMPT FROMB64 idx=%u fromb64 %u %s %s
+              // result %u\n",       saved_idx,      fromb64,      tmp, repl,
+              // *status);
 
-      }
+            }
 
-#endif
+          }
+
+        }
+
+        // input is converted to base64? decode repl with base64!
+        if ((i % 3) == 2 && i < 24 && tob64 > i) {
+
+          u32 olen = from_base64(repl, tmp, i + 1);
+          memcpy(buf + idx, tmp, olen);
+          if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
+          // fprintf(stderr, "RTN ATTEMPT tob64 %u idx=%u result %u\n", tob64,
+          // idx, *status);
+
+        }
+
+      }
 
       // input is converted to hex? convert repl to binary!
-      if (i < 16 && tohex > i) {
+      if (afl->cmplog_enable_xtreme_transform && i < 16 && tohex > i) {
 
         u32 off;
         if (to_slash + to_x + to_0 == 2) {
@@ -2292,8 +2348,8 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
       }
 
       // input is hex and converted to binary? convert repl to hex!
-      if (i && (i % 2) && i < 16 && fromhex &&
-          fromhex + from_slash + from_x + from_0 > i) {
+      if (afl->cmplog_enable_xtreme_transform && (i % 2) == 1 && i < 16 &&
+          fromhex && fromhex + from_slash + from_x + from_0 > i) {
 
         u8 off = 0;
         if (from_slash && from_x) {
@@ -2328,31 +2384,36 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
 
         }
 
-        if (to_up == 1) {
+        for (u32 hlen = i; hlen <= (i << 1) && hlen + idx < len; hlen += i) {
 
-          for (j = 0; j <= (i >> 1); j++) {
+          if (to_up == 1) {
 
-            tmp[off + (j << 1)] = hex_table_up[repl[j] >> 4];
-            tmp[off + (j << 1) + 1] = hex_table_up[repl[j] % 16];
+            for (j = 0; j <= (hlen >> 1); j++) {
 
-          }
+              tmp[off + (j << 1)] = hex_table_up[repl[j] >> 4];
+              tmp[off + (j << 1) + 1] = hex_table_up[repl[j] % 16];
 
-        } else {
+            }
+
+          } else {
 
-          for (j = 0; j <= (i >> 1); j++) {
+            for (j = 0; j <= (hlen >> 1); j++) {
 
-            tmp[off + (j << 1)] = hex_table_low[repl[j] >> 4];
-            tmp[off + (j << 1) + 1] = hex_table_low[repl[j] % 16];
+              tmp[off + (j << 1)] = hex_table_low[repl[j] >> 4];
+              tmp[off + (j << 1) + 1] = hex_table_low[repl[j] % 16];
+
+            }
 
           }
 
-        }
+          memcpy(buf + idx, tmp, hlen + 1 + off);
+          if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
+          tmp[hlen + 1 + off] = 0;
+          // fprintf(stderr, "RTN ATTEMPT idx=%u len=%u fromhex %u %s %s result
+          // %u\n", idx, len, fromhex, tmp, repl, *status);
+          memcpy(buf + idx, save, hlen + 1 + off);
 
-        memcpy(buf + idx, tmp, i + 1 + off);
-        if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
-        // fprintf(stderr, "RTN ATTEMPT fromhex %u result %u\n", fromhex,
-        // *status);
-        memcpy(buf + idx, save, i + 1 + off);
+        }
 
       }
 
@@ -2401,11 +2462,9 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
 
       if ((i >= 7 &&
            (i >= xor&&i >= arith &&i >= tolower &&i >= toupper &&i > tohex &&i >
-                (fromhex + from_0 + from_x + from_slash + 1)
-#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64
-            && i > tob64 + 3 && i > fromb64 + 4
-#endif
-            )) ||
+                (fromhex + from_0 + from_x + from_slash + 1) &&
+            (afl->cmplog_enable_xtreme_transform && i > tob64 + 3 &&
+             i > fromb64 + 4))) ||
           repl[i] != changed_val[i] || *status == 1) {
 
         break;
@@ -2418,8 +2477,6 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
 
   }
 
-  // #endif
-
   return 0;
 
 }
@@ -2429,7 +2486,7 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
 
   struct tainted    *t;
   struct cmp_header *h = &afl->shm.cmp_map->headers[key];
-  u32                i, j, idx, have_taint = 1, taint_len, loggeds;
+  u32                i, idx, have_taint = 1, taint_len, loggeds;
   u8                 status = 0, found_one = 0;
 
   hshape = SHAPE_BYTES(h->shape);
@@ -2452,19 +2509,23 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
     struct cmpfn_operands *orig_o =
         &((struct cmpfn_operands *)afl->orig_cmp_map->log[key])[i];
 
-    // opt not in the paper
-    for (j = 0; j < i; ++j) {
+    /*
+        // opt not in the paper
+        for (j = 0; j < i; ++j) {
 
-      if (!memcmp(&((struct cmpfn_operands *)afl->shm.cmp_map->log[key])[j], o,
-                  sizeof(struct cmpfn_operands))) {
+          if (!memcmp(&((struct cmpfn_operands *)afl->shm.cmp_map->log[key])[j],
+       o, sizeof(struct cmpfn_operands))) {
 
-        goto rtn_fuzz_next_iter;
+            goto rtn_fuzz_next_iter;
 
-      }
+          }
 
-    }
+        }
 
-    /*
+    */
+
+#ifdef _DEBUG
+    u32                j;
     struct cmp_header *hh = &afl->orig_cmp_map->headers[key];
     fprintf(stderr, "RTN N hits=%u id=%u shape=%u attr=%u v0=", h->hits, h->id,
             hshape, h->attribute);
@@ -2481,7 +2542,7 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
     for (j = 0; j < 8; j++)
       fprintf(stderr, "%02x", orig_o->v1[j]);
     fprintf(stderr, "\n");
-    */
+#endif
 
     t = taint;
     while (t->next) {
@@ -2515,7 +2576,7 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
       status = 0;
 
 #ifdef _DEBUG
-      int w;
+      u32 w;
       fprintf(stderr, "key=%u idx=%u len=%u o0=", key, idx, hshape);
       for (w = 0; w < hshape; ++w)
         fprintf(stderr, "%02x", orig_o->v0[w]);
@@ -2605,7 +2666,7 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
 
     }
 
-  rtn_fuzz_next_iter:
+    // rtn_fuzz_next_iter:
     afl->stage_cur++;
 
   }
@@ -2818,12 +2879,7 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
 
       }
 
-    } else if ((lvl & LVL1)
-
-               // #ifdef CMPLOG_SOLVE_TRANSFORM
-               || ((lvl & LVL3) && afl->cmplog_enable_transform)
-               // #endif
-    ) {
+    } else if ((lvl & LVL1) || ((lvl & LVL3) && afl->cmplog_enable_transform)) {
 
       if (unlikely(rtn_fuzz(afl, k, orig_buf, buf, cbuf, len, lvl, taint))) {
 
diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c
index 99f69314..5a6b95cf 100644
--- a/src/afl-fuzz-state.c
+++ b/src/afl-fuzz-state.c
@@ -200,6 +200,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
             afl->afl_env.afl_exit_on_time =
                 (u8 *)get_afl_env(afl_environment_variables[i]);
 
+          } else if (!strncmp(env, "AFL_CRASHING_SEEDS_AS_NEW_CRASH",
+
+                              afl_environment_variable_len)) {
+
+            afl->afl_env.afl_crashing_seeds_as_new_crash =
+                atoi((u8 *)get_afl_env(afl_environment_variables[i]));
+
           } else if (!strncmp(env, "AFL_NO_AFFINITY",
 
                               afl_environment_variable_len)) {
diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c
index 4013370d..3d0a9b9a 100644
--- a/src/afl-fuzz-stats.c
+++ b/src/afl-fuzz-stats.c
@@ -37,8 +37,13 @@ char *get_fuzzing_state(afl_state_t *afl) {
   u64 cur_run_time = cur_ms - afl->start_time;
   u64 cur_total_run_time = afl->prev_run_time + cur_run_time;
 
-  if (unlikely(cur_run_time < 60 * 3 * 1000 ||
-               cur_total_run_time < 60 * 5 * 1000)) {
+  if (unlikely(afl->non_instrumented_mode)) {
+
+    return fuzzing_state[1];
+
+  } else if (unlikely(cur_run_time < 60 * 3 * 1000 ||
+
+                      cur_total_run_time < 60 * 5 * 1000)) {
 
     return fuzzing_state[0];
 
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index 9afece66..cdb3f996 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -180,12 +180,14 @@ static void usage(u8 *argv0, int more_help) {
       "it.\n"
       "                  if using QEMU/FRIDA or the fuzzing target is "
       "compiled\n"
-      "                  for CmpLog then just use -c 0.\n"
+      "                  for CmpLog then use '-c 0'. To disable Cmplog use '-c "
+      "-'.\n"
       "  -l cmplog_opts - CmpLog configuration values (e.g. \"2ATR\"):\n"
       "                  1=small files, 2=larger files (default), 3=all "
       "files,\n"
       "                  A=arithmetic solving, T=transformational solving,\n"
-      "                  R=random colorization bytes.\n\n"
+      "                  X=extreme transform solving, R=random colorization "
+      "bytes.\n\n"
       "Fuzzing behavior settings:\n"
       "  -Z            - sequential queue selection instead of weighted "
       "random\n"
@@ -277,7 +279,8 @@ static void usage(u8 *argv0, int more_help) {
       "AFL_IGNORE_UNKNOWN_ENVS: don't warn on unknown env vars\n"
       "AFL_IMPORT_FIRST: sync and import test cases from other fuzzer instances first\n"
       "AFL_INPUT_LEN_MIN/AFL_INPUT_LEN_MAX: like -g/-G set min/max fuzz length produced\n"
-      "AFL_PIZZA_MODE: 1 - enforce pizza mode, 0 - disable for April 1st\n"
+      "AFL_PIZZA_MODE: 1 - enforce pizza mode, -1 - disable for April 1st,\n"
+      "                0 (default) - activate on April 1st\n"
       "AFL_KILL_SIGNAL: Signal ID delivered to child processes on timeout, etc.\n"
       "                 (default: SIGKILL)\n"
       "AFL_FORK_SERVER_KILL_SIGNAL: Kill signal for the fork server on termination\n"
@@ -297,7 +300,12 @@ static void usage(u8 *argv0, int more_help) {
       "AFL_NO_SNAPSHOT: do not use the snapshot feature (if the snapshot lkm is loaded)\n"
       "AFL_NO_STARTUP_CALIBRATION: no initial seed calibration, start fuzzing at once\n"
       "AFL_NO_UI: switch status screen off\n"
-
+      "AFL_NYX_AUX_SIZE: size of the Nyx auxiliary buffer. Must be a multiple of 4096.\n"
+      "                  Increase this value in case the crash reports are truncated.\n"
+      "                  Default value is 4096.\n"
+      "AFL_NYX_DISABLE_SNAPSHOT_MODE: disable snapshot mode (must be supported by the agent)\n"
+      "AFL_NYX_LOG: output NYX hprintf messages to another file\n"
+      "AFL_NYX_REUSE_SNAPSHOT: reuse an existing Nyx root snapshot\n"
       DYN_COLOR
 
       "AFL_PATH: path to AFL support binaries\n"
@@ -306,8 +314,8 @@ static void usage(u8 *argv0, int more_help) {
 
       PERSISTENT_MSG
 
-      "AFL_POST_PROCESS_KEEP_ORIGINAL: save the file as it was prior post-processing to the queue,\n"
-      "                                but execute the post-processed one\n"
+      "AFL_POST_PROCESS_KEEP_ORIGINAL: save the file as it was prior post-processing to\n"
+      "                                the queue, but execute the post-processed one\n"
       "AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
       "AFL_TARGET_ENV: pass extra environment variables to target\n"
       "AFL_SHUFFLE_QUEUE: reorder the input queue randomly on startup\n"
@@ -318,18 +326,17 @@ static void usage(u8 *argv0, int more_help) {
       "AFL_STATSD_HOST: change default statsd host (default 127.0.0.1)\n"
       "AFL_STATSD_PORT: change default statsd port (default: 8125)\n"
       "AFL_STATSD_TAGS_FLAVOR: set statsd tags format (default: disable tags)\n"
-      "                        Supported formats are: 'dogstatsd', 'librato',\n"
-      "                        'signalfx' and 'influxdb'\n"
+      "                        suported formats: dogstatsd, librato, signalfx, influxdb\n"
       "AFL_SYNC_TIME: sync time between fuzzing instances (in minutes)\n"
       "AFL_NO_CRASH_README: do not create a README in the crashes directory\n"
       "AFL_TESTCACHE_SIZE: use a cache for testcases, improves performance (in MB)\n"
       "AFL_TMPDIR: directory to use for input file generation (ramdisk recommended)\n"
       "AFL_EARLY_FORKSERVER: force an early forkserver in an afl-clang-fast/\n"
       "                      afl-clang-lto/afl-gcc-fast target\n"
-      "AFL_PERSISTENT: enforce persistent mode (if __AFL_LOOP is in a shared lib\n"
-      "AFL_DEFER_FORKSRV: enforced deferred forkserver (__AFL_INIT is in a .so)\n"
-      "AFL_FUZZER_STATS_UPDATE_INTERVAL: interval to update fuzzer_stats file in seconds, "
-      "(default: 60, minimum: 1)\n"
+      "AFL_PERSISTENT: enforce persistent mode (if __AFL_LOOP is in a shared lib)\n"
+      "AFL_DEFER_FORKSRV: enforced deferred forkserver (__AFL_INIT is in a shared lib)\n"
+      "AFL_FUZZER_STATS_UPDATE_INTERVAL: interval to update fuzzer_stats file in\n"
+      "                                  seconds (default: 60, minimum: 1)\n"
       "\n"
     );
 
@@ -594,8 +601,23 @@ int main(int argc, char **argv_orig, char **envp) {
 
       case 'c': {
 
-        afl->shm.cmplog_mode = 1;
-        afl->cmplog_binary = ck_strdup(optarg);
+        if (strcmp(optarg, "-") == 0) {
+
+          if (afl->shm.cmplog_mode) {
+
+            ACTF("Disabling cmplog again because of '-c -'.");
+            afl->shm.cmplog_mode = 0;
+            afl->cmplog_binary = NULL;
+
+          }
+
+        } else {
+
+          afl->shm.cmplog_mode = 1;
+          afl->cmplog_binary = ck_strdup(optarg);
+
+        }
+
         break;
 
       }
@@ -1120,6 +1142,10 @@ int main(int argc, char **argv_orig, char **envp) {
             case 'T':
               afl->cmplog_enable_transform = 1;
               break;
+            case 'x':
+            case 'X':
+              afl->cmplog_enable_xtreme_transform = 1;
+              break;
             case 'r':
             case 'R':
               afl->cmplog_random_colorization = 1;
@@ -1500,8 +1526,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
   if (!afl->use_banner) { afl->use_banner = argv[optind]; }
 
-  if (afl->shm.cmplog_mode &&
-      (!strcmp("-", afl->cmplog_binary) || !strcmp("0", afl->cmplog_binary))) {
+  if (afl->shm.cmplog_mode && strcmp("0", afl->cmplog_binary) == 0) {
 
     afl->cmplog_binary = strdup(argv[optind]);
 
@@ -2755,7 +2780,8 @@ int main(int argc, char **argv_orig, char **envp) {
 
     u64 cur_time = get_cur_time();
 
-    if (likely(afl->switch_fuzz_mode && afl->fuzz_mode == 0) &&
+    if (likely(afl->switch_fuzz_mode && afl->fuzz_mode == 0 &&
+               !afl->non_instrumented_mode) &&
         unlikely(cur_time > afl->last_find_time + afl->switch_fuzz_mode)) {
 
       if (afl->afl_env.afl_no_ui) {
diff --git a/src/afl-showmap.c b/src/afl-showmap.c
index b82bcd72..7a639cf6 100644
--- a/src/afl-showmap.c
+++ b/src/afl-showmap.c
@@ -1611,6 +1611,7 @@ int main(int argc, char **argv_orig, char **envp) {
   if (in_dir || in_filelist) {
 
     afl->fsrv.dev_urandom_fd = open("/dev/urandom", O_RDONLY);
+    if (afl->fsrv.dev_urandom_fd < 0) { PFATAL("Unable to open /dev/urandom"); }
     afl->afl_env.afl_custom_mutator_library =
         getenv("AFL_CUSTOM_MUTATOR_LIBRARY");
     afl->afl_env.afl_python_module = getenv("AFL_PYTHON_MODULE");
diff --git a/test/unittests/unit_rand.c b/test/unittests/unit_rand.c
index 1ad02a80..f89b2ab5 100644
--- a/test/unittests/unit_rand.c
+++ b/test/unittests/unit_rand.c
@@ -67,6 +67,7 @@ static void test_rand_below(void **state) {
     rand_set_seed(&afl, 1337);
 
     afl.fsrv.dev_urandom_fd = open("/dev/urandom", O_RDONLY);
+    if (afl.fsrv.dev_urandom_fd < 0) { PFATAL("Unable to open /dev/urandom"); }
 
     assert(!(rand_below(&afl, 9000) > 9000));
     assert_int_equal(rand_below(&afl, 1), 0);