aboutsummaryrefslogtreecommitdiff
path: root/utils/aflpp_driver/aflpp_driver.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/aflpp_driver/aflpp_driver.c')
-rw-r--r--utils/aflpp_driver/aflpp_driver.c132
1 files changed, 97 insertions, 35 deletions
diff --git a/utils/aflpp_driver/aflpp_driver.c b/utils/aflpp_driver/aflpp_driver.c
index 7289c845..4e8f466d 100644
--- a/utils/aflpp_driver/aflpp_driver.c
+++ b/utils/aflpp_driver/aflpp_driver.c
@@ -1,12 +1,16 @@
-//===- afl_driver.cpp - a glue between AFL++ and libFuzzer ------*- C++ -* ===//
-//===----------------------------------------------------------------------===//
+//
+// afl_driver.cpp - a glue between AFL++ and LLVMFuzzerTestOneInput harnesses
+//
-/* This file allows to fuzz libFuzzer-style target functions
+/*
+
+ This file allows to fuzz libFuzzer-style target functions
(LLVMFuzzerTestOneInput) with AFL++ using persistent in-memory fuzzing.
Usage:
-################################################################################
-cat << EOF > test_fuzzer.cc
+
+# Example target:
+$ cat << EOF > test_fuzzer.cc
#include <stddef.h>
#include <stdint.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
@@ -20,21 +24,24 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
}
EOF
-# Build your target with -fsanitize-coverage=trace-pc-guard using fresh clang.
-clang -c aflpp_driver.c
-# Build afl-compiler-rt.o.c from the AFL distribution.
-clang -c $AFL_HOME/instrumentation/afl-compiler-rt.o.c
-# Build this file, link it with afl-compiler-rt.o.o and the target code.
-afl-clang-fast -o test_fuzzer test_fuzzer.cc afl-compiler-rt.o aflpp_driver.o
+
+# Build your target with afl-cc -fsanitize=fuzzer
+$ afl-c++ -fsanitize=fuzzer -o test_fuzzer test_fuzzer.cc
# Run AFL:
-rm -rf IN OUT; mkdir IN OUT; echo z > IN/z;
-$AFL_HOME/afl-fuzz -i IN -o OUT ./a.out
-################################################################################
+$ mkdir -p in ; echo z > in/foo;
+$ afl-fuzz -i in -o out -- ./test_fuzzer
+
*/
+#ifdef __cplusplus
+extern "C" {
+
+#endif
+
#include <assert.h>
#include <errno.h>
#include <stdarg.h>
+#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -57,15 +64,26 @@ $AFL_HOME/afl-fuzz -i IN -o OUT ./a.out
#include "hash.h"
#endif
+// AFL++ shared memory fuzz cases
int __afl_sharedmem_fuzzing = 1;
-extern unsigned int * __afl_fuzz_len;
+extern unsigned int *__afl_fuzz_len;
extern unsigned char *__afl_fuzz_ptr;
-// libFuzzer interface is thin, so we don't include any libFuzzer headers.
-int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
-__attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv);
+// AFL++ coverage map
+extern unsigned char *__afl_area_ptr;
+extern unsigned int __afl_map_size;
-// Default nop ASan hooks for manual posisoning when not linking the ASan
+// libFuzzer interface is thin, so we don't include any libFuzzer headers.
+/* 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(
+ int *argc, char ***argv, int (*callback)(const uint8_t *data, size_t size));
+
+// Default nop ASan hooks for manual poisoning when not linking the ASan
// runtime
// https://github.com/google/sanitizers/wiki/AddressSanitizerManualPoisoning
__attribute__((weak)) void __asan_poison_memory_region(
@@ -187,7 +205,8 @@ static void maybe_close_fd_mask() {
// Define LLVMFuzzerMutate to avoid link failures for targets that use it
// with libFuzzer's LLVMFuzzerCustomMutator.
-size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize) {
+__attribute__((weak)) size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size,
+ size_t MaxSize) {
// assert(false && "LLVMFuzzerMutate should not be called from afl_driver");
return 0;
@@ -195,7 +214,9 @@ size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize) {
}
// Execute any files provided as parameters.
-static int ExecuteFilesOnyByOne(int argc, char **argv) {
+static int ExecuteFilesOnyByOne(int argc, char **argv,
+ int (*callback)(const uint8_t *data,
+ size_t size)) {
unsigned char *buf = (unsigned char *)malloc(MAX_FILE);
@@ -231,7 +252,7 @@ static int ExecuteFilesOnyByOne(int argc, char **argv) {
prev_length = length;
printf("Reading %zu bytes from %s\n", length, argv[i]);
- LLVMFuzzerTestOneInput(buf, length);
+ callback(buf, length);
printf("Execution successful.\n");
}
@@ -245,7 +266,18 @@ static int ExecuteFilesOnyByOne(int argc, char **argv) {
}
-int main(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(
@@ -265,6 +297,17 @@ int main(int argc, char **argv) {
"===================================================================\n",
argv[0], argv[0]);
+ return LLVMFuzzerRunDriver(&argc, &argv, LLVMFuzzerTestOneInput);
+
+}
+
+__attribute__((weak)) int LLVMFuzzerRunDriver(
+ int *argcp, char ***argvp,
+ int (*callback)(const uint8_t *data, size_t size)) {
+
+ int argc = *argcp;
+ char **argv = *argvp;
+
if (getenv("AFL_GDB")) {
char cmd[64];
@@ -275,6 +318,12 @@ int main(int argc, char **argv) {
}
+ bool in_afl = !(!getenv(SHM_FUZZ_ENV_VAR) || !getenv(SHM_ENV_VAR) ||
+ fcntl(FORKSRV_FD, F_GETFD) == -1 ||
+ fcntl(FORKSRV_FD + 1, F_GETFD) == -1);
+
+ if (!in_afl) { __afl_sharedmem_fuzzing = 0; }
+
output_file = stderr;
maybe_duplicate_stderr();
maybe_close_fd_mask();
@@ -295,27 +344,28 @@ int main(int argc, char **argv) {
int N = INT_MAX;
- if (argc == 2 && !strcmp(argv[1], "-")) {
+ if (!in_afl && argc == 2 && !strcmp(argv[1], "-")) {
- __afl_sharedmem_fuzzing = 0;
__afl_manual_init();
- return ExecuteFilesOnyByOne(argc, argv);
+ return ExecuteFilesOnyByOne(argc, argv, callback);
- } else if (argc == 2 && argv[1][0] == '-') {
+ } else if (argc == 2 && argv[1][0] == '-' && argv[1][1]) {
N = atoi(argv[1] + 1);
- } else if (argc == 2 && (N = atoi(argv[1])) > 0) {
+ } else if (argc == 2 && argv[1][0] != '-' && (N = atoi(argv[1])) > 0) {
printf("WARNING: using the deprecated call style `%s %d`\n", argv[0], N);
- } else if (argc > 1) {
-
- __afl_sharedmem_fuzzing = 0;
+ } else if (!in_afl && argc > 1 && argv[1][0] != '-') {
if (argc == 2) { __afl_manual_init(); }
- return ExecuteFilesOnyByOne(argc, argv);
+ return ExecuteFilesOnyByOne(argc, argv, callback);
+
+ } else {
+
+ N = INT_MAX;
}
@@ -325,7 +375,7 @@ int main(int argc, char **argv) {
// Call LLVMFuzzerTestOneInput here so that coverage caused by initialization
// on the first execution of LLVMFuzzerTestOneInput is ignored.
- LLVMFuzzerTestOneInput(dummy_input, 4);
+ callback(dummy_input, 4);
__asan_poison_memory_region(__afl_fuzz_ptr, MAX_FILE);
size_t prev_length = 0;
@@ -352,7 +402,13 @@ int main(int argc, char **argv) {
}
prev_length = length;
- LLVMFuzzerTestOneInput(__afl_fuzz_ptr, length);
+
+ if (unlikely(callback(__afl_fuzz_ptr, length) == -1)) {
+
+ memset(__afl_area_ptr, 0, __afl_map_size);
+ __afl_area_ptr[0] = 1;
+
+ }
}
@@ -362,7 +418,7 @@ int main(int argc, char **argv) {
while (__afl_persistent_loop(N)) {
- LLVMFuzzerTestOneInput(__afl_fuzz_ptr, *__afl_fuzz_len);
+ callback(__afl_fuzz_ptr, *__afl_fuzz_len);
}
@@ -372,3 +428,9 @@ int main(int argc, char **argv) {
}
+#ifdef __cplusplus
+
+}
+
+#endif
+