1 //===- afl_driver.cpp - a glue between AFL and libFuzzer --------*- C++ -* ===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //===----------------------------------------------------------------------===//
8 /* This file allows to fuzz libFuzzer-style target functions
9 (LLVMFuzzerTestOneInput) with AFL using AFL's persistent (in-process) mode.
12 ################################################################################
13 cat << EOF > test_fuzzer.cc
16 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
17 if (size > 0 && data[0] == 'H')
18 if (size > 1 && data[1] == 'I')
19 if (size > 2 && data[2] == '!')
24 # Build your target with -fsanitize-coverage=trace-pc-guard using fresh clang.
25 clang -g -fsanitize-coverage=trace-pc-guard test_fuzzer.cc -c
26 # Build afl-llvm-rt.o.c from the AFL distribution.
27 clang -c -w $AFL_HOME/llvm_mode/afl-llvm-rt.o.c
28 # Build this file, link it with afl-llvm-rt.o.o and the target code.
29 clang++ afl_driver.cpp test_fuzzer.o afl-llvm-rt.o.o
31 rm -rf IN OUT; mkdir IN OUT; echo z > IN/z;
32 $AFL_HOME/afl-fuzz -i IN -o OUT ./a.out
33 ################################################################################
34 AFL_DRIVER_STDERR_DUPLICATE_FILENAME: Setting this *appends* stderr to the file
35 specified. If the file does not exist, it is created. This is useful for getting
36 stack traces (when using ASAN for example) or original error messages on hard
37 to reproduce bugs. Note that any content written to stderr will be written to
38 this file instead of stderr's usual location.
40 AFL_DRIVER_CLOSE_FD_MASK: Similar to libFuzzer's -close_fd_mask behavior option.
41 If 1, close stdout at startup. If 2 close stderr; if 3 close both.
57 // Platform detection. Copied from FuzzerInternal.h
59 #define LIBFUZZER_LINUX 1
60 #define LIBFUZZER_APPLE 0
61 #define LIBFUZZER_NETBSD 0
62 #define LIBFUZZER_FREEBSD 0
64 #define LIBFUZZER_LINUX 0
65 #define LIBFUZZER_APPLE 1
66 #define LIBFUZZER_NETBSD 0
67 #define LIBFUZZER_FREEBSD 0
69 #define LIBFUZZER_LINUX 0
70 #define LIBFUZZER_APPLE 0
71 #define LIBFUZZER_NETBSD 1
72 #define LIBFUZZER_FREEBSD 0
74 #define LIBFUZZER_LINUX 0
75 #define LIBFUZZER_APPLE 0
76 #define LIBFUZZER_NETBSD 0
77 #define LIBFUZZER_FREEBSD 1
79 #error "Support for your platform has not been implemented"
82 // libFuzzer interface is thin, so we don't include any libFuzzer headers.
84 int LLVMFuzzerTestOneInput(const uint8_t *Data
, size_t Size
);
85 __attribute__((weak
)) int LLVMFuzzerInitialize(int *argc
, char ***argv
);
88 // Notify AFL about persistent mode.
89 static volatile char AFL_PERSISTENT
[] = "##SIG_AFL_PERSISTENT##";
90 extern "C" int __afl_persistent_loop(unsigned int);
91 static volatile char suppress_warning2
= AFL_PERSISTENT
[0];
93 // Notify AFL about deferred forkserver.
94 static volatile char AFL_DEFER_FORKSVR
[] = "##SIG_AFL_DEFER_FORKSRV##";
95 extern "C" void __afl_manual_init();
96 static volatile char suppress_warning1
= AFL_DEFER_FORKSVR
[0];
99 static const size_t kMaxAflInputSize
= 1 << 20;
100 static uint8_t AflInputBuf
[kMaxAflInputSize
];
102 // Use this optionally defined function to output sanitizer messages even if
103 // user asks to close stderr.
104 extern "C" __attribute__((weak
)) void __sanitizer_set_report_fd(void *);
106 // Keep track of where stderr content is being written to, so that
107 // dup_and_close_stderr can use the correct one.
108 static FILE *output_file
= stderr
;
110 // Experimental feature to use afl_driver without AFL's deferred mode.
111 // Needs to run before __afl_auto_init.
112 __attribute__((constructor(0))) static void __decide_deferred_forkserver(void) {
113 if (getenv("AFL_DRIVER_DONT_DEFER")) {
114 if (unsetenv("__AFL_DEFER_FORKSRV")) {
115 perror("Failed to unset __AFL_DEFER_FORKSRV");
121 // If the user asks us to duplicate stderr, then do it.
122 static void maybe_duplicate_stderr() {
123 char *stderr_duplicate_filename
=
124 getenv("AFL_DRIVER_STDERR_DUPLICATE_FILENAME");
126 if (!stderr_duplicate_filename
)
129 FILE *stderr_duplicate_stream
=
130 freopen(stderr_duplicate_filename
, "a+", stderr
);
132 if (!stderr_duplicate_stream
) {
135 "Failed to duplicate stderr to AFL_DRIVER_STDERR_DUPLICATE_FILENAME");
138 output_file
= stderr_duplicate_stream
;
141 // Most of these I/O functions were inspired by/copied from libFuzzer's code.
142 static void discard_output(int fd
) {
143 FILE *temp
= fopen("/dev/null", "w");
146 dup2(fileno(temp
), fd
);
150 static void close_stdout() { discard_output(STDOUT_FILENO
); }
152 // Prevent the targeted code from writing to "stderr" but allow sanitizers and
153 // this driver to do so.
154 static void dup_and_close_stderr() {
155 int output_fileno
= fileno(output_file
);
156 int output_fd
= dup(output_fileno
);
159 FILE *new_output_file
= fdopen(output_fd
, "w");
160 if (!new_output_file
)
162 if (!__sanitizer_set_report_fd
)
164 __sanitizer_set_report_fd(reinterpret_cast<void *>(output_fd
));
165 discard_output(output_fileno
);
168 static void Printf(const char *Fmt
, ...) {
171 vfprintf(output_file
, Fmt
, ap
);
176 // Close stdout and/or stderr if user asks for it.
177 static void maybe_close_fd_mask() {
178 char *fd_mask_str
= getenv("AFL_DRIVER_CLOSE_FD_MASK");
181 int fd_mask
= atoi(fd_mask_str
);
183 dup_and_close_stderr();
188 // Define LLVMFuzzerMutate to avoid link failures for targets that use it
189 // with libFuzzer's LLVMFuzzerCustomMutator.
190 extern "C" size_t LLVMFuzzerMutate(uint8_t *Data
, size_t Size
, size_t MaxSize
) {
191 assert(false && "LLVMFuzzerMutate should not be called from afl_driver");
195 // Execute any files provided as parameters.
196 static int ExecuteFilesOnyByOne(int argc
, char **argv
) {
197 for (int i
= 1; i
< argc
; i
++) {
198 std::ifstream
in(argv
[i
], std::ios::binary
);
200 size_t length
= in
.tellg();
201 in
.seekg (0, in
.beg
);
202 std::cout
<< "Reading " << length
<< " bytes from " << argv
[i
] << std::endl
;
203 // Allocate exactly length bytes so that we reliably catch buffer overflows.
204 std::vector
<char> bytes(length
);
205 in
.read(bytes
.data(), bytes
.size());
207 LLVMFuzzerTestOneInput(reinterpret_cast<const uint8_t *>(bytes
.data()),
209 std::cout
<< "Execution successful" << std::endl
;
214 int main(int argc
, char **argv
) {
216 "======================= INFO =========================\n"
217 "This binary is built for AFL-fuzz.\n"
218 "To run the target function on individual input(s) execute this:\n"
221 " %s INPUT_FILE1 [INPUT_FILE2 ... ]\n"
222 "To fuzz with afl-fuzz execute this:\n"
223 " afl-fuzz [afl-flags] %s [-N]\n"
224 "afl-fuzz will run N iterations before "
225 "re-spawning the process (default: 1000)\n"
226 "======================================================\n",
227 argv
[0], argv
[0], argv
[0]);
229 maybe_duplicate_stderr();
230 maybe_close_fd_mask();
231 if (LLVMFuzzerInitialize
)
232 LLVMFuzzerInitialize(&argc
, &argv
);
233 // Do any other expensive one-time initialization here.
235 if (!getenv("AFL_DRIVER_DONT_DEFER"))
239 if (argc
== 2 && argv
[1][0] == '-')
240 N
= atoi(argv
[1] + 1);
241 else if(argc
== 2 && (N
= atoi(argv
[1])) > 0)
242 Printf("WARNING: using the deprecated call style `%s %d`\n", argv
[0], N
);
244 return ExecuteFilesOnyByOne(argc
, argv
);
248 // Call LLVMFuzzerTestOneInput here so that coverage caused by initialization
249 // on the first execution of LLVMFuzzerTestOneInput is ignored.
250 uint8_t dummy_input
[1] = {0};
251 LLVMFuzzerTestOneInput(dummy_input
, 1);
254 while (__afl_persistent_loop(N
)) {
255 ssize_t n_read
= read(0, AflInputBuf
, kMaxAflInputSize
);
257 // Copy AflInputBuf into a separate buffer to let asan find buffer
258 // overflows. Don't use unique_ptr/etc to avoid extra dependencies.
259 uint8_t *copy
= new uint8_t[n_read
];
260 memcpy(copy
, AflInputBuf
, n_read
);
262 LLVMFuzzerTestOneInput(copy
, n_read
);
266 Printf("%s: successfully executed %d input(s)\n", argv
[0], num_runs
);