[llvm] r269141 - [libFuzzer] add a driver file to use AFL on LLVMFuzzerTestOneInput

Kostya Serebryany via llvm-commits llvm-commits at lists.llvm.org
Tue May 10 16:46:51 PDT 2016


Author: kcc
Date: Tue May 10 18:46:50 2016
New Revision: 269141

URL: http://llvm.org/viewvc/llvm-project?rev=269141&view=rev
Log:
[libFuzzer] add a driver file to use AFL on LLVMFuzzerTestOneInput

Added:
    llvm/trunk/lib/Fuzzer/afl/
    llvm/trunk/lib/Fuzzer/afl/afl_driver.cpp

Added: llvm/trunk/lib/Fuzzer/afl/afl_driver.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/afl/afl_driver.cpp?rev=269141&view=auto
==============================================================================
--- llvm/trunk/lib/Fuzzer/afl/afl_driver.cpp (added)
+++ llvm/trunk/lib/Fuzzer/afl/afl_driver.cpp Tue May 10 18:46:50 2016
@@ -0,0 +1,82 @@
+/* This file allows to fuzz libFuzzer-style target functions
+ (LLVMFuzzerTestOneInput) with AFL using AFL's persistent (in-process) mode.
+
+Usage:
+################################################################################
+cat << EOF > test_fuzzer.cc
+#include <stdint.h>
+#include <stddef.h>
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  if (size > 0 && data[0] == 'H')
+    if (size > 1 && data[1] == 'I')
+       if (size > 2 && data[2] == '!')
+       __builtin_trap();
+  return 0;
+}
+EOF
+# Build your target with -fsanitize-coverage=trace-pc using fresh clang.
+clang -g -fsanitize-coverage=trace-pc test_fuzzer.cc -c
+# Build afl-llvm-rt.o.c from the AFL distribution.
+clang -c -w $AFL_HOME/llvm_mode/afl-llvm-rt.o.c
+# Build this file, link it with afl-llvm-rt.o.o and the target code.
+clang++ afl_driver.cpp test_fuzzer.o afl-llvm-rt.o.o
+# Run AFL:
+rm -rf IN OUT; mkdir IN OUT; echo z > IN/z;
+$AFL_HOME/afl-fuzz -i IN -o OUT ./a.out
+################################################################################
+*/
+#include <assert.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+// libFuzzer interface is thin, so we don't include any libFuzzer headers.
+extern "C" {
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
+__attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv);
+}
+
+// Notify AFL about persistent mode.
+static volatile char AFL_PERSISTENT[] = "##SIG_AFL_PERSISTENT##";
+extern "C" int __afl_persistent_loop(unsigned int);
+static volatile char suppress_warning2 = AFL_PERSISTENT[0];
+
+// Notify AFL about deferred forkserver.
+static volatile char AFL_DEFER_FORKSVR[] = "##SIG_AFL_DEFER_FORKSRV##";
+extern "C" void  __afl_manual_init();
+static volatile char suppress_warning1 = AFL_DEFER_FORKSVR[0];
+
+// Input buffer.
+static const size_t kMaxAflInputSize = 1 << 20;
+static uint8_t AflInputBuf[kMaxAflInputSize];
+
+int main(int argc, char **argv) {
+  fprintf(stderr, "Running in AFl-fuzz mode\nUsage:\n"
+                  "afl-fuzz [afl-flags] %s [N] "
+                  "-- run N fuzzing iterations before "
+                  "re-spawning the process (default: 1000)\n",
+          argv[0]);
+  if (LLVMFuzzerInitialize)
+    LLVMFuzzerInitialize(&argc, &argv);
+  // Do any other expensive one-time initialization here.
+
+  __afl_manual_init();
+
+  int N = 1000;
+  if (argc >= 2)
+    N = atoi(argv[1]);
+  assert(N > 0);
+  while (__afl_persistent_loop(N)) {
+    ssize_t n_read = read(0, AflInputBuf, kMaxAflInputSize);
+    if (n_read > 0) {
+      // Copy AflInputBuf into a separate buffer to let asan find buffer
+      // overflows. Don't use unique_ptr/etc to avoid extra dependencies.
+      uint8_t *copy = new uint8_t[n_read];
+      memcpy(copy, AflInputBuf, n_read);
+      LLVMFuzzerTestOneInput(copy, n_read);
+      delete[] copy;
+    }
+  }
+}




More information about the llvm-commits mailing list