about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.gitmodules2
-rw-r--r--CONTRIBUTING.md4
-rw-r--r--README.md11
-rw-r--r--custom_mutators/honggfuzz/honggfuzz.c1
-rw-r--r--custom_mutators/libfuzzer/FuzzerIO.cpp7
-rw-r--r--custom_mutators/libfuzzer/FuzzerLoop.cpp13
-rw-r--r--custom_mutators/libfuzzer/FuzzerMutate.cpp24
-rw-r--r--custom_mutators/libfuzzer/FuzzerMutate.h1
-rw-r--r--custom_mutators/libfuzzer/Makefile5
-rw-r--r--custom_mutators/libfuzzer/libfuzzer.cpp13
-rw-r--r--custom_mutators/radamsa/radamsa-mutator.c1
-rw-r--r--custom_mutators/symcc/symcc.c1
-rw-r--r--docs/Changelog.md12
-rw-r--r--docs/custom_mutators.md10
-rw-r--r--examples/afl_frida/afl-frida.c7
-rw-r--r--examples/custom_mutators/custom_mutator_helpers.h2
-rw-r--r--examples/custom_mutators/post_library_gif.so.c8
-rw-r--r--examples/custom_mutators/post_library_png.so.c8
-rw-r--r--examples/custom_mutators/simple_example.c2
-rw-r--r--examples/defork/forking_target.c1
-rw-r--r--include/afl-fuzz.h33
-rw-r--r--instrumentation/SanitizerCoveragePCGUARD.so.cc8
-rw-r--r--instrumentation/afl-compiler-rt.o.c4
-rw-r--r--qemu_mode/QEMUAFL_VERSION2
-rw-r--r--qemu_mode/libcompcov/pmparser.h8
-rw-r--r--src/afl-cc.c113
-rw-r--r--src/afl-common.c2
-rw-r--r--src/afl-forkserver.c17
-rw-r--r--src/afl-fuzz-bitmap.c81
-rw-r--r--src/afl-fuzz-init.c9
-rw-r--r--src/afl-fuzz-mutators.c7
-rw-r--r--src/afl-fuzz-one.c14
-rw-r--r--src/afl-fuzz-python.c38
-rw-r--r--src/afl-fuzz.c50
-rw-r--r--src/afl-gotcpu.c1
-rw-r--r--unicorn_mode/samples/persistent/simple_target_noncrashing.c16
m---------unicorn_mode/unicornafl0
37 files changed, 409 insertions, 127 deletions
diff --git a/.gitmodules b/.gitmodules
index 3ad6e10c..7c7613ac 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -7,4 +7,4 @@
 	url = https://github.com/AFLplusplus/Grammar-Mutator
 [submodule "qemu_mode/qemuafl"]
 	path = qemu_mode/qemuafl
-	url = https://github.com/AFLplusplus/qemuafl.git
+	url = https://github.com/AFLplusplus/qemuafl
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index ccacef5f..c36ed9d8 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -16,9 +16,9 @@ project, or added a file in a directory we already format, otherwise run:
 ```
 
 Regarding the coding style, please follow the AFL style.
-No camel case at all and use the AFL's macros wherever possible 
+No camel case at all and use AFL's macros wherever possible
 (e.g. WARNF, FATAL, MAP_SIZE, ...).
 
 Remember that AFLplusplus has to build and run on many platforms, so
 generalize your Makefiles/GNUmakefile (or your patches to our pre-existing
-Makefiles) to be as much generic as possible.
+Makefiles) to be as generic as possible.
diff --git a/README.md b/README.md
index d7c5694e..494a6bb7 100644
--- a/README.md
+++ b/README.md
@@ -22,8 +22,8 @@
   afl++ is a superior fork to Google's afl - more speed, more and better
   mutations, more and better instrumentation, custom module support, etc.
 
-  If you want to use afl++ for you academic work, check the [papers page](https://aflplus.plus/papers/)
-  in the website.
+  If you want to use afl++ for your academic work, check the [papers page](https://aflplus.plus/papers/)
+  on the website.
 
 ## Major changes in afl++ 3.0
 
@@ -585,7 +585,10 @@ For every secondary fuzzer there should be a variation, e.g.:
    activated (`export AFL_USE_ASAN=1 ; export AFL_USE_UBSAN=1 ;
    export AFL_USE_CFISAN=1 ; `
  * one should fuzz the target with CMPLOG/redqueen (see above)
- * one to three should fuzz a target compiled with laf-intel/COMPCOV (see above).
+ * one to three fuzzers should fuzz a target compiled with laf-intel/COMPCOV
+   (see above). Important note: If you run more than one laf-intel/COMPCOV
+   fuzzer and you want them to share their intermediate results, the main
+   fuzzer (`-M`) must be one of the them!
 
 All other secondaries should be used like this:
  * A third to a half with the MOpt mutator enabled: `-L 0`
@@ -597,11 +600,11 @@ You can also use different fuzzers.
 If you are using afl spinoffs or afl conforming fuzzers, then just use the
 same -o directory and give it a unique `-S` name.
 Examples are:
- * [Angora](https://github.com/AngoraFuzzer/Angora)
  * [Untracer](https://github.com/FoRTE-Research/UnTracer-AFL)
  * [AFLsmart](https://github.com/aflsmart/aflsmart)
  * [FairFuzz](https://github.com/carolemieux/afl-rb)
  * [Neuzz](https://github.com/Dongdongshe/neuzz)
+ * [Angora](https://github.com/AngoraFuzzer/Angora)
 
 A long list can be found at [https://github.com/Microsvuln/Awesome-AFL](https://github.com/Microsvuln/Awesome-AFL)
 
diff --git a/custom_mutators/honggfuzz/honggfuzz.c b/custom_mutators/honggfuzz/honggfuzz.c
index bde922c6..b4f07258 100644
--- a/custom_mutators/honggfuzz/honggfuzz.c
+++ b/custom_mutators/honggfuzz/honggfuzz.c
@@ -37,6 +37,7 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
 
   if ((data->mutator_buf = malloc(MAX_FILE)) == NULL) {
 
+    free(data);
     perror("mutator_buf alloc");
     return NULL;
 
diff --git a/custom_mutators/libfuzzer/FuzzerIO.cpp b/custom_mutators/libfuzzer/FuzzerIO.cpp
index e0c15db4..d8d52b63 100644
--- a/custom_mutators/libfuzzer/FuzzerIO.cpp
+++ b/custom_mutators/libfuzzer/FuzzerIO.cpp
@@ -83,6 +83,8 @@ void WriteToFile(const std::string &Data, const std::string &Path) {
 
 void WriteToFile(const uint8_t *Data, size_t Size, const std::string &Path) {
 
+  return;
+ 
   // Use raw C interface because this function may be called from a sig handler.
   FILE *Out = fopen(Path.c_str(), "wb");
   if (!Out) return;
@@ -93,6 +95,8 @@ void WriteToFile(const uint8_t *Data, size_t Size, const std::string &Path) {
 
 void AppendToFile(const std::string &Data, const std::string &Path) {
 
+  return;
+
   AppendToFile(reinterpret_cast<const uint8_t *>(Data.data()), Data.size(),
                Path);
 
@@ -100,6 +104,8 @@ void AppendToFile(const std::string &Data, const std::string &Path) {
 
 void AppendToFile(const uint8_t *Data, size_t Size, const std::string &Path) {
 
+  return;
+
   FILE *Out = fopen(Path.c_str(), "a");
   if (!Out) return;
   fwrite(Data, sizeof(Data[0]), Size, Out);
@@ -182,6 +188,7 @@ void Printf(const char *Fmt, ...) {
 
 void VPrintf(bool Verbose, const char *Fmt, ...) {
 
+  return;
   if (!Verbose) return;
   va_list ap;
   va_start(ap, Fmt);
diff --git a/custom_mutators/libfuzzer/FuzzerLoop.cpp b/custom_mutators/libfuzzer/FuzzerLoop.cpp
index 201883f0..08fda520 100644
--- a/custom_mutators/libfuzzer/FuzzerLoop.cpp
+++ b/custom_mutators/libfuzzer/FuzzerLoop.cpp
@@ -206,6 +206,8 @@ void Fuzzer::StaticDeathCallback() {
 
 void Fuzzer::DumpCurrentUnit(const char *Prefix) {
 
+  return;
+
   if (!CurrentUnitData) return;  // Happens when running individual inputs.
   ScopedDisableMsanInterceptorChecks S;
   MD.PrintMutationSequence();
@@ -733,6 +735,7 @@ std::string Fuzzer::WriteToOutputCorpus(const Unit &U) {
 
 void Fuzzer::WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix) {
 
+  return;
   if (!Options.SaveArtifacts) return;
   std::string Path = Options.ArtifactPrefix + Prefix + Hash(U);
   if (!Options.ExactArtifactPath.empty())
@@ -1073,13 +1076,21 @@ void Fuzzer::MinimizeCrashLoop(const Unit &U) {
 
 }  // namespace fuzzer
 
+#ifdef  INTROSPECTION
+  extern const char *introspection_ptr;
+#endif
+
 extern "C" {
 
 ATTRIBUTE_INTERFACE size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size,
                                             size_t MaxSize) {
 
   assert(fuzzer::F);
-  return fuzzer::F->GetMD().DefaultMutate(Data, Size, MaxSize);
+  size_t r = fuzzer::F->GetMD().DefaultMutate(Data, Size, MaxSize);
+#ifdef  INTROSPECTION
+  introspection_ptr = fuzzer::F->GetMD().WriteMutationSequence();
+#endif
+  return r;
 
 }
 
diff --git a/custom_mutators/libfuzzer/FuzzerMutate.cpp b/custom_mutators/libfuzzer/FuzzerMutate.cpp
index eebae39b..edfe0455 100644
--- a/custom_mutators/libfuzzer/FuzzerMutate.cpp
+++ b/custom_mutators/libfuzzer/FuzzerMutate.cpp
@@ -14,6 +14,8 @@
 #include "FuzzerMutate.h"
 #include "FuzzerOptions.h"
 #include "FuzzerTracePC.h"
+#include <random>
+#include <chrono>
 
 namespace fuzzer {
 
@@ -100,15 +102,17 @@ size_t MutationDispatcher::Mutate_CustomCrossOver(uint8_t *Data, size_t Size,
 
 }
 
+
 size_t MutationDispatcher::Mutate_ShuffleBytes(uint8_t *Data, size_t Size,
                                                size_t MaxSize) {
-
   if (Size > MaxSize || Size == 0) return 0;
   size_t ShuffleAmount =
       Rand(std::min(Size, (size_t)8)) + 1;  // [1,8] and <= Size.
   size_t ShuffleStart = Rand(Size - ShuffleAmount);
   assert(ShuffleStart + ShuffleAmount <= Size);
-  std::shuffle(Data + ShuffleStart, Data + ShuffleStart + ShuffleAmount, Rand);
+  unsigned num = std::chrono::system_clock::now().time_since_epoch().count();
+  std::shuffle(Data + ShuffleStart, Data + ShuffleStart + ShuffleAmount, std::default_random_engine(num));
+  //std::shuffle(Data + ShuffleStart, Data + ShuffleStart + ShuffleAmount, Rand);
   return Size;
 
 }
@@ -609,8 +613,24 @@ void MutationDispatcher::PrintRecommendedDictionary() {
 
 }
 
+const char *MutationDispatcher::WriteMutationSequence() {
+
+  static std::string buf;
+  buf = "";
+
+  for (size_t i = 0; i < CurrentMutatorSequence.size(); i++) {
+  
+    buf = buf + " " + CurrentMutatorSequence[i].Name;
+  
+  }
+  
+  return buf.c_str();
+
+}
+
 void MutationDispatcher::PrintMutationSequence(bool Verbose) {
 
+  return;
   Printf("MS: %zd ", CurrentMutatorSequence.size());
   size_t EntriesToPrint =
       Verbose ? CurrentMutatorSequence.size()
diff --git a/custom_mutators/libfuzzer/FuzzerMutate.h b/custom_mutators/libfuzzer/FuzzerMutate.h
index 37fd6100..6252f265 100644
--- a/custom_mutators/libfuzzer/FuzzerMutate.h
+++ b/custom_mutators/libfuzzer/FuzzerMutate.h
@@ -26,6 +26,7 @@ public:
   void StartMutationSequence();
   /// Print the current sequence of mutations. Only prints the full sequence
   /// when Verbose is true.
+  const char *WriteMutationSequence();
   void PrintMutationSequence(bool Verbose = true);
   /// Return the current sequence of mutations.
   std::string MutationSequence();
diff --git a/custom_mutators/libfuzzer/Makefile b/custom_mutators/libfuzzer/Makefile
index 95402f6c..51263b89 100644
--- a/custom_mutators/libfuzzer/Makefile
+++ b/custom_mutators/libfuzzer/Makefile
@@ -3,6 +3,11 @@ CFLAGS = -g -O3 -funroll-loops -fPIC -fpermissive -std=c++11
 #CFLAGS = -g -O0 -fPIC -fpermissive -std=c++11
 CXX ?= clang++
 
+ifdef INTROSPECTION
+  $(info Compiling with introspection documentation)
+  CFLAGS += -DINTROSPECTION=1
+endif
+
 all: libfuzzer-mutator.so
 
 FuzzerCrossOver.o:	FuzzerCrossOver.cpp
diff --git a/custom_mutators/libfuzzer/libfuzzer.cpp b/custom_mutators/libfuzzer/libfuzzer.cpp
index 5e37df66..dc1fbeb2 100644
--- a/custom_mutators/libfuzzer/libfuzzer.cpp
+++ b/custom_mutators/libfuzzer/libfuzzer.cpp
@@ -6,6 +6,10 @@
 //#include "debug.h"
 #include "afl-fuzz.h"
 
+#ifdef  INTROSPECTION
+  const char *introspection_ptr;
+#endif
+
 afl_state_t *afl_struct;
 
 extern "C" size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize);
@@ -46,6 +50,7 @@ extern "C" my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
 
   if ((data->mutator_buf = (u8 *)malloc(MAX_FILE)) == NULL) {
 
+    free(data);
     perror("mutator_buf alloc");
     return NULL;
 
@@ -133,6 +138,14 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf,
 
 }
 
+#ifdef  INTROSPECTION
+extern "C" const char* afl_custom_introspection(my_mutator_t *data) {
+
+  return introspection_ptr;
+
+}
+#endif
+
 /**
  * Deinitialize everything
  *
diff --git a/custom_mutators/radamsa/radamsa-mutator.c b/custom_mutators/radamsa/radamsa-mutator.c
index 82d28001..624ace3d 100644
--- a/custom_mutators/radamsa/radamsa-mutator.c
+++ b/custom_mutators/radamsa/radamsa-mutator.c
@@ -33,6 +33,7 @@ my_mutator_t *afl_custom_init(afl_t *afl, unsigned int seed) {
 
   if ((data->mutator_buf = malloc(MAX_FILE)) == NULL) {
 
+    free(data);
     perror("mutator_buf alloc");
     return NULL;
 
diff --git a/custom_mutators/symcc/symcc.c b/custom_mutators/symcc/symcc.c
index acec29da..9c6c0cb8 100644
--- a/custom_mutators/symcc/symcc.c
+++ b/custom_mutators/symcc/symcc.c
@@ -45,6 +45,7 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
 
   if ((data->mutator_buf = malloc(MAX_FILE)) == NULL) {
 
+    free(data);
     perror("mutator_buf alloc");
     return NULL;
 
diff --git a/docs/Changelog.md b/docs/Changelog.md
index 50c1d48a..baa2667b 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -38,22 +38,26 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
     - added INTROSPECTION make target that writes all mutations to
       out/NAME/introspection.txt
     - print special compile time options used in help output
+    - somewhere we broke -n dumb fuzzing, fixed
   - instrumentation
     - We received an enhanced gcc_plugin module from AdaCore, thank you
       very much!!
     - not overriding -Ox or -fno-unroll-loops anymore
     - we now have our own trace-pc-guard implementation. It is the same as
       -fsanitize-coverage=trace-pc-guard from llvm 12, but: it is a) inline
-      and b) works from llvm 10+ on :)
+      and b) works from llvm 10.0.1 + onwards :)
     - new llvm pass: dict2file via AFL_LLVM_DICT2FILE, create afl-fuzz
       -x dictionary of string comparisons found during compilation
     - LTO autodict now also collects interesting cmp comparisons,
       std::string compare + find + ==, bcmp
     - fix crash in dict2file for integers > 64 bit
+  - custom mutators
+    - added a new custom mutator: symcc -> https://github.com/eurecom-s3/symcc/
+    - added a new custom mutator: libfuzzer that integrates libfuzzer mutations
+    - Our afl++ Grammar-Mutator is now better integrated into custom_mutators/
+    - added INTROSPECTION support for custom modules
+    - python fuzz function was not optional, fixed
   - unicornafl synced with upstream (arm64 fix, better rust bindings)
-  - added a new custom mutator: symcc -> https://github.com/eurecom-s3/symcc/
-  - added a new custom mutator: libfuzzer that integrates libfuzzer mutations
-  - Our afl++ Grammar-Mutator is now better integrated into custom_mutators/
 
 
 ### Version ++2.68c (release)
diff --git a/docs/custom_mutators.md b/docs/custom_mutators.md
index 81ee9de4..2516e511 100644
--- a/docs/custom_mutators.md
+++ b/docs/custom_mutators.md
@@ -42,6 +42,7 @@ size_t afl_custom_havoc_mutation(void *data, unsigned char *buf, size_t buf_size
 unsigned char afl_custom_havoc_mutation_probability(void *data);
 unsigned char afl_custom_queue_get(void *data, const unsigned char *filename);
 void afl_custom_queue_new_entry(void *data, const unsigned char *filename_new_queue, const unsigned int *filename_orig_queue);
+const char* afl_custom_introspection(my_mutator_t *data);
 void afl_custom_deinit(void *data);
 ```
 
@@ -81,6 +82,9 @@ def queue_new_entry(filename_new_queue, filename_orig_queue):
     pass
 ```
 
+def introspection():
+    return string
+
 ### Custom Mutation
 
 - `init`:
@@ -130,6 +134,12 @@ def queue_new_entry(filename_new_queue, filename_orig_queue):
 
     This methods is called after adding a new test case to the queue.
 
+- `introspection` (optional):
+
+    This method is called after a new queue entry, crash or timeout is
+    discovered if compiled with INTROSPECTION. The custom mutator can then
+    return a string (const char *) that reports the exact mutations used.
+
 - `deinit`:
 
     The last method to be called, deinitializing the state.
diff --git a/examples/afl_frida/afl-frida.c b/examples/afl_frida/afl-frida.c
index 2ad5a72a..31bf8f25 100644
--- a/examples/afl_frida/afl-frida.c
+++ b/examples/afl_frida/afl-frida.c
@@ -6,7 +6,7 @@
 
    Written mostly by meme -> https://github.com/meme/hotwax
 
-   Modificationy by Marc Heuse <mh@mh-sec.de>
+   Modifications by Marc Heuse <mh@mh-sec.de>
 
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
@@ -504,11 +504,12 @@ int main() {
     previous_pc = 0;  // Required!
 
 #ifdef _DEBUG
-    fprintf(stderr, "CLIENT crc: %016llx len: %u\n", hash64(__afl_fuzz_ptr, *__a
+    fprintf(stderr, "CLIENT crc: %016llx len: %u\n",
+            hash64(__afl_fuzz_ptr, *__afl_fuzz_len), *__afl_fuzz_len);
     fprintf(stderr, "RECV:");
     for (int i = 0; i < *__afl_fuzz_len; i++)
       fprintf(stderr, "%02x", __afl_fuzz_ptr[i]);
-    fprintf(stderr,"\n");
+    fprintf(stderr, "\n");
 #endif
 
     // STEP 3: ensure the minimum length is present and setup the target
diff --git a/examples/custom_mutators/custom_mutator_helpers.h b/examples/custom_mutators/custom_mutator_helpers.h
index ad5acb08..62e6efba 100644
--- a/examples/custom_mutators/custom_mutator_helpers.h
+++ b/examples/custom_mutators/custom_mutator_helpers.h
@@ -13,7 +13,7 @@
 #define BUF_VAR(type, name) \
   type * name##_buf;        \
   size_t name##_size;
-/* this filles in `&structptr->something_buf, &structptr->something_size`. */
+/* this fills in `&structptr->something_buf, &structptr->something_size`. */
 #define BUF_PARAMS(struct, name) \
   (void **)&struct->name##_buf, &struct->name##_size
 
diff --git a/examples/custom_mutators/post_library_gif.so.c b/examples/custom_mutators/post_library_gif.so.c
index 2d72400c..ac10f409 100644
--- a/examples/custom_mutators/post_library_gif.so.c
+++ b/examples/custom_mutators/post_library_gif.so.c
@@ -94,7 +94,13 @@ void *afl_custom_init(void *afl) {
   }
 
   state->buf = calloc(sizeof(unsigned char), 4096);
-  if (!state->buf) { return NULL; }
+  if (!state->buf) {
+
+    free(state);
+    perror("calloc");
+    return NULL;
+
+  }
 
   return state;
 
diff --git a/examples/custom_mutators/post_library_png.so.c b/examples/custom_mutators/post_library_png.so.c
index 7c1ea93e..941f7e55 100644
--- a/examples/custom_mutators/post_library_png.so.c
+++ b/examples/custom_mutators/post_library_png.so.c
@@ -54,7 +54,13 @@ void *afl_custom_init(void *afl) {
   }
 
   state->buf = calloc(sizeof(unsigned char), 4096);
-  if (!state->buf) { return NULL; }
+  if (!state->buf) {
+
+    free(state);
+    perror("calloc");
+    return NULL;
+
+  }
 
   return state;
 
diff --git a/examples/custom_mutators/simple_example.c b/examples/custom_mutators/simple_example.c
index a351d787..d888ec1f 100644
--- a/examples/custom_mutators/simple_example.c
+++ b/examples/custom_mutators/simple_example.c
@@ -8,7 +8,7 @@
 #include <stdio.h>
 
 #ifndef _FIXED_CHAR
-  #define 0x41
+  #define _FIXED_CHAR 0x41
 #endif
 
 typedef struct my_mutator {
diff --git a/examples/defork/forking_target.c b/examples/defork/forking_target.c
index 98f6365a..628d23c9 100644
--- a/examples/defork/forking_target.c
+++ b/examples/defork/forking_target.c
@@ -26,6 +26,7 @@ int main(int argc, char **argv) {
     FILE *f = fopen(argv[1], "r");
     char  buf[4096];
     fread(buf, 1, 4096, f);
+    fclose(f);
     uint32_t offset = buf[100] + (buf[101] << 8);
     char     test_val = buf[offset];
     return test_val < 100;
diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h
index e59d5f90..c355263b 100644
--- a/include/afl-fuzz.h
+++ b/include/afl-fuzz.h
@@ -310,6 +310,7 @@ enum {
   /* 09 */ PY_FUNC_HAVOC_MUTATION_PROBABILITY,
   /* 10 */ PY_FUNC_QUEUE_GET,
   /* 11 */ PY_FUNC_QUEUE_NEW_ENTRY,
+  /* 12 */ PY_FUNC_INTROSPECTION,
   PY_FUNC_COUNT
 
 };
@@ -684,6 +685,8 @@ typedef struct afl_state {
 
   u32 custom_mutators_count;
 
+  struct custom_mutator *current_custom_fuzz;
+
   list_t custom_mutator_list;
 
   /* this is a fixed buffer of size map_size that can be used by any function if
@@ -748,6 +751,15 @@ struct custom_mutator {
   void *(*afl_custom_init)(afl_state_t *afl, unsigned int seed);
 
   /**
+   * When afl-fuzz was compiled with INTROSPECTION=1 then custom mutators can
+   * also give introspection information back with this function.
+   *
+   * @param data pointer returned in afl_custom_init for this fuzz case
+   * @return pointer to a text string (const char*)
+   */
+  const char *(*afl_custom_introspection)(void *data);
+
+  /**
    * This method is called just before fuzzing a queue entry with the custom
    * mutator, and receives the initial buffer. It should return the number of
    * fuzzes to perform.
@@ -953,16 +965,17 @@ u8   trim_case_custom(afl_state_t *, struct queue_entry *q, u8 *in_buf,
 struct custom_mutator *load_custom_mutator_py(afl_state_t *, char *);
 void                   finalize_py_module(void *);
 
-u32    fuzz_count_py(void *, const u8 *, size_t);
-size_t post_process_py(void *, u8 *, size_t, u8 **);
-s32    init_trim_py(void *, u8 *, size_t);
-s32    post_trim_py(void *, u8);
-size_t trim_py(void *, u8 **);
-size_t havoc_mutation_py(void *, u8 *, size_t, u8 **, size_t);
-u8     havoc_mutation_probability_py(void *);
-u8     queue_get_py(void *, const u8 *);
-void   queue_new_entry_py(void *, const u8 *, const u8 *);
-void   deinit_py(void *);
+u32         fuzz_count_py(void *, const u8 *, size_t);
+size_t      post_process_py(void *, u8 *, size_t, u8 **);
+s32         init_trim_py(void *, u8 *, size_t);
+s32         post_trim_py(void *, u8);
+size_t      trim_py(void *, u8 **);
+size_t      havoc_mutation_py(void *, u8 *, size_t, u8 **, size_t);
+u8          havoc_mutation_probability_py(void *);
+u8          queue_get_py(void *, const u8 *);
+const char *introspection_py(void *);
+void        queue_new_entry_py(void *, const u8 *, const u8 *);
+void        deinit_py(void *);
 
 #endif
 
diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc
index b3c55108..e85f9cd3 100644
--- a/instrumentation/SanitizerCoveragePCGUARD.so.cc
+++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc
@@ -544,7 +544,9 @@ bool ModuleSanitizerCoverage::instrumentModule(
     be_quiet = 1;
 
   skip_nozero = getenv("AFL_LLVM_SKIP_NEVERZERO");
-  // scanForDangerousFunctions(&M);
+
+  initInstrumentList();
+  scanForDangerousFunctions(&M);
 
   if (debug) {
 
@@ -819,6 +821,8 @@ void ModuleSanitizerCoverage::instrumentFunction(
     Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) {
 
   if (F.empty()) return;
+  if (!isInInstrumentList(&F)) return;
+
   if (F.getName().find(".module_ctor") != std::string::npos)
     return;  // Should not instrument sanitizer init functions.
   if (F.getName().startswith("__sanitizer_"))
@@ -1315,6 +1319,7 @@ std::string ModuleSanitizerCoverage::getSectionEnd(
 }
 
 char ModuleSanitizerCoverageLegacyPass::ID = 0;
+
 INITIALIZE_PASS_BEGIN(ModuleSanitizerCoverageLegacyPass, "sancov",
                       "Pass for instrumenting coverage on functions", false,
                       false)
@@ -1323,6 +1328,7 @@ INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass)
 INITIALIZE_PASS_END(ModuleSanitizerCoverageLegacyPass, "sancov",
                     "Pass for instrumenting coverage on functions", false,
                     false)
+
 ModulePass *llvm::createModuleSanitizerCoverageLegacyPassPass(
     const SanitizerCoverageOptions &Options,
     const std::vector<std::string> &AllowlistFiles,
diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c
index f38af668..18501b65 100644
--- a/instrumentation/afl-compiler-rt.o.c
+++ b/instrumentation/afl-compiler-rt.o.c
@@ -123,7 +123,7 @@ void __afl_trace(const u32 x) {
   u8 c = __builtin_add_overflow(*p, 1, p);
   *p += c;
   #else
-  *p += 1 + ((u8)(1 + *p == 0);
+  *p += 1 + ((u8)(1 + *p) == 0);
   #endif
 #else
   ++*p;
@@ -182,7 +182,7 @@ static void __afl_map_shm_fuzz() {
 
     if (!map || map == (void *)-1) {
 
-      perror("Could not access fuzzign shared memory");
+      perror("Could not access fuzzing shared memory");
       exit(1);
 
     }
diff --git a/qemu_mode/QEMUAFL_VERSION b/qemu_mode/QEMUAFL_VERSION
index 75883247..43403430 100644
--- a/qemu_mode/QEMUAFL_VERSION
+++ b/qemu_mode/QEMUAFL_VERSION
@@ -1 +1 @@
-21ff343837
+d66c9e2654
diff --git a/qemu_mode/libcompcov/pmparser.h b/qemu_mode/libcompcov/pmparser.h
index 9421d47e..0eb4fb1d 100644
--- a/qemu_mode/libcompcov/pmparser.h
+++ b/qemu_mode/libcompcov/pmparser.h
@@ -108,8 +108,7 @@ void pmparser_print(procmaps_struct *map, int order);
 
 procmaps_iterator *pmparser_parse(int pid) {
 
-  procmaps_iterator *maps_it = malloc(sizeof(procmaps_iterator));
-  char               maps_path[500];
+  char maps_path[500];
   if (pid >= 0) {
 
     sprintf(maps_path, "/proc/%d/maps", pid);
@@ -129,8 +128,9 @@ procmaps_iterator *pmparser_parse(int pid) {
 
   }
 
-  int  ind = 0;
-  char buf[PROCMAPS_LINE_MAX_LENGTH];
+  procmaps_iterator *maps_it = malloc(sizeof(procmaps_iterator));
+  int                ind = 0;
+  char               buf[PROCMAPS_LINE_MAX_LENGTH];
   // int c;
   procmaps_struct *list_maps = NULL;
   procmaps_struct *tmp;
diff --git a/src/afl-cc.c b/src/afl-cc.c
index 771a58f5..5d8d33a5 100644
--- a/src/afl-cc.c
+++ b/src/afl-cc.c
@@ -49,14 +49,14 @@ static u8 * obj_path;                  /* Path to runtime libraries         */
 static u8 **cc_params;                 /* Parameters passed to the real CC  */
 static u32  cc_par_cnt = 1;            /* Param count, including argv0      */
 static u8   llvm_fullpath[PATH_MAX];
-static u8   instrument_mode, instrument_opt_mode, ngram_size, lto_mode,
-    compiler_mode, plusplus_mode;
-static u8  have_gcc, have_llvm, have_gcc_plugin, have_lto;
-static u8 *lto_flag = AFL_CLANG_FLTO, *argvnull;
-static u8  debug;
-static u8  cwd[4096];
-static u8  cmplog_mode;
-u8         use_stdin;                                              /* dummy */
+static u8   instrument_mode, instrument_opt_mode, ngram_size, lto_mode;
+static u8   compiler_mode, plusplus_mode, have_instr_env = 0;
+static u8   have_gcc, have_llvm, have_gcc_plugin, have_lto, have_instr_list = 0;
+static u8 * lto_flag = AFL_CLANG_FLTO, *argvnull;
+static u8   debug;
+static u8   cwd[4096];
+static u8   cmplog_mode;
+u8          use_stdin;                                             /* dummy */
 // static u8 *march_opt = CFLAGS_OPT;
 
 enum {
@@ -354,19 +354,13 @@ static void edit_params(u32 argc, char **argv, char **envp) {
     if (lto_mode && plusplus_mode)
       cc_params[cc_par_cnt++] = "-lc++";  // needed by fuzzbench, early
 
-    if (lto_mode) {
-
-      if (getenv("AFL_LLVM_INSTRUMENT_FILE") != NULL ||
-          getenv("AFL_LLVM_WHITELIST") || getenv("AFL_LLVM_ALLOWLIST") ||
-          getenv("AFL_LLVM_DENYLIST") || getenv("AFL_LLVM_BLOCKLIST")) {
+    if (lto_mode && have_instr_env) {
 
-        cc_params[cc_par_cnt++] = "-Xclang";
-        cc_params[cc_par_cnt++] = "-load";
-        cc_params[cc_par_cnt++] = "-Xclang";
-        cc_params[cc_par_cnt++] =
-            alloc_printf("%s/afl-llvm-lto-instrumentlist.so", obj_path);
-
-      }
+      cc_params[cc_par_cnt++] = "-Xclang";
+      cc_params[cc_par_cnt++] = "-load";
+      cc_params[cc_par_cnt++] = "-Xclang";
+      cc_params[cc_par_cnt++] =
+          alloc_printf("%s/afl-llvm-lto-instrumentlist.so", obj_path);
 
     }
 
@@ -508,11 +502,25 @@ static void edit_params(u32 argc, char **argv, char **envp) {
       if (instrument_mode == INSTRUMENT_PCGUARD) {
 
 #if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
-        cc_params[cc_par_cnt++] = "-Xclang";
-        cc_params[cc_par_cnt++] = "-load";
-        cc_params[cc_par_cnt++] = "-Xclang";
-        cc_params[cc_par_cnt++] =
-            alloc_printf("%s/SanitizerCoveragePCGUARD.so", obj_path);
+        if (have_instr_list) {
+
+          if (!be_quiet)
+            SAYF(
+                "Using unoptimized trace-pc-guard, due usage of "
+                "-fsanitize-coverage-allow/denylist, you can use "
+                "AFL_LLVM_ALLOWLIST/AFL_LLMV_DENYLIST instead.\n");
+          cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
+
+        } else {
+
+          cc_params[cc_par_cnt++] = "-Xclang";
+          cc_params[cc_par_cnt++] = "-load";
+          cc_params[cc_par_cnt++] = "-Xclang";
+          cc_params[cc_par_cnt++] =
+              alloc_printf("%s/SanitizerCoveragePCGUARD.so", obj_path);
+
+        }
+
 #else
   #if LLVM_MAJOR >= 4
         if (!be_quiet)
@@ -590,6 +598,9 @@ static void edit_params(u32 argc, char **argv, char **envp) {
     if (!strcmp(cur, "armv7a-linux-androideabi")) bit_mode = 32;
     if (!strcmp(cur, "-m64")) bit_mode = 64;
 
+    if (!strncmp(cur, "-fsanitize-coverage-", 20) && strstr(cur, "list="))
+      have_instr_list = 1;
+
     if (!strcmp(cur, "-fsanitize=address") || !strcmp(cur, "-fsanitize=memory"))
       asan_set = 1;
 
@@ -856,6 +867,14 @@ int main(int argc, char **argv, char **envp) {
 
     be_quiet = 1;
 
+  if (getenv("AFL_LLVM_INSTRUMENT_FILE") || getenv("AFL_LLVM_WHITELIST") ||
+      getenv("AFL_LLVM_ALLOWLIST") || getenv("AFL_LLVM_DENYLIST") ||
+      getenv("AFL_LLVM_BLOCKLIST")) {
+
+    have_instr_env = 1;
+
+  }
+
   if ((ptr = strrchr(callname, '/')) != NULL) callname = ptr + 1;
   argvnull = (u8 *)argv[0];
   check_environment_vars(envp);
@@ -1015,14 +1034,14 @@ int main(int argc, char **argv, char **envp) {
 
   }
 
-  if ((getenv("AFL_LLVM_INSTRUMENT_FILE") != NULL ||
-       getenv("AFL_LLVM_WHITELIST") || getenv("AFL_LLVM_ALLOWLIST") ||
-       getenv("AFL_LLVM_DENYLIST") || getenv("AFL_LLVM_BLOCKLIST")) &&
-      getenv("AFL_DONT_OPTIMIZE"))
+  if (have_instr_env && getenv("AFL_DONT_OPTIMIZE")) {
+
     WARNF(
         "AFL_LLVM_ALLOWLIST/DENYLIST and AFL_DONT_OPTIMIZE cannot be combined "
         "for file matching, only function matching!");
 
+  }
+
   if (getenv("AFL_LLVM_INSTRIM") || getenv("INSTRIM") ||
       getenv("INSTRIM_LIB")) {
 
@@ -1426,22 +1445,20 @@ int main(int argc, char **argv, char **envp) {
 #if LLVM_MAJOR <= 6
     instrument_mode = INSTRUMENT_AFL;
 #else
-    if (getenv("AFL_LLVM_INSTRUMENT_FILE") != NULL ||
-        getenv("AFL_LLVM_WHITELIST") || getenv("AFL_LLVM_ALLOWLIST") ||
-        getenv("AFL_LLVM_DENYLIST") || getenv("AFL_LLVM_BLOCKLIST")) {
+  #if LLVM_MAJOR < 11 && (LLVM_MAJOR < 10 || LLVM_MINOR < 1)
+    if (have_instr_env) {
 
       instrument_mode = INSTRUMENT_AFL;
-      WARNF(
-          "switching to classic instrumentation because "
-          "AFL_LLVM_ALLOWLIST/DENYLIST does not work with PCGUARD. Use "
-          "-fsanitize-coverage-allowlist=allowlist.txt or "
-          "-fsanitize-coverage-blocklist=denylist.txt if you want to use "
-          "PCGUARD. Requires llvm 12+. See https://clang.llvm.org/docs/ "
-          "SanitizerCoverage.html#partially-disabling-instrumentation");
+      if (!be_quiet)
+        WARNF(
+            "Switching to classic instrumentation because "
+            "AFL_LLVM_ALLOWLIST/DENYLIST does not work with PCGUARD < 10.0.1.");
 
     } else
 
+  #endif
       instrument_mode = INSTRUMENT_PCGUARD;
+
 #endif
 
   }
@@ -1487,18 +1504,16 @@ int main(int argc, char **argv, char **envp) {
         "AFL_LLVM_NOT_ZERO and AFL_LLVM_SKIP_NEVERZERO can not be set "
         "together");
 
-  if (instrument_mode == INSTRUMENT_PCGUARD &&
-      (getenv("AFL_LLVM_INSTRUMENT_FILE") != NULL ||
-       getenv("AFL_LLVM_WHITELIST") || getenv("AFL_LLVM_ALLOWLIST") ||
-       getenv("AFL_LLVM_DENYLIST") || getenv("AFL_LLVM_BLOCKLIST")))
+#if LLVM_MAJOR < 11 && (LLVM_MAJOR < 10 || LLVM_MINOR < 1)
+  if (instrument_mode == INSTRUMENT_PCGUARD && have_instr_env) {
+
     FATAL(
         "Instrumentation type PCGUARD does not support "
-        "AFL_LLVM_ALLOWLIST/DENYLIST! Use "
-        "-fsanitize-coverage-allowlist=allowlist.txt or "
-        "-fsanitize-coverage-blocklist=denylist.txt instead (requires llvm "
-        "12+), see "
-        "https://clang.llvm.org/docs/"
-        "SanitizerCoverage.html#partially-disabling-instrumentation");
+        "AFL_LLVM_ALLOWLIST/DENYLIST! Use LLVM 10.0.1+ instead.");
+
+  }
+
+#endif
 
   u8 *ptr2;
 
diff --git a/src/afl-common.c b/src/afl-common.c
index 19c9419b..8cf1a444 100644
--- a/src/afl-common.c
+++ b/src/afl-common.c
@@ -342,7 +342,7 @@ u8 *find_binary(u8 *fname) {
     if (stat(target_path, &st) || !S_ISREG(st.st_mode) ||
         !(st.st_mode & 0111) || st.st_size < 4) {
 
-      free(target_path);
+      ck_free(target_path);
       FATAL("Program '%s' not found or not executable", fname);
 
     }
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index 45be2abd..3814a77e 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -116,7 +116,7 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) {
   fsrv_to->use_fauxsrv = 0;
   fsrv_to->last_run_timed_out = 0;
 
-  fsrv_to->init_child_func = fsrv_exec_child;
+  fsrv_to->init_child_func = from->init_child_func;
   // Note: do not copy ->add_extra_func
 
   list_append(&fsrv_list, fsrv_to);
@@ -272,7 +272,8 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) {
 
       *(u32 *)fsrv->trace_bits = EXEC_FAIL_SIG;
 
-      PFATAL("Execv failed in fauxserver.");
+      WARNF("Execv failed in fauxserver.");
+      break;
 
     }
 
@@ -286,13 +287,13 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) {
     if (waitpid(child_pid, &status, 0) < 0) {
 
       // Zombie Child could not be collected. Scary!
-      PFATAL("Fauxserver could not determin child's exit code. ");
+      WARNF("Fauxserver could not determine child's exit code. ");
 
     }
 
     /* Relay wait status to AFL pipe, then loop back. */
 
-    if (write(FORKSRV_FD + 1, &status, 4) != 4) { exit(0); }
+    if (write(FORKSRV_FD + 1, &status, 4) != 4) { exit(1); }
 
   }
 
@@ -330,7 +331,7 @@ static void report_error_and_exit(int error) {
           "memory failed.");
       break;
     default:
-      FATAL("unknown error code %u from fuzzing target!", error);
+      FATAL("unknown error code %d from fuzzing target!", error);
 
   }
 
@@ -355,7 +356,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
 
   if (fsrv->use_fauxsrv) {
 
-    /* TODO: Come up with sone nice way to initialize this all */
+    /* TODO: Come up with some nice way to initialize this all */
 
     if (fsrv->init_child_func != fsrv_exec_child) {
 
@@ -520,7 +521,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
 
     *(u32 *)fsrv->trace_bits = EXEC_FAIL_SIG;
     fprintf(stderr, "Error: execv to target failed\n");
-    exit(0);
+    exit(1);
 
   }
 
@@ -1137,7 +1138,7 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
   }
 
   // Fauxserver should handle this now.
-  // if (tb4 == EXEC_FAIL_SIG) return FSRV_RUN_ERROR;
+  if (*(u32 *)fsrv->trace_bits == EXEC_FAIL_SIG) return FSRV_RUN_ERROR;
 
   return FSRV_RUN_OK;
 
diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c
index 4b29672a..2d14b04e 100644
--- a/src/afl-fuzz-bitmap.c
+++ b/src/afl-fuzz-bitmap.c
@@ -591,8 +591,32 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
     add_to_queue(afl, queue_fn, len, 0);
 
 #ifdef INTROSPECTION
-    fprintf(afl->introspection_file, "QUEUE %s = %s\n", afl->mutation,
-            afl->queue_top->fname);
+    if (afl->custom_mutators_count && afl->current_custom_fuzz) {
+
+      LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
+
+        if (afl->current_custom_fuzz == el && el->afl_custom_introspection) {
+
+          const char *ptr = el->afl_custom_introspection(el->data);
+
+          if (ptr != NULL && *ptr != 0) {
+
+            fprintf(afl->introspection_file, "QUEUE CUSTOM %s = %s\n", ptr,
+                    afl->queue_top->fname);
+
+          }
+
+        }
+
+      });
+
+    } else if (afl->mutation[0] != 0) {
+
+      fprintf(afl->introspection_file, "QUEUE %s = %s\n", afl->mutation,
+              afl->queue_top->fname);
+
+    }
+
 #endif
 
     if (hnb == 2) {
@@ -663,7 +687,32 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
 
       ++afl->unique_tmouts;
 #ifdef INTROSPECTION
-      fprintf(afl->introspection_file, "UNIQUE_TIMEOUT %s\n", afl->mutation);
+      if (afl->custom_mutators_count && afl->current_custom_fuzz) {
+
+        LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
+
+          if (afl->current_custom_fuzz == el && el->afl_custom_introspection) {
+
+            const char *ptr = el->afl_custom_introspection(el->data);
+
+            if (ptr != NULL && *ptr != 0) {
+
+              fprintf(afl->introspection_file,
+                      "UNIQUE_TIMEOUT CUSTOM %s = %s\n", ptr,
+                      afl->queue_top->fname);
+
+            }
+
+          }
+
+        });
+
+      } else if (afl->mutation[0] != 0) {
+
+        fprintf(afl->introspection_file, "UNIQUE_TIMEOUT %s\n", afl->mutation);
+
+      }
+
 #endif
 
       /* Before saving, we make sure that it's a genuine hang by re-running
@@ -749,7 +798,31 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
 
       ++afl->unique_crashes;
 #ifdef INTROSPECTION
-      fprintf(afl->introspection_file, "UNIQUE_CRASH %s\n", afl->mutation);
+      if (afl->custom_mutators_count && afl->current_custom_fuzz) {
+
+        LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
+
+          if (afl->current_custom_fuzz == el && el->afl_custom_introspection) {
+
+            const char *ptr = el->afl_custom_introspection(el->data);
+
+            if (ptr != NULL && *ptr != 0) {
+
+              fprintf(afl->introspection_file, "UNIQUE_CRASH CUSTOM %s = %s\n",
+                      ptr, afl->queue_top->fname);
+
+            }
+
+          }
+
+        });
+
+      } else if (afl->mutation[0] != 0) {
+
+        fprintf(afl->introspection_file, "UNIQUE_CRASH %s\n", afl->mutation);
+
+      }
+
 #endif
       if (unlikely(afl->infoexec)) {
 
diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c
index 19a8d77b..6884bb1d 100644
--- a/src/afl-fuzz-init.c
+++ b/src/afl-fuzz-init.c
@@ -2300,12 +2300,6 @@ void fix_up_sync(afl_state_t *afl) {
 
   u8 *x = afl->sync_id;
 
-  if (afl->non_instrumented_mode) {
-
-    FATAL("-S / -M and -n are mutually exclusive");
-
-  }
-
   while (*x) {
 
     if (!isalnum(*x) && *x != '_' && *x != '-') {
@@ -2503,7 +2497,8 @@ void check_binary(afl_state_t *afl, u8 *fname) {
 
   }
 
-  if (afl->afl_env.afl_skip_bin_check || afl->use_wine || afl->unicorn_mode) {
+  if (afl->afl_env.afl_skip_bin_check || afl->use_wine || afl->unicorn_mode ||
+      afl->non_instrumented_mode) {
 
     return;
 
diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c
index c4d7233c..1d14f657 100644
--- a/src/afl-fuzz-mutators.c
+++ b/src/afl-fuzz-mutators.c
@@ -166,6 +166,13 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
 
   }
 
+  /* "afl_custom_introspection", optional */
+#ifdef INTROSPECTION
+  mutator->afl_custom_introspection = dlsym(dh, "afl_custom_introspection");
+  if (!mutator->afl_custom_introspection)
+    ACTF("optional symbol 'afl_custom_introspection' not found.");
+#endif
+
   /* "afl_custom_fuzz_count", optional */
   mutator->afl_custom_fuzz_count = dlsym(dh, "afl_custom_fuzz_count");
   if (!mutator->afl_custom_fuzz_count)
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index 91bbced6..0adc3719 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -1780,10 +1780,16 @@ custom_mutator_stage:
 
   orig_hit_cnt = afl->queued_paths + afl->unique_crashes;
 
+#ifdef INTROSPECTION
+  afl->mutation[0] = 0;
+#endif
+
   LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
 
     if (el->afl_custom_fuzz) {
 
+      afl->current_custom_fuzz = el;
+
       if (el->afl_custom_fuzz_count)
         afl->stage_max = el->afl_custom_fuzz_count(el->data, out_buf, len);
       else
@@ -1840,12 +1846,6 @@ custom_mutator_stage:
 
           if (mutated_size > 0) {
 
-#ifdef INTROSPECTION
-            snprintf(afl->mutation, sizeof(afl->mutation), "%s CUSTOM-%s",
-                     afl->queue_cur->fname,
-                     target != NULL ? (char *)target->fname : "none");
-#endif
-
             if (common_fuzz_stuff(afl, mutated_buf, (u32)mutated_size)) {
 
               goto abandon_entry;
@@ -1889,6 +1889,8 @@ custom_mutator_stage:
 
   });
 
+  afl->current_custom_fuzz = NULL;
+
   if (!has_custom_fuzz) goto havoc_stage;
 
   new_hit_cnt = afl->queued_paths + afl->unique_crashes;
diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c
index adb92649..cfaf055d 100644
--- a/src/afl-fuzz-python.c
+++ b/src/afl-fuzz-python.c
@@ -163,6 +163,8 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
         PyObject_GetAttrString(py_module, "queue_get");
     py_functions[PY_FUNC_QUEUE_NEW_ENTRY] =
         PyObject_GetAttrString(py_module, "queue_new_entry");
+    py_functions[PY_FUNC_INTROSPECTION] =
+        PyObject_GetAttrString(py_module, "introspection");
     py_functions[PY_FUNC_DEINIT] = PyObject_GetAttrString(py_module, "deinit");
     if (!py_functions[PY_FUNC_DEINIT])
       FATAL("deinit function not found in python module");
@@ -212,6 +214,7 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
 
     PyErr_Print();
     fprintf(stderr, "Failed to load \"%s\"\n", module_name);
+    free(py);
     return NULL;
 
   }
@@ -326,9 +329,7 @@ struct custom_mutator *load_custom_mutator_py(afl_state_t *afl,
 
   if (py_functions[PY_FUNC_DEINIT]) { 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. */
-  mutator->afl_custom_fuzz = fuzz_py;
+  if (py_functions[PY_FUNC_FUZZ]) { mutator->afl_custom_fuzz = fuzz_py; }
 
   if (py_functions[PY_FUNC_POST_PROCESS]) {
 
@@ -381,6 +382,15 @@ struct custom_mutator *load_custom_mutator_py(afl_state_t *afl,
 
   }
 
+  #ifdef INTROSPECTION
+  if (py_functions[PY_FUNC_INTROSPECTION]) {
+
+    mutator->afl_custom_introspection = introspection_py;
+
+  }
+
+  #endif
+
   OKF("Python mutator '%s' installed successfully.", module_name);
 
   /* Initialize the custom mutator */
@@ -679,6 +689,28 @@ u8 havoc_mutation_probability_py(void *py_mutator) {
 
 }
 
+const char *introspection_py(void *py_mutator) {
+
+  PyObject *py_args, *py_value;
+
+  py_args = PyTuple_New(0);
+  py_value = PyObject_CallObject(
+      ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_INTROSPECTION],
+      py_args);
+  Py_DECREF(py_args);
+
+  if (py_value == NULL) {
+
+    return NULL;
+
+  } else {
+
+    return PyByteArray_AsString(py_value);
+
+  }
+
+}
+
 u8 queue_get_py(void *py_mutator, const u8 *filename) {
 
   PyObject *py_args, *py_value;
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index 269ce1bf..cedfdf8f 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -435,9 +435,26 @@ int main(int argc, char **argv_orig, char **envp) {
 
         u8 *c;
 
+        if (afl->non_instrumented_mode) {
+
+          FATAL("-M is not supported in non-instrumented mode");
+
+        }
+
         if (afl->sync_id) { FATAL("Multiple -S or -M options not supported"); }
+
+        /* sanity check for argument: should not begin with '-' (possible
+         * option) */
+        if (optarg && *optarg == '-') {
+
+          FATAL(
+              "argument for -M started with a dash '-', which is used for "
+              "options");
+
+        }
+
         afl->sync_id = ck_strdup(optarg);
-        afl->skip_deterministic = 0;  // force determinsitic fuzzing
+        afl->skip_deterministic = 0;  // force deterministic fuzzing
         afl->old_seed_selection = 1;  // force old queue walking seed selection
 
         if ((c = strchr(afl->sync_id, ':'))) {
@@ -464,7 +481,24 @@ int main(int argc, char **argv_orig, char **envp) {
 
       case 'S':                                        /* secondary sync id */
 
+        if (afl->non_instrumented_mode) {
+
+          FATAL("-S is not supported in non-instrumented mode");
+
+        }
+
         if (afl->sync_id) { FATAL("Multiple -S or -M options not supported"); }
+
+        /* sanity check for argument: should not begin with '-' (possible
+         * option) */
+        if (optarg && *optarg == '-') {
+
+          FATAL(
+              "argument for -M started with a dash '-', which is used for "
+              "options");
+
+        }
+
         afl->sync_id = ck_strdup(optarg);
         afl->is_secondary_node = 1;
         break;
@@ -620,6 +654,12 @@ int main(int argc, char **argv_orig, char **envp) {
 
       case 'n':                                                /* dumb mode */
 
+        if (afl->is_main_node || afl->is_secondary_node) {
+
+          FATAL("Non instrumented mode is not supported with -M / -S");
+
+        }
+
         if (afl->non_instrumented_mode) {
 
           FATAL("Multiple -n options not supported");
@@ -906,7 +946,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
   afl->power_name = power_names[afl->schedule];
 
-  if (!afl->sync_id) {
+  if (!afl->non_instrumented_mode && !afl->sync_id) {
 
     auto_sync = 1;
     afl->sync_id = ck_strdup("default");
@@ -1338,7 +1378,11 @@ int main(int argc, char **argv_orig, char **envp) {
 
     }
 
-    if (!afl->fsrv.qemu_mode) { check_binary(afl, afl->cmplog_binary); }
+    if (!afl->fsrv.qemu_mode && !afl->non_instrumented_mode) {
+
+      check_binary(afl, afl->cmplog_binary);
+
+    }
 
   }
 
diff --git a/src/afl-gotcpu.c b/src/afl-gotcpu.c
index bd0f7de6..1aea3e40 100644
--- a/src/afl-gotcpu.c
+++ b/src/afl-gotcpu.c
@@ -65,7 +65,6 @@
     #define cpu_set_t cpuset_t
   #elif defined(__NetBSD__)
     #include <pthread.h>
-    #include <sched.h>
   #elif defined(__APPLE__)
     #include <pthread.h>
     #include <mach/thread_act.h>
diff --git a/unicorn_mode/samples/persistent/simple_target_noncrashing.c b/unicorn_mode/samples/persistent/simple_target_noncrashing.c
index 00764473..9257643b 100644
--- a/unicorn_mode/samples/persistent/simple_target_noncrashing.c
+++ b/unicorn_mode/samples/persistent/simple_target_noncrashing.c
@@ -10,7 +10,7 @@
  * Written by Nathan Voss <njvoss99@gmail.com>
  * Adapted by Lukas Seidel <seidel.1@campus.tu-berlin.de>
  */
-
+#include <string.h>
 
 int main(int argc, char** argv) {
   if(argc < 2){
@@ -19,15 +19,19 @@ int main(int argc, char** argv) {
 
   char *data_buf = argv[1];
 
-  if len(data_buf < 20) {
-  if (data_buf[20] != 0) {
+  if (strlen(data_buf) >= 21 && data_buf[20] != 0) {
     printf("Not crashing");
-  } else if (data_buf[0] > 0x10 && data_buf[0] < 0x20 && data_buf[1] > data_buf[2]) {
+  } else if (strlen(data_buf) > 1
+             && data_buf[0] > 0x10 && data_buf[0] < 0x20 && data_buf[1] > data_buf[2]) {
     printf("Also not crashing with databuf[0] == %c", data_buf[0])
-  } else if (data_buf[9] == 0x00 && data_buf[10] != 0x00 && data_buf[11] == 0x00) {
+  }
+#if 0
+  // not possible with argv (zero terminated strings) (hexcoder-)
+  // do not try to access data_buf[10] and beyond
+  else if (data_buf[9] == 0x00 && data_buf[10] != 0x00 && data_buf[11] == 0x00) {
     // Cause a crash if data[10] is not zero, but [9] and [11] are zero
     unsigned char invalid_read = *(unsigned char *) 0x00000000;
   }
-
+#endif
   return 0;
 }
diff --git a/unicorn_mode/unicornafl b/unicorn_mode/unicornafl
-Subproject 0bf26f6c2601e1c1c84998551ed7d50b4108fbd
+Subproject f44ec48f8d5929f243522c1152b5b3c0985a554