about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--GNUmakefile2
-rw-r--r--README.md4
-rw-r--r--docs/Changelog.md17
-rw-r--r--docs/afl-fuzz_approach.md4
-rw-r--r--docs/custom_mutators.md4
-rw-r--r--docs/fuzzing_binary-only_targets.md8
-rw-r--r--docs/tutorials.md5
-rw-r--r--frida_mode/src/main.c4
-rw-r--r--frida_mode/src/ranges.c2
-rw-r--r--include/afl-mutations.h35
-rw-r--r--include/config.h2
-rw-r--r--include/envs.h1
-rw-r--r--instrumentation/SanitizerCoverageLTO.so.cc54
-rw-r--r--instrumentation/SanitizerCoveragePCGUARD.so.cc4
-rw-r--r--instrumentation/afl-llvm-common.cc8
-rw-r--r--instrumentation/afl-llvm-dict2file.so.cc33
-rw-r--r--instrumentation/cmplog-routines-pass.cc15
-rw-r--r--instrumentation/compare-transform-pass.so.cc30
m---------nyx_mode/QEMU-Nyx0
m---------nyx_mode/libnyx0
m---------nyx_mode/packer0
-rw-r--r--src/afl-cc.c2
-rw-r--r--src/afl-fuzz-bitmap.c11
-rw-r--r--src/afl-fuzz-state.c3
-rw-r--r--src/afl-fuzz.c2
-rw-r--r--utils/aflpp_driver/aflpp_driver.c7
26 files changed, 163 insertions, 94 deletions
diff --git a/GNUmakefile b/GNUmakefile
index 5fd37147..364cdde1 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -816,7 +816,7 @@ endif
 
 .PHONY: uninstall
 uninstall:
-	-cd $${DESTDIR}$(BIN_PATH) && rm -f $(PROGS) $(SH_PROGS) afl-cs-proxy afl-qemu-trace afl-plot-ui afl-fuzz-document afl-network-server afl-g* afl-plot.sh afl-as afl-ld-lto afl-c* afl-lto*
+	-cd $${DESTDIR}$(BIN_PATH) && rm -f $(PROGS) $(SH_PROGS) afl-cs-proxy afl-qemu-trace afl-plot-ui afl-fuzz-document afl-network-client afl-network-server afl-g* afl-plot.sh afl-as afl-ld-lto afl-c* afl-lto*
 	-cd $${DESTDIR}$(HELPER_PATH) && rm -f afl-g*.*o afl-llvm-*.*o afl-compiler-*.*o libdislocator.so libtokencap.so libcompcov.so libqasan.so afl-frida-trace.so libnyx.so socketfuzz*.so argvfuzz*.so libAFLDriver.a libAFLQemuDriver.a as afl-as SanitizerCoverage*.so compare-transform-pass.so cmplog-*-pass.so split-*-pass.so dynamic_list.txt
 	-rm -rf $${DESTDIR}$(MISC_PATH)/testcases $${DESTDIR}$(MISC_PATH)/dictionaries
 	-sh -c "ls docs/*.md | sed 's|^docs/|$${DESTDIR}$(DOC_PATH)/|' | xargs rm -f"
diff --git a/README.md b/README.md
index 322ebcf2..fd48cb14 100644
--- a/README.md
+++ b/README.md
@@ -2,9 +2,9 @@
 
 <img align="right" src="https://raw.githubusercontent.com/AFLplusplus/Website/main/static/aflpp_bg.svg" alt="AFL++ logo" width="250" heigh="250">
 
-Release version: [4.08c](https://github.com/AFLplusplus/AFLplusplus/releases)
+Release version: [4.09c](https://github.com/AFLplusplus/AFLplusplus/releases)
 
-GitHub version: 4.09a
+GitHub version: 4.10a
 
 Repository:
 [https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
diff --git a/docs/Changelog.md b/docs/Changelog.md
index b2e9fbf6..c8f04217 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -3,8 +3,19 @@
   This is the list of all noteworthy changes made in every public
   release of the tool. See README.md for the general instruction manual.
 
-### Version ++4.09a (dev)
+### Version ++4.10a (dev)
   - afl-fuzz:
+    - default power schedule is now EXPLORE, due a fix in fast schedules
+      explore is slightly better now.
+    - fixed minor issues in the mutation engine, thanks to @futhewo for
+      reporting!
+  - instrumentation:
+    - LLVM 18 support, thanks to @devnexen!
+
+
+### Version ++4.09c (release)
+  - afl-fuzz:
+    - fixed the new mutation implementation for two bugs
     - added `AFL_FINAL_SYNC` which forces a final fuzzer sync (also for `-F`)
       before terminating.
     - added AFL_IGNORE_SEED_PROBLEMS to skip over seeds that time out instead
@@ -23,14 +34,16 @@
     - option -n will not use color in the output
   - instrumentation:
     - fix for a few string compare transform functions for LAF
+    - we are instrumenting __cxx internal functions again. this might break
+      a few targets, please report if so.
   - frida_mode:
     - fixes support for large map offsets
+  - support for AFL_FUZZER_LOOPCOUNT for afl.rs and LLVMFuzzerTestOneInput
   - afl-cmin/afl-cmin.bash: prevent unneeded file errors
   - added new tool afl-addseeds that adds new seeds to a running campaign
   - added benchmark/benchmark.py if you want to see how good your fuzzing
     speed is in comparison to other setups.
 
-
 ### Version ++4.08c (release)
   - afl-fuzz:
     - new mutation engine: mutations that favor discovery more paths are
diff --git a/docs/afl-fuzz_approach.md b/docs/afl-fuzz_approach.md
index 7d18b178..9ea06325 100644
--- a/docs/afl-fuzz_approach.md
+++ b/docs/afl-fuzz_approach.md
@@ -5,6 +5,10 @@ instrumentation-guided genetic algorithm. It uses a modified form of edge
 coverage to effortlessly pick up subtle, local-scale changes to program control
 flow.
 
+Note: If you are interested in a more current up-to-date deep dive how AFL++
+works then we commend this blog post:
+[https://blog.ritsec.club/posts/afl-under-hood/](https://blog.ritsec.club/posts/afl-under-hood/)
+
 Simplifying a bit, the overall algorithm can be summed up as:
 
 1) Load user-supplied initial test cases into the queue.
diff --git a/docs/custom_mutators.md b/docs/custom_mutators.md
index 1c4ab2cf..ce0a42dc 100644
--- a/docs/custom_mutators.md
+++ b/docs/custom_mutators.md
@@ -198,7 +198,7 @@ def deinit():  # optional for Python
     This method can be used if you want to send data to the target yourself,
     e.g. via IPC. This replaces some usage of utils/afl_proxy but requires
     that you start the target with afl-fuzz.
-    Example: [custom_mutators/examples/custom_send.c](custom_mutators/examples/custom_send.c)
+    Example: [custom_mutators/examples/custom_send.c](../custom_mutators/examples/custom_send.c)
 
 - `queue_new_entry` (optional):
 
@@ -377,4 +377,4 @@ See [example.c](../custom_mutators/examples/example.c) and
     - [bruce30262/libprotobuf-mutator_fuzzing_learning](https://github.com/bruce30262/libprotobuf-mutator_fuzzing_learning/tree/master/4_libprotobuf_aflpp_custom_mutator)
     - [thebabush/afl-libprotobuf-mutator](https://github.com/thebabush/afl-libprotobuf-mutator)
 - [XML Fuzzing@NullCon 2017](https://www.agarri.fr/docs/XML_Fuzzing-NullCon2017-PUBLIC.pdf)
-    - [A bug detected by AFL + XML-aware mutators](https://bugs.chromium.org/p/chromium/issues/detail?id=930663)
\ No newline at end of file
+    - [A bug detected by AFL + XML-aware mutators](https://bugs.chromium.org/p/chromium/issues/detail?id=930663)
diff --git a/docs/fuzzing_binary-only_targets.md b/docs/fuzzing_binary-only_targets.md
index 9d9d6bb6..a151bce4 100644
--- a/docs/fuzzing_binary-only_targets.md
+++ b/docs/fuzzing_binary-only_targets.md
@@ -94,8 +94,7 @@ For more information, see
 
 In FRIDA mode, you can fuzz binary-only targets as easily as with QEMU mode.
 FRIDA mode is most of the times slightly faster than QEMU mode. It is also
-newer, lacks COMPCOV, and has the advantage that it works on MacOS (both intel
-and M1).
+newer, and has the advantage that it works on MacOS (both intel and M1).
 
 To build FRIDA mode:
 
@@ -113,10 +112,6 @@ The mode is approximately 2-5x slower than compile-time instrumentation, and is
 less conducive to parallelization. But for binary-only fuzzing, it gives a huge
 speed improvement if it is possible to use.
 
-If you want to fuzz a binary-only library, then you can fuzz it with frida-gum
-via frida_mode/. You will have to write a harness to call the target function in
-the library, use afl-frida.c as a template.
-
 You can also perform remote fuzzing with frida, e.g., if you want to fuzz on
 iPhone or Android devices, for this you can use
 [https://github.com/ttdennis/fpicker/](https://github.com/ttdennis/fpicker/) as
@@ -302,7 +297,6 @@ some are very hard to set up...
 * S2E: [https://github.com/S2E](https://github.com/S2E)
 * TinyInst:
   [https://github.com/googleprojectzero/TinyInst](https://github.com/googleprojectzero/TinyInst)
-  (Mac/Windows only)
 *  ... please send me any missing that are good
 
 ## Closing words
diff --git a/docs/tutorials.md b/docs/tutorials.md
index a5ee3322..0a09f6dc 100644
--- a/docs/tutorials.md
+++ b/docs/tutorials.md
@@ -21,7 +21,7 @@ training, then we can highly recommend the following:
 
 * [https://github.com/antonio-morales/Fuzzing101](https://github.com/antonio-morales/Fuzzing101)
 
-Here is a good forkflow description (and tutorial) for qemu_mode:
+Here is a good workflow description (and tutorial) for qemu_mode:
 
 * [https://airbus-seclab.github.io/AFLplusplus-blogpost/](https://airbus-seclab.github.io/AFLplusplus-blogpost/)
 
@@ -41,6 +41,9 @@ structure is), these links have you covered (some are outdated though):
 * Superion for AFL++:
   [https://github.com/adrian-rt/superion-mutator](https://github.com/adrian-rt/superion-mutator)
 
+For a very in-depth explanation on how AFL++ works check out:
+[https://blog.ritsec.club/posts/afl-under-hood/](https://blog.ritsec.club/posts/afl-under-hood/)
+
 ## Video Tutorials
 
 * [Install AFL++ Ubuntu](https://www.youtube.com/watch?v=5dCvhkbi3RA)
diff --git a/frida_mode/src/main.c b/frida_mode/src/main.c
index bd7b1351..9daf067b 100644
--- a/frida_mode/src/main.c
+++ b/frida_mode/src/main.c
@@ -166,7 +166,7 @@ static void afl_print_env(void) {
 
   if (fd < 0) {
 
-    FWARNF("Failed to open /proc/self/cmdline, errno: (%d)", errno);
+    FWARNF("Failed to open /proc/self/environ, errno: (%d)", errno);
     return;
 
   }
@@ -174,7 +174,7 @@ static void afl_print_env(void) {
   ssize_t bytes_read = read(fd, buffer, PROC_MAX - 1);
   if (bytes_read < 0) {
 
-    FFATAL("Failed to read /proc/self/cmdline, errno: (%d)", errno);
+    FFATAL("Failed to read /proc/self/environ, errno: (%d)", errno);
 
   }
 
diff --git a/frida_mode/src/ranges.c b/frida_mode/src/ranges.c
index e9fc3b4e..269ba59b 100644
--- a/frida_mode/src/ranges.c
+++ b/frida_mode/src/ranges.c
@@ -653,7 +653,7 @@ void ranges_init(void) {
   /*
    * After step 4 we have the total ranges to be instrumented, we now subtract
    * that either from the original ranges of the modules or from the whole
-   * memory if AFL_INST_NO_DYNAMIC_LOAD to configure the stalker.
+   * memory if AFL_FRIDA_INST_NO_DYNAMIC_LOAD to configure the stalker.
    */
   if (ranges_inst_dynamic_load) {
 
diff --git a/include/afl-mutations.h b/include/afl-mutations.h
index d709b90d..75e66484 100644
--- a/include/afl-mutations.h
+++ b/include/afl-mutations.h
@@ -1082,6 +1082,7 @@ u32 mutation_strategy_exploration_binary[MUT_STRATEGY_ARRAY_SIZE] = {
     MUT_CLONE_COPY,
     MUT_CLONE_COPY,
     MUT_CLONE_COPY,
+    MUT_CLONE_COPY,
     MUT_CLONE_FIXED,
     MUT_CLONE_FIXED,
     MUT_CLONE_FIXED,
@@ -2456,14 +2457,14 @@ inline u32 afl_mutate(afl_state_t *afl, u8 *buf, u32 len, u32 steps,
 
         }
 
-        char buf[20];
-        snprintf(buf, sizeof(buf), "%" PRId64, val);
+        char numbuf[32];
+        snprintf(numbuf, sizeof(buf), "%" PRId64, val);
         u32 old_len = off2 - off;
-        u32 new_len = strlen(buf);
+        u32 new_len = strlen(numbuf);
 
         if (old_len == new_len) {
 
-          memcpy(buf + off, buf, new_len);
+          memcpy(buf + off, numbuf, new_len);
 
         } else {
 
@@ -2473,7 +2474,7 @@ inline u32 afl_mutate(afl_state_t *afl, u8 *buf, u32 len, u32 steps,
 
           /* Inserted part */
 
-          memcpy(tmp_buf + off, buf, new_len);
+          memcpy(tmp_buf + off, numbuf, new_len);
 
           /* Tail */
           memcpy(tmp_buf + off + new_len, buf + off2, len - off2);
@@ -2490,12 +2491,13 @@ inline u32 afl_mutate(afl_state_t *afl, u8 *buf, u32 len, u32 steps,
 
       case MUT_INSERTASCIINUM: {
 
-        u32 len = 1 + rand_below(afl, 8);
+        u32 ins_len = 1 + rand_below(afl, 8);
         u32 pos = rand_below(afl, len);
 
         /* Insert ascii number. */
-        if (unlikely(len < pos + len)) {
+        if (unlikely(len < pos + ins_len)) {
 
+          // no retry if we have a small input
           if (unlikely(len < 8)) {
 
             break;
@@ -2509,9 +2511,22 @@ inline u32 afl_mutate(afl_state_t *afl, u8 *buf, u32 len, u32 steps,
         }
 
         u64  val = rand_next(afl);
-        char buf[20];
-        snprintf(buf, sizeof(buf), "%llu", val);
-        memcpy(buf + pos, buf, len);
+        char numbuf[32];
+        snprintf(numbuf, sizeof(numbuf), "%llu", val);
+        size_t val_len = strlen(numbuf), off;
+
+        if (ins_len > val_len) {
+
+          ins_len = val_len;
+          off = 0;
+
+        } else {
+
+          off = val_len - ins_len;
+
+        }
+
+        memcpy(buf + pos, numbuf + off, ins_len);
 
         break;
 
diff --git a/include/config.h b/include/config.h
index 988e536e..63340650 100644
--- a/include/config.h
+++ b/include/config.h
@@ -26,7 +26,7 @@
 /* Version string: */
 
 // c = release, a = volatile github dev, e = experimental branch
-#define VERSION "++4.09a"
+#define VERSION "++4.10a"
 
 /******************************************************
  *                                                    *
diff --git a/include/envs.h b/include/envs.h
index 93e49e34..560092d9 100644
--- a/include/envs.h
+++ b/include/envs.h
@@ -172,6 +172,7 @@ static char *afl_environment_variables[] = {
     "AFL_LLVM_LTO_DONTWRITEID",
     "AFL_LLVM_LTO_SKIPINIT"
     "AFL_LLVM_LTO_STARTID",
+    "AFL_FUZZER_LOOPCOUNT",
     "AFL_NO_ARITH",
     "AFL_NO_AUTODICT",
     "AFL_NO_BUILTIN",
diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc
index c70fbd4f..68423029 100644
--- a/instrumentation/SanitizerCoverageLTO.so.cc
+++ b/instrumentation/SanitizerCoverageLTO.so.cc
@@ -692,33 +692,37 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
              * prototype */
             FunctionType *FT = Callee->getFunctionType();
 
-            isStrcmp &= FT->getNumParams() == 2 &&
-                        FT->getReturnType()->isIntegerTy(32) &&
-                        FT->getParamType(0) == FT->getParamType(1) &&
-                        FT->getParamType(0) ==
-                            IntegerType::getInt8PtrTy(M.getContext());
-            isStrcasecmp &= FT->getNumParams() == 2 &&
-                            FT->getReturnType()->isIntegerTy(32) &&
-                            FT->getParamType(0) == FT->getParamType(1) &&
-                            FT->getParamType(0) ==
-                                IntegerType::getInt8PtrTy(M.getContext());
+            isStrcmp &=
+                FT->getNumParams() == 2 &&
+                FT->getReturnType()->isIntegerTy(32) &&
+                FT->getParamType(0) == FT->getParamType(1) &&
+                FT->getParamType(0) ==
+                    IntegerType::getInt8Ty(M.getContext())->getPointerTo(0);
+            isStrcasecmp &=
+                FT->getNumParams() == 2 &&
+                FT->getReturnType()->isIntegerTy(32) &&
+                FT->getParamType(0) == FT->getParamType(1) &&
+                FT->getParamType(0) ==
+                    IntegerType::getInt8Ty(M.getContext())->getPointerTo(0);
             isMemcmp &= FT->getNumParams() == 3 &&
                         FT->getReturnType()->isIntegerTy(32) &&
                         FT->getParamType(0)->isPointerTy() &&
                         FT->getParamType(1)->isPointerTy() &&
                         FT->getParamType(2)->isIntegerTy();
-            isStrncmp &= FT->getNumParams() == 3 &&
-                         FT->getReturnType()->isIntegerTy(32) &&
-                         FT->getParamType(0) == FT->getParamType(1) &&
-                         FT->getParamType(0) ==
-                             IntegerType::getInt8PtrTy(M.getContext()) &&
-                         FT->getParamType(2)->isIntegerTy();
-            isStrncasecmp &= FT->getNumParams() == 3 &&
-                             FT->getReturnType()->isIntegerTy(32) &&
-                             FT->getParamType(0) == FT->getParamType(1) &&
-                             FT->getParamType(0) ==
-                                 IntegerType::getInt8PtrTy(M.getContext()) &&
-                             FT->getParamType(2)->isIntegerTy();
+            isStrncmp &=
+                FT->getNumParams() == 3 &&
+                FT->getReturnType()->isIntegerTy(32) &&
+                FT->getParamType(0) == FT->getParamType(1) &&
+                FT->getParamType(0) ==
+                    IntegerType::getInt8Ty(M.getContext())->getPointerTo(0) &&
+                FT->getParamType(2)->isIntegerTy();
+            isStrncasecmp &=
+                FT->getNumParams() == 3 &&
+                FT->getReturnType()->isIntegerTy(32) &&
+                FT->getParamType(0) == FT->getParamType(1) &&
+                FT->getParamType(0) ==
+                    IntegerType::getInt8Ty(M.getContext())->getPointerTo(0) &&
+                FT->getParamType(2)->isIntegerTy();
             isStdString &= FT->getNumParams() >= 2 &&
                            FT->getParamType(0)->isPointerTy() &&
                            FT->getParamType(1)->isPointerTy();
@@ -1241,7 +1245,11 @@ void ModuleSanitizerCoverageLTO::instrumentFunction(
   if (F.empty()) return;
   if (F.getName().find(".module_ctor") != std::string::npos)
     return;  // Should not instrument sanitizer init functions.
+#if LLVM_VERSION_MAJOR >= 18
+  if (F.getName().starts_with("__sanitizer_"))
+#else
   if (F.getName().startswith("__sanitizer_"))
+#endif
     return;  // Don't instrument __sanitizer_* callbacks.
   // Don't touch available_externally functions, their actual body is elsewhere.
   if (F.getLinkage() == GlobalValue::AvailableExternallyLinkage) return;
@@ -1493,7 +1501,7 @@ GlobalVariable *ModuleSanitizerCoverageLTO::CreateFunctionLocalArrayInSection(
       Array->setComdat(Comdat);
 #endif
   Array->setSection(getSectionName(Section));
-  Array->setAlignment(Align(DL->getTypeStoreSize(Ty).getFixedSize()));
+  Array->setAlignment(Align(DL->getTypeStoreSize(Ty).getFixedValue()));
   GlobalsToAppendToUsed.push_back(Array);
   GlobalsToAppendToCompilerUsed.push_back(Array);
   MDNode *MD = MDNode::get(F.getContext(), ValueAsMetadata::get(&F));
diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc
index 588eb950..1c019d26 100644
--- a/instrumentation/SanitizerCoveragePCGUARD.so.cc
+++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc
@@ -572,7 +572,11 @@ void ModuleSanitizerCoverageAFL::instrumentFunction(
   if (!isInInstrumentList(&F, FMNAME)) return;
   if (F.getName().find(".module_ctor") != std::string::npos)
     return;  // Should not instrument sanitizer init functions.
+#if LLVM_VERSION_MAJOR >= 18
+  if (F.getName().starts_with("__sanitizer_"))
+#else
   if (F.getName().startswith("__sanitizer_"))
+#endif
     return;  // Don't instrument __sanitizer_* callbacks.
   // Don't touch available_externally functions, their actual body is elewhere.
   if (F.getLinkage() == GlobalValue::AvailableExternallyLinkage) return;
diff --git a/instrumentation/afl-llvm-common.cc b/instrumentation/afl-llvm-common.cc
index 7f17b02d..96952bd6 100644
--- a/instrumentation/afl-llvm-common.cc
+++ b/instrumentation/afl-llvm-common.cc
@@ -97,11 +97,15 @@ bool isIgnoreFunction(const llvm::Function *F) {
 
   static constexpr const char *ignoreSubstringList[] = {
 
-      "__asan", "__msan",       "__ubsan",    "__lsan",  "__san", "__sanitize",
-      "__cxx",  "DebugCounter", "DwarfDebug", "DebugLoc"
+      "__asan",     "__msan",       "__ubsan",    "__lsan",  "__san",
+      "__sanitize", "DebugCounter", "DwarfDebug", "DebugLoc"
 
   };
 
+  // This check is very sensitive, we must be sure to not include patterns
+  // that are part of user-written C++ functions like the ones including
+  // std::string as parameter (see #1927) as the mangled type is inserted in the
+  // mangled name of the user-written function
   for (auto const &ignoreListFunc : ignoreSubstringList) {
 
     // hexcoder: F->getName().contains() not avaiilable in llvm 3.8.0
diff --git a/instrumentation/afl-llvm-dict2file.so.cc b/instrumentation/afl-llvm-dict2file.so.cc
index 59b16ca0..c60f3e06 100644
--- a/instrumentation/afl-llvm-dict2file.so.cc
+++ b/instrumentation/afl-llvm-dict2file.so.cc
@@ -433,32 +433,35 @@ bool AFLdict2filePass::runOnModule(Module &M) {
           isStrstr &=
               FT->getNumParams() == 2 &&
               FT->getParamType(0) == FT->getParamType(1) &&
-              FT->getParamType(0) == IntegerType::getInt8PtrTy(M.getContext());
+              FT->getParamType(0) ==
+                  IntegerType::getInt8Ty(M.getContext())->getPointerTo(0);
           isStrcmp &=
               FT->getNumParams() == 2 && FT->getReturnType()->isIntegerTy(32) &&
               FT->getParamType(0) == FT->getParamType(1) &&
-              FT->getParamType(0) == IntegerType::getInt8PtrTy(M.getContext());
+              FT->getParamType(0) ==
+                  IntegerType::getInt8Ty(M.getContext())->getPointerTo(0);
           isStrcasecmp &=
               FT->getNumParams() == 2 && FT->getReturnType()->isIntegerTy(32) &&
               FT->getParamType(0) == FT->getParamType(1) &&
-              FT->getParamType(0) == IntegerType::getInt8PtrTy(M.getContext());
+              FT->getParamType(0) ==
+                  IntegerType::getInt8Ty(M.getContext())->getPointerTo(0);
           isMemcmp &= FT->getNumParams() == 3 &&
                       FT->getReturnType()->isIntegerTy(32) &&
                       FT->getParamType(0)->isPointerTy() &&
                       FT->getParamType(1)->isPointerTy() &&
                       FT->getParamType(2)->isIntegerTy();
-          isStrncmp &= FT->getNumParams() == 3 &&
-                       FT->getReturnType()->isIntegerTy(32) &&
-                       FT->getParamType(0) == FT->getParamType(1) &&
-                       FT->getParamType(0) ==
-                           IntegerType::getInt8PtrTy(M.getContext()) &&
-                       FT->getParamType(2)->isIntegerTy();
-          isStrncasecmp &= FT->getNumParams() == 3 &&
-                           FT->getReturnType()->isIntegerTy(32) &&
-                           FT->getParamType(0) == FT->getParamType(1) &&
-                           FT->getParamType(0) ==
-                               IntegerType::getInt8PtrTy(M.getContext()) &&
-                           FT->getParamType(2)->isIntegerTy();
+          isStrncmp &=
+              FT->getNumParams() == 3 && FT->getReturnType()->isIntegerTy(32) &&
+              FT->getParamType(0) == FT->getParamType(1) &&
+              FT->getParamType(0) ==
+                  IntegerType::getInt8Ty(M.getContext())->getPointerTo(0) &&
+              FT->getParamType(2)->isIntegerTy();
+          isStrncasecmp &=
+              FT->getNumParams() == 3 && FT->getReturnType()->isIntegerTy(32) &&
+              FT->getParamType(0) == FT->getParamType(1) &&
+              FT->getParamType(0) ==
+                  IntegerType::getInt8Ty(M.getContext())->getPointerTo(0) &&
+              FT->getParamType(2)->isIntegerTy();
           isStdString &= FT->getNumParams() >= 2 &&
                          FT->getParamType(0)->isPointerTy() &&
                          FT->getParamType(1)->isPointerTy();
diff --git a/instrumentation/cmplog-routines-pass.cc b/instrumentation/cmplog-routines-pass.cc
index 54e9ddf3..b27e06e0 100644
--- a/instrumentation/cmplog-routines-pass.cc
+++ b/instrumentation/cmplog-routines-pass.cc
@@ -385,7 +385,8 @@ bool CmpLogRoutines::hookRtns(Module &M) {
           isStrcmp &=
               FT->getNumParams() == 2 && FT->getReturnType()->isIntegerTy(32) &&
               FT->getParamType(0) == FT->getParamType(1) &&
-              FT->getParamType(0) == IntegerType::getInt8PtrTy(M.getContext());
+              FT->getParamType(0) ==
+                  IntegerType::getInt8Ty(M.getContext())->getPointerTo(0);
 
           bool isStrncmp = (!FuncName.compare("strncmp") ||
                             !FuncName.compare("xmlStrncmp") ||
@@ -398,12 +399,12 @@ bool CmpLogRoutines::hookRtns(Module &M) {
                             !FuncName.compare("g_ascii_strncasecmp") ||
                             !FuncName.compare("Curl_strncasecompare") ||
                             !FuncName.compare("g_strncasecmp"));
-          isStrncmp &= FT->getNumParams() == 3 &&
-                       FT->getReturnType()->isIntegerTy(32) &&
-                       FT->getParamType(0) == FT->getParamType(1) &&
-                       FT->getParamType(0) ==
-                           IntegerType::getInt8PtrTy(M.getContext()) &&
-                       FT->getParamType(2)->isIntegerTy();
+          isStrncmp &=
+              FT->getNumParams() == 3 && FT->getReturnType()->isIntegerTy(32) &&
+              FT->getParamType(0) == FT->getParamType(1) &&
+              FT->getParamType(0) ==
+                  IntegerType::getInt8Ty(M.getContext())->getPointerTo(0) &&
+              FT->getParamType(2)->isIntegerTy();
 
           bool isGccStdStringStdString =
               Callee->getName().find("__is_charIT_EE7__value") !=
diff --git a/instrumentation/compare-transform-pass.so.cc b/instrumentation/compare-transform-pass.so.cc
index 5a5415d7..b0d6355a 100644
--- a/instrumentation/compare-transform-pass.so.cc
+++ b/instrumentation/compare-transform-pass.so.cc
@@ -271,28 +271,30 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
           isStrcmp &=
               FT->getNumParams() == 2 && FT->getReturnType()->isIntegerTy(32) &&
               FT->getParamType(0) == FT->getParamType(1) &&
-              FT->getParamType(0) == IntegerType::getInt8PtrTy(M.getContext());
+              FT->getParamType(0) ==
+                  IntegerType::getInt8Ty(M.getContext())->getPointerTo(0);
           isStrcasecmp &=
               FT->getNumParams() == 2 && FT->getReturnType()->isIntegerTy(32) &&
               FT->getParamType(0) == FT->getParamType(1) &&
-              FT->getParamType(0) == IntegerType::getInt8PtrTy(M.getContext());
+              FT->getParamType(0) ==
+                  IntegerType::getInt8Ty(M.getContext())->getPointerTo(0);
           isMemcmp &= FT->getNumParams() == 3 &&
                       FT->getReturnType()->isIntegerTy(32) &&
                       FT->getParamType(0)->isPointerTy() &&
                       FT->getParamType(1)->isPointerTy() &&
                       FT->getParamType(2)->isIntegerTy();
-          isStrncmp &= FT->getNumParams() == 3 &&
-                       FT->getReturnType()->isIntegerTy(32) &&
-                       FT->getParamType(0) == FT->getParamType(1) &&
-                       FT->getParamType(0) ==
-                           IntegerType::getInt8PtrTy(M.getContext()) &&
-                       FT->getParamType(2)->isIntegerTy();
-          isStrncasecmp &= FT->getNumParams() == 3 &&
-                           FT->getReturnType()->isIntegerTy(32) &&
-                           FT->getParamType(0) == FT->getParamType(1) &&
-                           FT->getParamType(0) ==
-                               IntegerType::getInt8PtrTy(M.getContext()) &&
-                           FT->getParamType(2)->isIntegerTy();
+          isStrncmp &=
+              FT->getNumParams() == 3 && FT->getReturnType()->isIntegerTy(32) &&
+              FT->getParamType(0) == FT->getParamType(1) &&
+              FT->getParamType(0) ==
+                  IntegerType::getInt8Ty(M.getContext())->getPointerTo(0) &&
+              FT->getParamType(2)->isIntegerTy();
+          isStrncasecmp &=
+              FT->getNumParams() == 3 && FT->getReturnType()->isIntegerTy(32) &&
+              FT->getParamType(0) == FT->getParamType(1) &&
+              FT->getParamType(0) ==
+                  IntegerType::getInt8Ty(M.getContext())->getPointerTo(0) &&
+              FT->getParamType(2)->isIntegerTy();
 
           if (!isStrcmp && !isMemcmp && !isStrncmp && !isStrcasecmp &&
               !isStrncasecmp && !isIntMemcpy)
diff --git a/nyx_mode/QEMU-Nyx b/nyx_mode/QEMU-Nyx
-Subproject 60c216bc9e4c79834716d4099993d8397a3a8fd
+Subproject 02a6f2aed360cfe76bb3d788dafe517c350d74e
diff --git a/nyx_mode/libnyx b/nyx_mode/libnyx
-Subproject 2da7f08b6e0267ccfe64e1320b24cdb29223459
+Subproject 512058a68d58b1a90a4e3971b526a955559735b
diff --git a/nyx_mode/packer b/nyx_mode/packer
-Subproject 202bace888d237e4e8f4507d0eba6791a811554
+Subproject bcf3e248b660764f48af54232a3388389a2dfc2
diff --git a/src/afl-cc.c b/src/afl-cc.c
index 6242ece0..22cce2cd 100644
--- a/src/afl-cc.c
+++ b/src/afl-cc.c
@@ -2313,7 +2313,7 @@ int main(int argc, char **argv, char **envp) {
             "0x10000\n"
             "  AFL_LLVM_DOCUMENT_IDS: write all edge IDs and the corresponding "
             "functions\n"
-            "    into this file\n"
+            "    into this file (LTO mode)\n"
             "  AFL_LLVM_LTO_DONTWRITEID: don't write the highest ID used to a "
             "global var\n"
             "  AFL_LLVM_LTO_STARTID: from which ID to start counting from for "
diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c
index 568c5274..5f67347c 100644
--- a/src/afl-fuzz-bitmap.c
+++ b/src/afl-fuzz-bitmap.c
@@ -459,6 +459,17 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
 
   if (unlikely(fault == FSRV_RUN_TMOUT && afl->afl_env.afl_ignore_timeouts)) {
 
+    if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) {
+
+      classify_counts(&afl->fsrv);
+      u64 cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
+
+      // Saturated increment
+      if (likely(afl->n_fuzz[cksum % N_FUZZ_SIZE] < 0xFFFFFFFF))
+        afl->n_fuzz[cksum % N_FUZZ_SIZE]++;
+
+    }
+
     return 0;
 
   }
diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c
index db82536d..7d6fdfb9 100644
--- a/src/afl-fuzz-state.c
+++ b/src/afl-fuzz-state.c
@@ -89,9 +89,8 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) {
   afl->w_end = 0.3;
   afl->g_max = 5000;
   afl->period_pilot_tmp = 5000.0;
-  afl->schedule = FAST;                 /* Power schedule (default: FAST)   */
+  afl->schedule = EXPLORE;              /* Power schedule (default: EXPLORE)*/
   afl->havoc_max_mult = HAVOC_MAX_MULT;
-
   afl->clear_screen = 1;                /* Window resized?                  */
   afl->havoc_div = 1;                   /* Cycle count divisor for havoc    */
   afl->stage_name = "init";             /* Name of the current fuzz stage   */
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index becad351..dd990e71 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -138,7 +138,7 @@ static void usage(u8 *argv0, int more_help) {
       "to\n"
       "                  exploit mode, and back on new coverage (default: %u)\n"
       "  -p schedule   - power schedules compute a seed's performance score:\n"
-      "                  fast(default), explore, exploit, seek, rare, mmopt, "
+      "                  explore(default), fast, exploit, seek, rare, mmopt, "
       "coe, lin\n"
       "                  quad -- see docs/FAQ.md for more information\n"
       "  -f file       - location read by the fuzzed program (default: stdin "
diff --git a/utils/aflpp_driver/aflpp_driver.c b/utils/aflpp_driver/aflpp_driver.c
index dab7fd95..9ffb2383 100644
--- a/utils/aflpp_driver/aflpp_driver.c
+++ b/utils/aflpp_driver/aflpp_driver.c
@@ -292,6 +292,7 @@ __attribute__((weak)) int main(int argc, char **argv) {
         "afl-fuzz will run N iterations before re-spawning the process "
         "(default: "
         "INT_MAX)\n"
+        "You can also use AFL_FUZZER_LOOPCOUNT to set N\n"
         "For stdin input processing, pass '-' as single command line option.\n"
         "For file input processing, pass '@@' as single command line option.\n"
         "To use with afl-cmin or afl-cmin.bash pass '-' as single command line "
@@ -379,6 +380,12 @@ __attribute__((weak)) int LLVMFuzzerRunDriver(
 
   }
 
+  if (getenv("AFL_FUZZER_LOOPCOUNT")) {
+
+    N = atoi(getenv("AFL_FUZZER_LOOPCOUNT"));
+
+  }
+
   assert(N > 0);
 
   __afl_manual_init();