about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--GNUmakefile3
-rw-r--r--GNUmakefile.llvm5
-rwxr-xr-xafl-plot4
-rw-r--r--custom_mutators/examples/custom_mutator_helpers.h342
-rw-r--r--custom_mutators/examples/custom_send.c8
-rw-r--r--custom_mutators/examples/example.c116
-rw-r--r--custom_mutators/examples/post_library_gif.so.c53
-rw-r--r--custom_mutators/examples/post_library_png.so.c24
-rw-r--r--custom_mutators/examples/simple_example.c28
-rw-r--r--docs/Changelog.md18
-rw-r--r--docs/custom_mutators.md9
-rw-r--r--docs/third_party_tools.md5
-rw-r--r--dynamic_list.txt1
-rw-r--r--include/afl-fuzz.h12
-rw-r--r--instrumentation/SanitizerCoverageLTO.so.cc2
-rw-r--r--instrumentation/SanitizerCoveragePCGUARD.so.cc2
-rw-r--r--instrumentation/afl-compiler-rt.o.c2
-rw-r--r--instrumentation/afl-llvm-pass.so.cc10
-rw-r--r--qemu_mode/QEMUAFL_VERSION2
m---------qemu_mode/qemuafl0
-rw-r--r--src/afl-fuzz-python.c49
-rw-r--r--src/afl-fuzz-queue.c14
-rw-r--r--src/afl-fuzz-run.c10
-rw-r--r--src/afl-fuzz.c7
-rwxr-xr-xtest/test-llvm.sh2
-rw-r--r--utils/aflpp_driver/aflpp_driver.c26
26 files changed, 172 insertions, 582 deletions
diff --git a/GNUmakefile b/GNUmakefile
index 208e965b..5bc3f9d5 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -388,6 +388,7 @@ help:
 	@echo NO_NYX - disable building nyx mode dependencies
 	@echo "NO_CORESIGHT - disable building coresight (arm64 only)"
 	@echo NO_UNICORN_ARM64 - disable building unicorn on arm64
+	@echo "WAFL_MODE - enable for WASM fuzzing with https://github.com/fgsect/WAFL"
 	@echo AFL_NO_X86 - if compiling on non-intel/amd platforms
 	@echo "LLVM_CONFIG - if your distro doesn't use the standard name for llvm-config (e.g., Debian)"
 	@echo "=========================================="
@@ -546,7 +547,7 @@ ifndef AFL_NO_X86
 test_build: afl-cc afl-gcc afl-as afl-showmap
 	@echo "[*] Testing the CC wrapper afl-cc and its instrumentation output..."
 	@unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_LSAN AFL_USE_ASAN AFL_USE_MSAN; ASAN_OPTIONS=detect_leaks=0 AFL_INST_RATIO=100 AFL_PATH=. ./afl-cc test-instr.c $(LDFLAGS) -o test-instr 2>&1 || (echo "Oops, afl-cc failed"; exit 1 )
-	- ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -o .test-instr0 ./test-instr < /dev/null
+	-ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -q -m none -o .test-instr0 ./test-instr < /dev/null
 	-echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
 	@rm -f test-instr
 	@cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation of afl-cc does not seem to be behaving correctly!"; echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue."; echo; exit 1; fi
diff --git a/GNUmakefile.llvm b/GNUmakefile.llvm
index 09e9b5be..a053403b 100644
--- a/GNUmakefile.llvm
+++ b/GNUmakefile.llvm
@@ -294,6 +294,11 @@ endif
 CLANG_CPPFL  = `$(LLVM_CONFIG) --cxxflags` -fno-rtti -fPIC $(CXXFLAGS) -Wno-deprecated-declarations
 CLANG_LFL    = `$(LLVM_CONFIG) --ldflags` $(LDFLAGS)
 
+# wasm fuzzing: disable thread-local storage and unset LLVM debug flag
+ifdef WAFL_MODE
+  $(info Compiling libraries for use with WAVM)
+  CLANG_CPPFL += -DNDEBUG -DNO_TLS
+endif
 
 # User teor2345 reports that this is required to make things work on MacOS X.
 ifeq "$(SYS)" "Darwin"
diff --git a/afl-plot b/afl-plot
index 90a46d24..230d3bfe 100755
--- a/afl-plot
+++ b/afl-plot
@@ -287,9 +287,9 @@ $PLOT_EG
 
 _EOF_
 
-) | gnuplot
+) | gnuplot || echo "Note: if you see errors concerning 'unknown or ambiguous terminal type' then you need to use a gnuplot that has png support compiled in."
 
-echo "[?] You can also use -g flag to view the plots in an GUI window, and interact with the plots (if you have built afl-plot-ui). Run \"afl-plot-h\" to know more."
+echo "[?] You can also use -g flag to view the plots in an GUI window, and interact with the plots (if you have built afl-plot-ui). Run \"afl-plot -h\" to know more."
 
 fi
 
diff --git a/custom_mutators/examples/custom_mutator_helpers.h b/custom_mutators/examples/custom_mutator_helpers.h
deleted file mode 100644
index 62e6efba..00000000
--- a/custom_mutators/examples/custom_mutator_helpers.h
+++ /dev/null
@@ -1,342 +0,0 @@
-#ifndef CUSTOM_MUTATOR_HELPERS
-#define CUSTOM_MUTATOR_HELPERS
-
-#include "config.h"
-#include "types.h"
-#include <stdlib.h>
-
-#define INITIAL_GROWTH_SIZE (64)
-
-#define RAND_BELOW(limit) (rand() % (limit))
-
-/* Use in a struct: creates a name_buf and a name_size variable. */
-#define BUF_VAR(type, name) \
-  type * name##_buf;        \
-  size_t name##_size;
-/* this fills in `&structptr->something_buf, &structptr->something_size`. */
-#define BUF_PARAMS(struct, name) \
-  (void **)&struct->name##_buf, &struct->name##_size
-
-typedef struct {
-
-} afl_t;
-
-static void surgical_havoc_mutate(u8 *out_buf, s32 begin, s32 end) {
-
-  static s8  interesting_8[] = {INTERESTING_8};
-  static s16 interesting_16[] = {INTERESTING_8, INTERESTING_16};
-  static s32 interesting_32[] = {INTERESTING_8, INTERESTING_16, INTERESTING_32};
-
-  switch (RAND_BELOW(12)) {
-
-    case 0: {
-
-      /* Flip a single bit somewhere. Spooky! */
-
-      s32 bit_idx = ((RAND_BELOW(end - begin) + begin) << 3) + RAND_BELOW(8);
-
-      out_buf[bit_idx >> 3] ^= 128 >> (bit_idx & 7);
-
-      break;
-
-    }
-
-    case 1: {
-
-      /* Set byte to interesting value. */
-
-      u8 val = interesting_8[RAND_BELOW(sizeof(interesting_8))];
-      out_buf[(RAND_BELOW(end - begin) + begin)] = val;
-
-      break;
-
-    }
-
-    case 2: {
-
-      /* Set word to interesting value, randomly choosing endian. */
-
-      if (end - begin < 2) break;
-
-      s32 byte_idx = (RAND_BELOW(end - begin) + begin);
-
-      if (byte_idx >= end - 1) break;
-
-      switch (RAND_BELOW(2)) {
-
-        case 0:
-          *(u16 *)(out_buf + byte_idx) =
-              interesting_16[RAND_BELOW(sizeof(interesting_16) >> 1)];
-          break;
-        case 1:
-          *(u16 *)(out_buf + byte_idx) =
-              SWAP16(interesting_16[RAND_BELOW(sizeof(interesting_16) >> 1)]);
-          break;
-
-      }
-
-      break;
-
-    }
-
-    case 3: {
-
-      /* Set dword to interesting value, randomly choosing endian. */
-
-      if (end - begin < 4) break;
-
-      s32 byte_idx = (RAND_BELOW(end - begin) + begin);
-
-      if (byte_idx >= end - 3) break;
-
-      switch (RAND_BELOW(2)) {
-
-        case 0:
-          *(u32 *)(out_buf + byte_idx) =
-              interesting_32[RAND_BELOW(sizeof(interesting_32) >> 2)];
-          break;
-        case 1:
-          *(u32 *)(out_buf + byte_idx) =
-              SWAP32(interesting_32[RAND_BELOW(sizeof(interesting_32) >> 2)]);
-          break;
-
-      }
-
-      break;
-
-    }
-
-    case 4: {
-
-      /* Set qword to interesting value, randomly choosing endian. */
-
-      if (end - begin < 8) break;
-
-      s32 byte_idx = (RAND_BELOW(end - begin) + begin);
-
-      if (byte_idx >= end - 7) break;
-
-      switch (RAND_BELOW(2)) {
-
-        case 0:
-          *(u64 *)(out_buf + byte_idx) =
-              (s64)interesting_32[RAND_BELOW(sizeof(interesting_32) >> 2)];
-          break;
-        case 1:
-          *(u64 *)(out_buf + byte_idx) = SWAP64(
-              (s64)interesting_32[RAND_BELOW(sizeof(interesting_32) >> 2)]);
-          break;
-
-      }
-
-      break;
-
-    }
-
-    case 5: {
-
-      /* Randomly subtract from byte. */
-
-      out_buf[(RAND_BELOW(end - begin) + begin)] -= 1 + RAND_BELOW(ARITH_MAX);
-
-      break;
-
-    }
-
-    case 6: {
-
-      /* Randomly add to byte. */
-
-      out_buf[(RAND_BELOW(end - begin) + begin)] += 1 + RAND_BELOW(ARITH_MAX);
-
-      break;
-
-    }
-
-    case 7: {
-
-      /* Randomly subtract from word, random endian. */
-
-      if (end - begin < 2) break;
-
-      s32 byte_idx = (RAND_BELOW(end - begin) + begin);
-
-      if (byte_idx >= end - 1) break;
-
-      if (RAND_BELOW(2)) {
-
-        *(u16 *)(out_buf + byte_idx) -= 1 + RAND_BELOW(ARITH_MAX);
-
-      } else {
-
-        u16 num = 1 + RAND_BELOW(ARITH_MAX);
-
-        *(u16 *)(out_buf + byte_idx) =
-            SWAP16(SWAP16(*(u16 *)(out_buf + byte_idx)) - num);
-
-      }
-
-      break;
-
-    }
-
-    case 8: {
-
-      /* Randomly add to word, random endian. */
-
-      if (end - begin < 2) break;
-
-      s32 byte_idx = (RAND_BELOW(end - begin) + begin);
-
-      if (byte_idx >= end - 1) break;
-
-      if (RAND_BELOW(2)) {
-
-        *(u16 *)(out_buf + byte_idx) += 1 + RAND_BELOW(ARITH_MAX);
-
-      } else {
-
-        u16 num = 1 + RAND_BELOW(ARITH_MAX);
-
-        *(u16 *)(out_buf + byte_idx) =
-            SWAP16(SWAP16(*(u16 *)(out_buf + byte_idx)) + num);
-
-      }
-
-      break;
-
-    }
-
-    case 9: {
-
-      /* Randomly subtract from dword, random endian. */
-
-      if (end - begin < 4) break;
-
-      s32 byte_idx = (RAND_BELOW(end - begin) + begin);
-
-      if (byte_idx >= end - 3) break;
-
-      if (RAND_BELOW(2)) {
-
-        *(u32 *)(out_buf + byte_idx) -= 1 + RAND_BELOW(ARITH_MAX);
-
-      } else {
-
-        u32 num = 1 + RAND_BELOW(ARITH_MAX);
-
-        *(u32 *)(out_buf + byte_idx) =
-            SWAP32(SWAP32(*(u32 *)(out_buf + byte_idx)) - num);
-
-      }
-
-      break;
-
-    }
-
-    case 10: {
-
-      /* Randomly add to dword, random endian. */
-
-      if (end - begin < 4) break;
-
-      s32 byte_idx = (RAND_BELOW(end - begin) + begin);
-
-      if (byte_idx >= end - 3) break;
-
-      if (RAND_BELOW(2)) {
-
-        *(u32 *)(out_buf + byte_idx) += 1 + RAND_BELOW(ARITH_MAX);
-
-      } else {
-
-        u32 num = 1 + RAND_BELOW(ARITH_MAX);
-
-        *(u32 *)(out_buf + byte_idx) =
-            SWAP32(SWAP32(*(u32 *)(out_buf + byte_idx)) + num);
-
-      }
-
-      break;
-
-    }
-
-    case 11: {
-
-      /* Just set a random byte to a random value. Because,
-         why not. We use XOR with 1-255 to eliminate the
-         possibility of a no-op. */
-
-      out_buf[(RAND_BELOW(end - begin) + begin)] ^= 1 + RAND_BELOW(255);
-
-      break;
-
-    }
-
-  }
-
-}
-
-/* This function calculates the next power of 2 greater or equal its argument.
- @return The rounded up power of 2 (if no overflow) or 0 on overflow.
-*/
-static inline size_t next_pow2(size_t in) {
-
-  if (in == 0 || in > (size_t)-1)
-    return 0;                  /* avoid undefined behaviour under-/overflow */
-  size_t out = in - 1;
-  out |= out >> 1;
-  out |= out >> 2;
-  out |= out >> 4;
-  out |= out >> 8;
-  out |= out >> 16;
-  return out + 1;
-
-}
-
-/* This function makes sure *size is > size_needed after call.
- It will realloc *buf otherwise.
- *size will grow exponentially as per:
- https://blog.mozilla.org/nnethercote/2014/11/04/please-grow-your-buffers-exponentially/
- Will return NULL and free *buf if size_needed is <1 or realloc failed.
- @return For convenience, this function returns *buf.
- */
-static inline void *maybe_grow(void **buf, size_t *size, size_t size_needed) {
-
-  /* No need to realloc */
-  if (likely(size_needed && *size >= size_needed)) return *buf;
-
-  /* No initial size was set */
-  if (size_needed < INITIAL_GROWTH_SIZE) size_needed = INITIAL_GROWTH_SIZE;
-
-  /* grow exponentially */
-  size_t next_size = next_pow2(size_needed);
-
-  /* handle overflow */
-  if (!next_size) { next_size = size_needed; }
-
-  /* alloc */
-  *buf = realloc(*buf, next_size);
-  *size = *buf ? next_size : 0;
-
-  return *buf;
-
-}
-
-/* Swaps buf1 ptr and buf2 ptr, as well as their sizes */
-static inline void afl_swap_bufs(void **buf1, size_t *size1, void **buf2,
-                                 size_t *size2) {
-
-  void * scratch_buf = *buf1;
-  size_t scratch_size = *size1;
-  *buf1 = *buf2;
-  *size1 = *size2;
-  *buf2 = scratch_buf;
-  *size2 = scratch_size;
-
-}
-
-#undef INITIAL_GROWTH_SIZE
-
-#endif
-
diff --git a/custom_mutators/examples/custom_send.c b/custom_mutators/examples/custom_send.c
index 7de72819..9cc4b160 100644
--- a/custom_mutators/examples/custom_send.c
+++ b/custom_mutators/examples/custom_send.c
@@ -10,21 +10,21 @@
 //   afl-fuzz -i in -o out -- ./test-instr -f /tmp/foo
 //
 
-#include "custom_mutator_helpers.h"
-
 #include <stdio.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <fcntl.h>
 
+#include "afl-fuzz.h"
+
 typedef struct my_mutator {
 
-  afl_t *afl;
+  afl_state_t *afl;
 
 } my_mutator_t;
 
-my_mutator_t *afl_custom_init(afl_t *afl, unsigned int seed) {
+my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
 
   my_mutator_t *data = calloc(1, sizeof(my_mutator_t));
   if (!data) {
diff --git a/custom_mutators/examples/example.c b/custom_mutators/examples/example.c
index e680ec8e..42c7469c 100644
--- a/custom_mutators/examples/example.c
+++ b/custom_mutators/examples/example.c
@@ -7,7 +7,7 @@
 */
 
 // You need to use -I/path/to/AFLplusplus/include -I.
-#include "custom_mutator_helpers.h"
+#include "afl-fuzz.h"
 
 #include <stdint.h>
 #include <stdlib.h>
@@ -26,19 +26,14 @@ static const char *commands[] = {
 
 typedef struct my_mutator {
 
-  afl_t *afl;
+  afl_state_t *afl;
 
   // any additional data here!
   size_t trim_size_current;
   int    trimmming_steps;
   int    cur_step;
 
-  // Reused buffers:
-  BUF_VAR(u8, fuzz);
-  BUF_VAR(u8, data);
-  BUF_VAR(u8, havoc);
-  BUF_VAR(u8, trim);
-  BUF_VAR(u8, post_process);
+  u8 *mutated_out, *post_process_buf, *trim_buf;
 
 } my_mutator_t;
 
@@ -53,7 +48,7 @@ typedef struct my_mutator {
  *         There may be multiple instances of this mutator in one afl-fuzz run!
  *         Return NULL on error.
  */
-my_mutator_t *afl_custom_init(afl_t *afl, unsigned int seed) {
+my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
 
   srand(seed);  // needed also by surgical_havoc_mutate()
 
@@ -65,6 +60,27 @@ my_mutator_t *afl_custom_init(afl_t *afl, unsigned int seed) {
 
   }
 
+  if ((data->mutated_out = (u8 *)malloc(MAX_FILE)) == NULL) {
+
+    perror("afl_custom_init malloc");
+    return NULL;
+
+  }
+
+  if ((data->post_process_buf = (u8 *)malloc(MAX_FILE)) == NULL) {
+
+    perror("afl_custom_init malloc");
+    return NULL;
+
+  }
+
+  if ((data->trim_buf = (u8 *)malloc(MAX_FILE)) == NULL) {
+
+    perror("afl_custom_init malloc");
+    return NULL;
+
+  }
+
   data->afl = afl;
 
   return data;
@@ -96,31 +112,14 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
   // the fuzzer
   size_t mutated_size = DATA_SIZE <= max_size ? DATA_SIZE : max_size;
 
-  // maybe_grow is optimized to be quick for reused buffers.
-  u8 *mutated_out = maybe_grow(BUF_PARAMS(data, fuzz), mutated_size);
-  if (!mutated_out) {
-
-    *out_buf = NULL;
-    perror("custom mutator allocation (maybe_grow)");
-    return 0;            /* afl-fuzz will very likely error out after this. */
-
-  }
+  memcpy(data->mutated_out, buf, buf_size);
 
   // Randomly select a command string to add as a header to the packet
-  memcpy(mutated_out, commands[rand() % 3], 3);
+  memcpy(data->mutated_out, commands[rand() % 3], 3);
 
-  // Mutate the payload of the packet
-  int i;
-  for (i = 0; i < 8; ++i) {
+  if (mutated_size > max_size) { mutated_size = max_size; }
 
-    // Randomly perform one of the (no len modification) havoc mutations
-    surgical_havoc_mutate(mutated_out, 3, mutated_size);
-
-  }
-
-  if (max_size > mutated_size) { mutated_size = max_size; }
-
-  *out_buf = mutated_out;
+  *out_buf = data->mutated_out;
   return mutated_size;
 
 }
@@ -144,24 +143,16 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
 size_t afl_custom_post_process(my_mutator_t *data, uint8_t *buf,
                                size_t buf_size, uint8_t **out_buf) {
 
-  uint8_t *post_process_buf =
-      maybe_grow(BUF_PARAMS(data, post_process), buf_size + 5);
-  if (!post_process_buf) {
+  if (buf_size + 5 > MAX_FILE) { buf_size = MAX_FILE - 5; }
 
-    perror("custom mutator realloc failed.");
-    *out_buf = NULL;
-    return 0;
+  memcpy(data->post_process_buf + 5, buf, buf_size);
+  data->post_process_buf[0] = 'A';
+  data->post_process_buf[1] = 'F';
+  data->post_process_buf[2] = 'L';
+  data->post_process_buf[3] = '+';
+  data->post_process_buf[4] = '+';
 
-  }
-
-  memcpy(post_process_buf + 5, buf, buf_size);
-  post_process_buf[0] = 'A';
-  post_process_buf[1] = 'F';
-  post_process_buf[2] = 'L';
-  post_process_buf[3] = '+';
-  post_process_buf[4] = '+';
-
-  *out_buf = post_process_buf;
+  *out_buf = data->post_process_buf;
 
   return buf_size + 5;
 
@@ -197,13 +188,6 @@ int32_t afl_custom_init_trim(my_mutator_t *data, uint8_t *buf,
 
   data->cur_step = 0;
 
-  if (!maybe_grow(BUF_PARAMS(data, trim), buf_size)) {
-
-    perror("init_trim grow");
-    return -1;
-
-  }
-
   memcpy(data->trim_buf, buf, buf_size);
 
   data->trim_size_current = buf_size;
@@ -284,27 +268,11 @@ int32_t afl_custom_post_trim(my_mutator_t *data, int success) {
 size_t afl_custom_havoc_mutation(my_mutator_t *data, u8 *buf, size_t buf_size,
                                  u8 **out_buf, size_t max_size) {
 
-  if (buf_size == 0) {
-
-    *out_buf = maybe_grow(BUF_PARAMS(data, havoc), 1);
-    if (!*out_buf) {
-
-      perror("custom havoc: maybe_grow");
-      return 0;
-
-    }
+  *out_buf = buf;  // in-place mutation
 
-    **out_buf = rand() % 256;
-    buf_size = 1;
-
-  } else {
-
-    // We reuse buf here. It's legal and faster.
-    *out_buf = buf;
-
-  }
+  if (buf_size <= sizeof(size_t)) { return buf_size; }
 
-  size_t victim = rand() % buf_size;
+  size_t victim = rand() % (buf_size - sizeof(size_t));
   (*out_buf)[victim] += rand() % 10;
 
   return buf_size;
@@ -371,9 +339,7 @@ uint8_t afl_custom_queue_new_entry(my_mutator_t  *data,
 void afl_custom_deinit(my_mutator_t *data) {
 
   free(data->post_process_buf);
-  free(data->havoc_buf);
-  free(data->data_buf);
-  free(data->fuzz_buf);
+  free(data->mutated_out);
   free(data->trim_buf);
   free(data);
 
diff --git a/custom_mutators/examples/post_library_gif.so.c b/custom_mutators/examples/post_library_gif.so.c
index 3cb018a6..6737c627 100644
--- a/custom_mutators/examples/post_library_gif.so.c
+++ b/custom_mutators/examples/post_library_gif.so.c
@@ -45,9 +45,8 @@
    1) If you don't want to modify the test case, simply set `*out_buf = in_buf`
       and return the original `len`.
 
-   NOTE: the following is currently NOT true, we abort in this case!
    2) If you want to skip this test case altogether and have AFL generate a
-      new one, return 0 or set `*out_buf = NULL`.
+      new one, return 0.
       Use this sparingly - it's faster than running the target program
       with patently useless inputs, but still wastes CPU time.
 
@@ -59,8 +58,6 @@
       Note that the buffer will *not* be freed for you. To avoid memory leaks,
       you need to free it or reuse it on subsequent calls (as shown below).
 
-      *** Feel free to reuse the original 'in_buf' BUFFER and return it. ***
-
     Alright. The example below shows a simple postprocessor that tries to make
     sure that all input files start with "GIF89a".
 
@@ -72,7 +69,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include "alloc-inl.h"
+#include "afl-fuzz.h"
 
 /* Header that must be present at the beginning of every test case: */
 
@@ -80,8 +77,7 @@
 
 typedef struct post_state {
 
-  unsigned char *buf;
-  size_t         size;
+  size_t size;
 
 } post_state_t;
 
@@ -95,15 +91,6 @@ void *afl_custom_init(void *afl) {
 
   }
 
-  state->buf = calloc(sizeof(unsigned char), 4096);
-  if (!state->buf) {
-
-    free(state);
-    perror("calloc");
-    return NULL;
-
-  }
-
   return state;
 
 }
@@ -113,6 +100,10 @@ void *afl_custom_init(void *afl) {
 size_t afl_custom_post_process(post_state_t *data, unsigned char *in_buf,
                                unsigned int len, unsigned char **out_buf) {
 
+  /* we do in-place modification as we do not increase the size */
+
+  *out_buf = in_buf;
+
   /* Skip execution altogether for buffers shorter than 6 bytes (just to
      show how it's done). We can trust len to be sane. */
 
@@ -120,34 +111,7 @@ size_t afl_custom_post_process(post_state_t *data, unsigned char *in_buf,
 
   /* Do nothing for buffers that already start with the expected header. */
 
-  if (!memcmp(in_buf, HEADER, strlen(HEADER))) {
-
-    *out_buf = in_buf;
-    return len;
-
-  }
-
-  /* Allocate memory for new buffer, reusing previous allocation if
-     possible. Note we have to use afl-fuzz's own realloc!
-     We use afl_realloc because it is effective.
-     You can also work within in_buf, and assign it to *out_buf. */
-
-  *out_buf = afl_realloc(out_buf, len);
-
-  /* If we're out of memory, the most graceful thing to do is to return the
-     original buffer and give up on modifying it. Let AFL handle OOM on its
-     own later on. */
-
-  if (!*out_buf) {
-
-    *out_buf = in_buf;
-    return len;
-
-  }
-
-  if (len > strlen(HEADER))
-    memcpy(*out_buf + strlen(HEADER), in_buf + strlen(HEADER),
-           len - strlen(HEADER));
+  if (!memcmp(in_buf, HEADER, strlen(HEADER))) { return len; }
 
   /* Insert the new header. */
 
@@ -162,7 +126,6 @@ size_t afl_custom_post_process(post_state_t *data, unsigned char *in_buf,
 /* Gets called afterwards */
 void afl_custom_deinit(post_state_t *data) {
 
-  free(data->buf);
   free(data);
 
 }
diff --git a/custom_mutators/examples/post_library_png.so.c b/custom_mutators/examples/post_library_png.so.c
index cd65b1bc..652da497 100644
--- a/custom_mutators/examples/post_library_png.so.c
+++ b/custom_mutators/examples/post_library_png.so.c
@@ -30,7 +30,7 @@
 #include <string.h>
 #include <zlib.h>
 #include <arpa/inet.h>
-#include "alloc-inl.h"
+#include "afl-fuzz.h"
 
 /* A macro to round an integer up to 4 kB. */
 
@@ -53,7 +53,7 @@ void *afl_custom_init(void *afl) {
 
   }
 
-  state->buf = calloc(sizeof(unsigned char), 4096);
+  state->buf = calloc(sizeof(unsigned char), MAX_FILE);
   if (!state->buf) {
 
     free(state);
@@ -80,21 +80,7 @@ size_t afl_custom_post_process(post_state_t *data, const unsigned char *in_buf,
 
   }
 
-  /* This is not a good way to do it, if you do not need to grow the buffer
-     then just work with in_buf instead for speed reasons.
-     But we want to show how to grow a buffer, so this is how it's done: */
-
-  unsigned int   pos = 8;
-  unsigned char *new_buf = afl_realloc(out_buf, UP4K(len));
-
-  if (!new_buf) {
-
-    *out_buf = in_buf;
-    return len;
-
-  }
-
-  memcpy(new_buf, in_buf, len);
+  unsigned int pos = 8;
 
   /* Minimum size of a zero-length PNG chunk is 12 bytes; if we
      don't have that, we can bail out. */
@@ -124,7 +110,7 @@ size_t afl_custom_post_process(post_state_t *data, const unsigned char *in_buf,
 
     if (real_cksum != file_cksum) {
 
-      *(uint32_t *)(new_buf + pos + 8 + chunk_len) = real_cksum;
+      *(uint32_t *)(data->buf + pos + 8 + chunk_len) = real_cksum;
 
     }
 
@@ -134,7 +120,7 @@ size_t afl_custom_post_process(post_state_t *data, const unsigned char *in_buf,
 
   }
 
-  *out_buf = new_buf;
+  *out_buf = data->buf;
   return len;
 
 }
diff --git a/custom_mutators/examples/simple_example.c b/custom_mutators/examples/simple_example.c
index d888ec1f..2c0abe29 100644
--- a/custom_mutators/examples/simple_example.c
+++ b/custom_mutators/examples/simple_example.c
@@ -1,6 +1,6 @@
 // This simple example just creates random buffer <= 100 filled with 'A'
 // needs -I /path/to/AFLplusplus/include
-#include "custom_mutator_helpers.h"
+#include "afl-fuzz.h"
 
 #include <stdint.h>
 #include <stdlib.h>
@@ -13,14 +13,14 @@
 
 typedef struct my_mutator {
 
-  afl_t *afl;
+  afl_state_t *afl;
 
   // Reused buffers:
-  BUF_VAR(u8, fuzz);
+  u8 *fuzz_buf;
 
 } my_mutator_t;
 
-my_mutator_t *afl_custom_init(afl_t *afl, unsigned int seed) {
+my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
 
   srand(seed);
   my_mutator_t *data = calloc(1, sizeof(my_mutator_t));
@@ -31,6 +31,14 @@ my_mutator_t *afl_custom_init(afl_t *afl, unsigned int seed) {
 
   }
 
+  data->fuzz_buf = (u8 *)malloc(MAX_FILE);
+  if (!data->fuzz_buf) {
+
+    perror("afl_custom_init malloc");
+    return NULL;
+
+  }
+
   data->afl = afl;
 
   return data;
@@ -44,18 +52,10 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
 
   int size = (rand() % 100) + 1;
   if (size > max_size) size = max_size;
-  u8 *mutated_out = maybe_grow(BUF_PARAMS(data, fuzz), size);
-  if (!mutated_out) {
-
-    *out_buf = NULL;
-    perror("custom mutator allocation (maybe_grow)");
-    return 0;            /* afl-fuzz will very likely error out after this. */
-
-  }
 
-  memset(mutated_out, _FIXED_CHAR, size);
+  memset(data->fuzz_buf, _FIXED_CHAR, size);
 
-  *out_buf = mutated_out;
+  *out_buf = data->fuzz_buf;
   return size;
 
 }
diff --git a/docs/Changelog.md b/docs/Changelog.md
index 736deb30..3337feb9 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -7,25 +7,31 @@
   - afl-fuzz:
     - ensure temporary file descriptor is closed when not used
     - added `AFL_NO_WARN_INSTABILITY`
-    - added `AFL_FRIDA_STATS_INTERVAL`
     - added time_wo_finds to fuzzer_stats
     - fixed a crash in pizza (1st april easter egg) mode. Sorry for
       everyone who was affected!
     - allow pizza mode to be disabled when AFL_PIZZA_MODE is set to -1
-    - add -z switch to prefer new coverage findings in seed selection
+    - option `-p mmopt` now also selects new queue items more often
+    - fix bug in post_process custom mutator implementation
     - print name of custom mutator in UI
+    - slight changes that improve fuzzer performance
   - afl-cc:
     - add CFI sanitizer variant to gcc targets
     - llvm 16 + 17 support (thanks to @devnexen!)
     - support llvm 15 native pcguard changes
     - support for LLVMFuzzerTestOneInput -1 return
+    - LTO autoken and llvm_mode: added AFL_LLVM_DICT2FILE_NO_MAIN support
   - qemu_mode:
     - fix _RANGES envs to allow hyphens in the filenames
-  - new custom module: autotoken, grammar free fuzzer for text inputs
-  - LTO autoken and llvm_mode: added AFL_LLVM_DICT2FILE_NO_MAIN support
+    - basic riscv support
+  - frida_mode:
+    - added `AFL_FRIDA_STATS_INTERVAL`
+    - fix issue on MacOS
+  - unicorn_mode:
+    - updated and minor issues fixed
+  - new custom module: autotoken, a grammar free fuzzer for text inputs
+  - fixed custom mutator C examples
   - better sanitizer default options support for all tools
-  - unicorn_mode: updated and minor issues fixed
-  - frida_mode: fix issue on MacOS
   - more minor fixes and cross-platform support
 
 ### Version ++4.05c (release)
diff --git a/docs/custom_mutators.md b/docs/custom_mutators.md
index 82131c92..a1de479e 100644
--- a/docs/custom_mutators.md
+++ b/docs/custom_mutators.md
@@ -118,7 +118,7 @@ def deinit():  # optional for Python
 
 ### Custom Mutation
 
-- `init`:
+- `init` (optional in Python):
 
     This method is called when AFL++ starts up and is used to seed RNG and set
     up buffers and state.
@@ -184,6 +184,11 @@ def deinit():  # optional for Python
     to the target, e.g. if it is too short, too corrupted, etc. If so,
     return a NULL buffer and zero length (or a 0 length string in Python).
 
+    NOTE: Do not make any random changes to the data in this function!
+
+    PERFORMANCE for C/C++: If possible make the changes in-place (so modify
+    the `*data` directly, and return it as `*outbuf = data`.
+
 - `fuzz_send` (optional):
 
     This method can be used if you want to send data to the target yourself,
@@ -202,7 +207,7 @@ def deinit():  # optional for Python
     discovered if compiled with INTROSPECTION. The custom mutator can then
     return a string (const char *) that reports the exact mutations used.
 
-- `deinit`:
+- `deinit` (optional in Python):
 
     The last method to be called, deinitializing the state.
 
diff --git a/docs/third_party_tools.md b/docs/third_party_tools.md
index 97f2c362..02a40ce5 100644
--- a/docs/third_party_tools.md
+++ b/docs/third_party_tools.md
@@ -1,5 +1,10 @@
 # Tools that help fuzzing with AFL++
 
+## AFL++ and other development languages
+
+* [afl-rs](https://github.com/rust-fuzz/afl.rs) - AFL++ for RUST
+* [WASM](https://github.com/fgsect/WAFL) - AFL++ for WASM
+
 ## Speeding up fuzzing
 
 * [libfiowrapper](https://github.com/marekzmyslowski/libfiowrapper) - if the
diff --git a/dynamic_list.txt b/dynamic_list.txt
index d06eae4e..50c0c6b8 100644
--- a/dynamic_list.txt
+++ b/dynamic_list.txt
@@ -54,4 +54,5 @@
   "__sanitizer_cov_trace_pc_guard";
   "__sanitizer_cov_trace_pc_guard_init";
   "__sanitizer_cov_trace_switch";
+  "LLVMFuzzerTestOneInput";
 };
diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h
index 7ff3315b..8b6502b4 100644
--- a/include/afl-fuzz.h
+++ b/include/afl-fuzz.h
@@ -501,8 +501,7 @@ typedef struct afl_state {
       custom_splice_optout,             /* Custom mutator no splice buffer  */
       is_main_node,                     /* if this is the main node         */
       is_secondary_node,                /* if this is a secondary instance  */
-      pizza_is_served,                  /* pizza mode                       */
-      prefer_new;                       /* prefer new queue entries         */
+      pizza_is_served;                  /* pizza mode                       */
 
   u32 stats_update_freq;                /* Stats update frequency (execs)   */
 
@@ -886,14 +885,19 @@ struct custom_mutator {
    * A post-processing function to use right before AFL writes the test case to
    * disk in order to execute the target.
    *
-   * (Optional) If this functionality is not needed, simply don't define this
+   * NOTE: Do not do any random changes to the data in this function!
+   *
+   * PERFORMANCE: If you can modify the data in-place you will have a better
+   *              performance. Modify *data and set `*out_buf = data`.
+   *
+   * (Optional) If this functionality is not needed, simply do not define this
    * function.
    *
    * @param[in] data pointer returned in afl_custom_init by this custom mutator
    * @param[in] buf Buffer containing the test case to be executed
    * @param[in] buf_size Size of the test case
    * @param[out] out_buf Pointer to the buffer storing the test case after
-   *     processing. External library should allocate memory for out_buf.
+   *     processing. The external library should allocate memory for out_buf.
    *     It can chose to alter buf in-place, if the space is large enough.
    * @return Size of the output buffer.
    */
diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc
index 5603c455..e41f19b6 100644
--- a/instrumentation/SanitizerCoverageLTO.so.cc
+++ b/instrumentation/SanitizerCoverageLTO.so.cc
@@ -18,7 +18,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallVector.h"
 #if LLVM_VERSION_MAJOR < 17
-#include "llvm/ADT/Triple.h"
+  #include "llvm/ADT/Triple.h"
 #endif
 #include "llvm/Analysis/EHPersonalities.h"
 #include "llvm/Analysis/PostDominators.h"
diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc
index 5f23698b..85b1ddd5 100644
--- a/instrumentation/SanitizerCoveragePCGUARD.so.cc
+++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc
@@ -14,7 +14,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallVector.h"
 #if LLVM_VERSION_MAJOR < 17
-#include "llvm/ADT/Triple.h"
+  #include "llvm/ADT/Triple.h"
 #endif
 #include "llvm/Analysis/EHPersonalities.h"
 #include "llvm/Analysis/PostDominators.h"
diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c
index 26fc7256..e0e40983 100644
--- a/instrumentation/afl-compiler-rt.o.c
+++ b/instrumentation/afl-compiler-rt.o.c
@@ -113,7 +113,7 @@ int        __afl_selective_coverage __attribute__((weak));
 int        __afl_selective_coverage_start_off __attribute__((weak));
 static int __afl_selective_coverage_temp = 1;
 
-#if defined(__ANDROID__) || defined(__HAIKU__)
+#if defined(__ANDROID__) || defined(__HAIKU__) || defined(NO_TLS)
 PREV_LOC_T __afl_prev_loc[NGRAM_SIZE_MAX];
 PREV_LOC_T __afl_prev_caller[CTX_MAX_K];
 u32        __afl_prev_ctx;
diff --git a/instrumentation/afl-llvm-pass.so.cc b/instrumentation/afl-llvm-pass.so.cc
index e8d0b1e5..c59324fd 100644
--- a/instrumentation/afl-llvm-pass.so.cc
+++ b/instrumentation/afl-llvm-pass.so.cc
@@ -413,7 +413,7 @@ bool AFLCoverage::runOnModule(Module &M) {
   GlobalVariable *AFLContext = NULL;
 
   if (ctx_str || caller_str)
-#if defined(__ANDROID__) || defined(__HAIKU__)
+#if defined(__ANDROID__) || defined(__HAIKU__) || defined(NO_TLS)
     AFLContext = new GlobalVariable(
         M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_ctx");
 #else
@@ -424,7 +424,7 @@ bool AFLCoverage::runOnModule(Module &M) {
 
 #ifdef AFL_HAVE_VECTOR_INTRINSICS
   if (ngram_size)
-  #if defined(__ANDROID__) || defined(__HAIKU__)
+  #if defined(__ANDROID__) || defined(__HAIKU__) || defined(NO_TLS)
     AFLPrevLoc = new GlobalVariable(
         M, PrevLocTy, /* isConstant */ false, GlobalValue::ExternalLinkage,
         /* Initializer */ nullptr, "__afl_prev_loc");
@@ -437,7 +437,7 @@ bool AFLCoverage::runOnModule(Module &M) {
   #endif
   else
 #endif
-#if defined(__ANDROID__) || defined(__HAIKU__)
+#if defined(__ANDROID__) || defined(__HAIKU__) || defined(NO_TLS)
     AFLPrevLoc = new GlobalVariable(
         M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc");
 #else
@@ -448,7 +448,7 @@ bool AFLCoverage::runOnModule(Module &M) {
 
 #ifdef AFL_HAVE_VECTOR_INTRINSICS
   if (ctx_k)
-  #if defined(__ANDROID__) || defined(__HAIKU__)
+  #if defined(__ANDROID__) || defined(__HAIKU__) || defined(NO_TLS)
     AFLPrevCaller = new GlobalVariable(
         M, PrevCallerTy, /* isConstant */ false, GlobalValue::ExternalLinkage,
         /* Initializer */ nullptr, "__afl_prev_caller");
@@ -461,7 +461,7 @@ bool AFLCoverage::runOnModule(Module &M) {
   #endif
   else
 #endif
-#if defined(__ANDROID__) || defined(__HAIKU__)
+#if defined(__ANDROID__) || defined(__HAIKU__) || defined(NO_TLS)
     AFLPrevCaller =
         new GlobalVariable(M, Int32Ty, false, GlobalValue::ExternalLinkage, 0,
                            "__afl_prev_caller");
diff --git a/qemu_mode/QEMUAFL_VERSION b/qemu_mode/QEMUAFL_VERSION
index 43dc832b..fa44d173 100644
--- a/qemu_mode/QEMUAFL_VERSION
+++ b/qemu_mode/QEMUAFL_VERSION
@@ -1 +1 @@
-249bf0c872
+0569eff8a1
diff --git a/qemu_mode/qemuafl b/qemu_mode/qemuafl
-Subproject 249bf0c8723671a1eebe400a9631d9e69306ff4
+Subproject 0569eff8a12dec73642b96757f6b5b51a618a03
diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c
index 673e5a6c..7dad0770 100644
--- a/src/afl-fuzz-python.c
+++ b/src/afl-fuzz-python.c
@@ -219,11 +219,14 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
 
   if (py_module != NULL) {
 
-    u8 py_notrim = 0, py_idx;
-    /* init, required */
+    u8 py_notrim = 0;
     py_functions[PY_FUNC_INIT] = PyObject_GetAttrString(py_module, "init");
-    if (!py_functions[PY_FUNC_INIT])
-      FATAL("init function not found in python module");
+    if (!py_functions[PY_FUNC_INIT]) {
+
+      WARNF("init function not found in python module");
+
+    }
+
     py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "fuzz");
     if (!py_functions[PY_FUNC_FUZZ])
       py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "mutate");
@@ -231,12 +234,6 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
         PyObject_GetAttrString(py_module, "describe");
     py_functions[PY_FUNC_FUZZ_COUNT] =
         PyObject_GetAttrString(py_module, "fuzz_count");
-    if (!py_functions[PY_FUNC_FUZZ]) {
-
-      WARNF("fuzz function not found in python module");
-
-    }
-
     py_functions[PY_FUNC_POST_PROCESS] =
         PyObject_GetAttrString(py_module, "post_process");
     py_functions[PY_FUNC_INIT_TRIM] =
@@ -263,36 +260,6 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
     if (!py_functions[PY_FUNC_DEINIT])
       WARNF("deinit function not found in python module");
 
-    for (py_idx = 0; py_idx < PY_FUNC_COUNT; ++py_idx) {
-
-      if (!py_functions[py_idx] || !PyCallable_Check(py_functions[py_idx])) {
-
-        if (py_idx >= PY_FUNC_INIT_TRIM && py_idx <= PY_FUNC_TRIM) {
-
-          // Implementing the trim API is optional for now
-          if (PyErr_Occurred()) { PyErr_Print(); }
-          py_notrim = 1;
-
-        } else if (py_idx >= PY_OPTIONAL) {
-
-          // Only _init and _deinit are not optional currently
-
-          if (PyErr_Occurred()) { PyErr_Print(); }
-
-        } else {
-
-          fprintf(stderr,
-                  "Cannot find/call function with index %d in external "
-                  "Python module.\n",
-                  py_idx);
-          return NULL;
-
-        }
-
-      }
-
-    }
-
     if (py_notrim) {
 
       py_functions[PY_FUNC_INIT_TRIM] = NULL;
@@ -345,6 +312,8 @@ static void init_py(afl_state_t *afl, py_mutator_t *py_mutator,
 
   (void)afl;
 
+  if (py_mutator->py_functions[PY_FUNC_INIT] == NULL) { return; }
+
   PyObject *py_args, *py_value;
 
   /* Provide the init function a seed for the Python RNG */
diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c
index 6fc3c743..8ad7cd97 100644
--- a/src/afl-fuzz-queue.c
+++ b/src/afl-fuzz-queue.c
@@ -149,21 +149,15 @@ void create_alias_table(afl_state_t *afl) {
 
     }
 
-    if (unlikely(afl->prefer_new) && afl->queued_discovered) {
+    if (unlikely(afl->schedule == MMOPT) && afl->queued_discovered) {
 
-      double avg_weight = sum / active;
+      u32 cnt = afl->queued_discovered >= 5 ? 5 : afl->queued_discovered;
 
-      for (i = n - afl->queued_discovered; i < n; i++) {
+      for (i = n - cnt; i < n; i++) {
 
         struct queue_entry *q = afl->queue_buf[i];
 
-        if (likely(!q->disabled) && q->weight > avg_weight) {
-
-          double prev_weight = q->weight;
-          q->weight *= (2.0 * (i / n));
-          sum += (q->weight - prev_weight);
-
-        }
+        if (likely(!q->disabled)) { q->weight *= 2.0; }
 
       }
 
diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c
index f5425011..4d56f3a7 100644
--- a/src/afl-fuzz-run.c
+++ b/src/afl-fuzz-run.c
@@ -133,7 +133,15 @@ write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) {
 
     }
 
-    if (new_mem != *mem) { *mem = new_mem; }
+    if (new_mem != *mem && new_mem != NULL && new_size > 0) {
+
+      u8 *new_buf = afl_realloc(AFL_BUF_PARAM(out_scratch), new_size);
+      if (unlikely(!new_buf)) { PFATAL("alloc"); }
+      *mem = new_buf;
+      memcpy(*mem, new_mem, new_size);
+      afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch));
+
+    }
 
     if (unlikely(afl->custom_mutators_count)) {
 
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index 0e380f73..f6628851 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -132,7 +132,6 @@ static void usage(u8 *argv0, int more_help) {
       "                  fast(default), explore, exploit, seek, rare, mmopt, "
       "coe, lin\n"
       "                  quad -- see docs/FAQ.md for more information\n"
-      "  -z            - prefer new coverage findings when fuzzing\n"
       "  -f file       - location read by the fuzzed program (default: stdin "
       "or @@)\n"
       "  -t msec       - timeout for each run (auto-scaled, default %u ms). "
@@ -493,7 +492,7 @@ int main(int argc, char **argv_orig, char **envp) {
   while (
       (opt = getopt(
            argc, argv,
-           "+Ab:B:c:CdDe:E:hi:I:f:F:g:G:l:L:m:M:nNOo:p:RQs:S:t:T:UV:WXx:YzZ")) >
+           "+Ab:B:c:CdDe:E:hi:I:f:F:g:G:l:L:m:M:nNOo:p:RQs:S:t:T:UV:WXx:YZ")) >
       0) {
 
     switch (opt) {
@@ -506,10 +505,6 @@ int main(int argc, char **argv_orig, char **envp) {
         afl->max_length = atoi(optarg);
         break;
 
-      case 'z':
-        afl->prefer_new = 1;
-        break;
-
       case 'Z':
         afl->old_seed_selection = 1;
         break;
diff --git a/test/test-llvm.sh b/test/test-llvm.sh
index 68649c23..0e66cc97 100755
--- a/test/test-llvm.sh
+++ b/test/test-llvm.sh
@@ -265,7 +265,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
       echo 00000000000000000000000000000000 > in/in
       AFL_BENCH_UNTIL_CRASH=1 ../afl-fuzz -m none -V15 -i in -o out -c./test-cmplog -- ./test-c >>errors 2>&1
     } >>errors 2>&1
-    test -n "$( ls out/default/crashes/id:000000* out/default/hangs/id:000000* 2>/dev/null )" & {
+    test -n "$( ls out/default/crashes/id:000000* out/default/hangs/id:000000* 2>/dev/null )" && {
       $ECHO "$GREEN[+] afl-fuzz is working correctly with llvm_mode cmplog"
     } || {
       echo CUT------------------------------------------------------------------CUT
diff --git a/utils/aflpp_driver/aflpp_driver.c b/utils/aflpp_driver/aflpp_driver.c
index ec304c8c..34294809 100644
--- a/utils/aflpp_driver/aflpp_driver.c
+++ b/utils/aflpp_driver/aflpp_driver.c
@@ -33,6 +33,11 @@ $ afl-fuzz -i in -o out -- ./test_fuzzer
 
 */
 
+#ifdef __cplusplus
+extern "C" {
+
+#endif
+
 #include <assert.h>
 #include <errno.h>
 #include <stdarg.h>
@@ -69,7 +74,10 @@ extern unsigned char *__afl_area_ptr;
 extern unsigned int   __afl_map_size;
 
 // libFuzzer interface is thin, so we don't include any libFuzzer headers.
-__attribute__((weak)) int LLVMFuzzerTestOneInput(const uint8_t *Data,
+/* Using the weak attributed on LLVMFuzzerTestOneInput() breaks oss-fuzz but
+   on the other hand this is what Google needs to make LLVMFuzzerRunDriver()
+   work. Choose your poison Google! */
+/*__attribute__((weak))*/ int LLVMFuzzerTestOneInput(const uint8_t *Data,
                                                  size_t         Size);
 __attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv);
 __attribute__((weak)) int LLVMFuzzerRunDriver(
@@ -260,6 +268,16 @@ static int ExecuteFilesOnyByOne(int argc, char **argv,
 
 __attribute__((weak)) int main(int argc, char **argv) {
 
+// Enable if LLVMFuzzerTestOneInput() has the weak attribute
+/*
+  if (!LLVMFuzzerTestOneInput) {
+
+    fprintf(stderr, "Error: function LLVMFuzzerTestOneInput() not found!\n");
+    abort();
+
+  }
+*/
+
   if (argc < 2 || strncmp(argv[1], "-h", 2) == 0)
     printf(
         "============================== INFO ================================\n"
@@ -409,3 +427,9 @@ __attribute__((weak)) int LLVMFuzzerRunDriver(
 
 }
 
+#ifdef __cplusplus
+
+}
+
+#endif
+