1de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//===- afl_driver.cpp - a glue between AFL and libFuzzer --------*- C++ -* ===//
2de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//
3de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//                     The LLVM Compiler Infrastructure
4de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//
5de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// This file is distributed under the University of Illinois Open Source
6de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// License. See LICENSE.TXT for details.
7de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//===----------------------------------------------------------------------===//
8de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
9de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar/* This file allows to fuzz libFuzzer-style target functions
10de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar (LLVMFuzzerTestOneInput) with AFL using AFL's persistent (in-process) mode.
11de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
12de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarUsage:
13de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar################################################################################
14de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarcat << EOF > test_fuzzer.cc
15de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include <stdint.h>
16de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include <stddef.h>
17de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarextern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
18de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  if (size > 0 && data[0] == 'H')
19de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    if (size > 1 && data[1] == 'I')
20de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar       if (size > 2 && data[2] == '!')
21de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar       __builtin_trap();
22de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  return 0;
23de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar}
24de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarEOF
25de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar# Build your target with -fsanitize-coverage=trace-pc using fresh clang.
26de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarclang -g -fsanitize-coverage=trace-pc test_fuzzer.cc -c
27de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar# Build afl-llvm-rt.o.c from the AFL distribution.
28de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarclang -c -w $AFL_HOME/llvm_mode/afl-llvm-rt.o.c
29de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar# Build this file, link it with afl-llvm-rt.o.o and the target code.
30de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarclang++ afl_driver.cpp test_fuzzer.o afl-llvm-rt.o.o
31de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar# Run AFL:
32de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarrm -rf IN OUT; mkdir IN OUT; echo z > IN/z;
33de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar$AFL_HOME/afl-fuzz -i IN -o OUT ./a.out
34de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar################################################################################
35de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarEnvironment Variables:
36de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarThere are a few environment variables that can be set to use features that
37de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarafl-fuzz doesn't have.
38de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
39de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarAFL_DRIVER_STDERR_DUPLICATE_FILENAME: Setting this *appends* stderr to the file
40de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarspecified. If the file does not exist, it is created. This is useful for getting
41de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstack traces (when using ASAN for example) or original error messages on hard to
42de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarreproduce bugs.
43de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
44de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarAFL_DRIVER_EXTRA_STATS_FILENAME: Setting this causes afl_driver to write extra
45de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatistics to the file specified. Currently these are peak_rss_mb
46de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar(the peak amount of virtual memory used in MB) and slowest_unit_time_secs. If
47de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarthe file does not exist it is created. If the file does exist then
48de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarafl_driver assumes it was restarted by afl-fuzz and will try to read old
49de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatistics from the file. If that fails then the process will quit.
50de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
51de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar*/
52de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include <assert.h>
53de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include <stdio.h>
54de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include <stdint.h>
55de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include <stdlib.h>
56de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include <string.h>
57de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include <unistd.h>
58de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include <errno.h>
59de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include <signal.h>
60de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include <sys/resource.h>
61de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include <sys/time.h>
62de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// Platform detection. Copied from FuzzerInternal.h
63de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#ifdef __linux__
64de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#define LIBFUZZER_LINUX 1
65de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#define LIBFUZZER_APPLE 0
66de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#elif __APPLE__
67de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#define LIBFUZZER_LINUX 0
68de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#define LIBFUZZER_APPLE 1
69de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#else
70de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#error "Support for your platform has not been implemented"
71de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#endif
72de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
73de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// Used to avoid repeating error checking boilerplate. If cond is false, a
74de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// fatal error has occured in the program. In this event print error_message
75de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// to stderr and abort(). Otherwise do nothing. Note that setting
76de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// AFL_DRIVER_STDERR_DUPLICATE_FILENAME may cause error_message to be appended
77de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// to the file as well, if the error occurs after the duplication is performed.
78de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#define CHECK_ERROR(cond, error_message)                                       \
79de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  if (!(cond)) {                                                               \
80de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    fprintf(stderr, (error_message));                                          \
81de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    abort();                                                                   \
82de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  }
83de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
84de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// libFuzzer interface is thin, so we don't include any libFuzzer headers.
85de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarextern "C" {
86de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarint LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
87de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar__attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv);
88de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar}
89de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
90de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// Notify AFL about persistent mode.
91de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic volatile char AFL_PERSISTENT[] = "##SIG_AFL_PERSISTENT##";
92de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarextern "C" int __afl_persistent_loop(unsigned int);
93de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic volatile char suppress_warning2 = AFL_PERSISTENT[0];
94de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
95de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// Notify AFL about deferred forkserver.
96de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic volatile char AFL_DEFER_FORKSVR[] = "##SIG_AFL_DEFER_FORKSRV##";
97de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarextern "C" void  __afl_manual_init();
98de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic volatile char suppress_warning1 = AFL_DEFER_FORKSVR[0];
99de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
100de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// Input buffer.
101de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic const size_t kMaxAflInputSize = 1 << 20;
102de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic uint8_t AflInputBuf[kMaxAflInputSize];
103de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
104de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// Variables we need for writing to the extra stats file.
105de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic FILE *extra_stats_file = NULL;
106de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic uint32_t previous_peak_rss = 0;
107de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic time_t slowest_unit_time_secs = 0;
108de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic const int kNumExtraStats = 2;
109de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic const char *kExtraStatsFormatString = "peak_rss_mb            : %u\n"
110de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                                             "slowest_unit_time_sec  : %u\n";
111de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
112de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// Copied from FuzzerUtil.cpp.
113de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarsize_t GetPeakRSSMb() {
114de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  struct rusage usage;
115de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  if (getrusage(RUSAGE_SELF, &usage))
116de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    return 0;
117de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  if (LIBFUZZER_LINUX) {
118de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    // ru_maxrss is in KiB
119de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    return usage.ru_maxrss >> 10;
120de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  } else if (LIBFUZZER_APPLE) {
121de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    // ru_maxrss is in bytes
122de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    return usage.ru_maxrss >> 20;
123de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  }
124de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  assert(0 && "GetPeakRSSMb() is not implemented for your platform");
125de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  return 0;
126de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar}
127de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
128de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// Based on SetSigaction in FuzzerUtil.cpp
129de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic void SetSigaction(int signum,
130de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                         void (*callback)(int, siginfo_t *, void *)) {
131de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  struct sigaction sigact;
132de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  memset(&sigact, 0, sizeof(sigact));
133de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  sigact.sa_sigaction = callback;
134de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  if (sigaction(signum, &sigact, 0)) {
135de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    fprintf(stderr, "libFuzzer: sigaction failed with %d\n", errno);
136de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    exit(1);
137de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  }
138de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar}
139de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
140de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// Write extra stats to the file specified by the user. If none is specified
141de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// this function will never be called.
142de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic void write_extra_stats() {
143de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  uint32_t peak_rss = GetPeakRSSMb();
144de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
145de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  if (peak_rss < previous_peak_rss)
146de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    peak_rss = previous_peak_rss;
147de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
148de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  int chars_printed = fprintf(extra_stats_file, kExtraStatsFormatString,
149de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                              peak_rss, slowest_unit_time_secs);
150de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
151de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  CHECK_ERROR(chars_printed != 0, "Failed to write extra_stats_file");
152de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
153de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  CHECK_ERROR(fclose(extra_stats_file) == 0,
154de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar              "Failed to close extra_stats_file");
155de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar}
156de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
157de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// Call write_extra_stats before we exit.
158de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic void crash_handler(int, siginfo_t *, void *) {
159de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // Make sure we don't try calling write_extra_stats again if we crashed while
160de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // trying to call it.
161de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  static bool first_crash = true;
162de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  CHECK_ERROR(first_crash,
163de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar              "Crashed in crash signal handler. This is a bug in the fuzzer.");
164de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
165de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  first_crash = false;
166de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  write_extra_stats();
167de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar}
168de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
169de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// If the user has specified an extra_stats_file through the environment
170de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// variable AFL_DRIVER_EXTRA_STATS_FILENAME, then perform necessary set up
171de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// to write stats to it on exit. If no file is specified, do nothing. Otherwise
172de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// install signal and exit handlers to write to the file when the process exits.
173de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// Then if the file doesn't exist create it and set extra stats to 0. But if it
174de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// does exist then read the initial values of the extra stats from the file
175de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// and check that the file is writable.
176de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic void maybe_initialize_extra_stats() {
177de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // If AFL_DRIVER_EXTRA_STATS_FILENAME isn't set then we have nothing to do.
178de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  char *extra_stats_filename = getenv("AFL_DRIVER_EXTRA_STATS_FILENAME");
179de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  if (!extra_stats_filename)
180de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    return;
181de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
182de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // Open the file and find the previous peak_rss_mb value.
183de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // This is necessary because the fuzzing process is restarted after N
184de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // iterations are completed. So we may need to get this value from a previous
185de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // process to be accurate.
186de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  extra_stats_file = fopen(extra_stats_filename, "r");
187de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
188de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // If extra_stats_file already exists: read old stats from it.
189de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  if (extra_stats_file) {
190de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    int matches = fscanf(extra_stats_file, kExtraStatsFormatString,
191de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                         &previous_peak_rss, &slowest_unit_time_secs);
192de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
193de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    // Make sure we have read a real extra stats file and that we have used it
194de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    // to set slowest_unit_time_secs and previous_peak_rss.
195de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    CHECK_ERROR(matches == kNumExtraStats, "Extra stats file is corrupt");
196de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
197de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    CHECK_ERROR(fclose(extra_stats_file) == 0, "Failed to close file");
198de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
199de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    // Now open the file for writing.
200de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    extra_stats_file = fopen(extra_stats_filename, "w");
201de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    CHECK_ERROR(extra_stats_file,
202de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                "Failed to open extra stats file for writing");
203de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  } else {
204de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    // Looks like this is the first time in a fuzzing job this is being called.
205de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    extra_stats_file = fopen(extra_stats_filename, "w+");
206de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    CHECK_ERROR(extra_stats_file, "failed to create extra stats file");
207de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  }
208de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
209de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // Make sure that crash_handler gets called on any kind of fatal error.
210de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  int crash_signals[] = {SIGSEGV, SIGBUS, SIGABRT, SIGILL, SIGFPE,  SIGINT,
211de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                         SIGTERM};
212de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
213de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  const size_t num_signals = sizeof(crash_signals) / sizeof(crash_signals[0]);
214de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
215de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  for (size_t idx = 0; idx < num_signals; idx++)
216de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    SetSigaction(crash_signals[idx], crash_handler);
217de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
218de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // Make sure it gets called on other kinds of exits.
219de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  atexit(write_extra_stats);
220de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar}
221de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
222de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// If the user asks us to duplicate stderr, then do it.
223de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic void maybe_duplicate_stderr() {
224de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  char* stderr_duplicate_filename =
225de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      getenv("AFL_DRIVER_STDERR_DUPLICATE_FILENAME");
226de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
227de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  if (!stderr_duplicate_filename)
228de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    return;
229de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
230de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  FILE* stderr_duplicate_stream =
231de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      freopen(stderr_duplicate_filename, "a+", stderr);
232de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
233de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  if (!stderr_duplicate_stream) {
234de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    fprintf(
235de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar        stderr,
236de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar        "Failed to duplicate stderr to AFL_DRIVER_STDERR_DUPLICATE_FILENAME");
237de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    abort();
238de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  }
239de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar}
240de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
241de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarint main(int argc, char **argv) {
242de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  fprintf(stderr, "Running in AFl-fuzz mode\nUsage:\n"
243de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                  "afl-fuzz [afl-flags] %s [N] "
244de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                  "-- run N fuzzing iterations before "
245de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                  "re-spawning the process (default: 1000)\n",
246de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar          argv[0]);
247de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  if (LLVMFuzzerInitialize)
248de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    LLVMFuzzerInitialize(&argc, &argv);
249de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // Do any other expensive one-time initialization here.
250de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
251de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  maybe_duplicate_stderr();
252de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  maybe_initialize_extra_stats();
253de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
254de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  __afl_manual_init();
255de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
256de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  int N = 1000;
257de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  if (argc >= 2)
258de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    N = atoi(argv[1]);
259de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  assert(N > 0);
260de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  time_t unit_time_secs;
261de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  while (__afl_persistent_loop(N)) {
262de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    ssize_t n_read = read(0, AflInputBuf, kMaxAflInputSize);
263de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    if (n_read > 0) {
264de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      // Copy AflInputBuf into a separate buffer to let asan find buffer
265de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      // overflows. Don't use unique_ptr/etc to avoid extra dependencies.
266de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      uint8_t *copy = new uint8_t[n_read];
267de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      memcpy(copy, AflInputBuf, n_read);
268de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
269de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      struct timeval unit_start_time;
270de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      CHECK_ERROR(gettimeofday(&unit_start_time, NULL) == 0,
271de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                  "Calling gettimeofday failed");
272de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
273de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      LLVMFuzzerTestOneInput(copy, n_read);
274de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
275de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      struct timeval unit_stop_time;
276de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      CHECK_ERROR(gettimeofday(&unit_stop_time, NULL) == 0,
277de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                  "Calling gettimeofday failed");
278de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
279de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      // Update slowest_unit_time_secs if we see a new max.
280de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      unit_time_secs = unit_stop_time.tv_sec - unit_start_time.tv_sec;
281de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      if (slowest_unit_time_secs < unit_time_secs)
282de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar        slowest_unit_time_secs = unit_time_secs;
283de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
284de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      delete[] copy;
285de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    }
286de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  }
287de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar}
288