LLVM  3.7.0
FuzzerDriver.cpp
Go to the documentation of this file.
1 //===- FuzzerDriver.cpp - FuzzerDriver function and flags -----------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 // FuzzerDriver and flag parsing.
10 //===----------------------------------------------------------------------===//
11 
12 #include "FuzzerInterface.h"
13 #include "FuzzerInternal.h"
14 
15 #include <cstring>
16 #include <chrono>
17 #include <unistd.h>
18 #include <thread>
19 #include <atomic>
20 #include <mutex>
21 #include <string>
22 #include <sstream>
23 #include <algorithm>
24 #include <iterator>
25 
26 namespace fuzzer {
27 
28 // Program arguments.
30  const char *Name;
31  const char *Description;
32  int Default;
33  int *IntFlag;
34  const char **StrFlag;
35 };
36 
37 struct {
38 #define FUZZER_FLAG_INT(Name, Default, Description) int Name;
39 #define FUZZER_FLAG_STRING(Name, Description) const char *Name;
40 #include "FuzzerFlags.def"
41 #undef FUZZER_FLAG_INT
42 #undef FUZZER_FLAG_STRING
43 } Flags;
44 
45 static FlagDescription FlagDescriptions [] {
46 #define FUZZER_FLAG_INT(Name, Default, Description) \
47  { #Name, Description, Default, &Flags.Name, nullptr},
48 #define FUZZER_FLAG_STRING(Name, Description) \
49  { #Name, Description, 0, nullptr, &Flags.Name },
50 #include "FuzzerFlags.def"
51 #undef FUZZER_FLAG_INT
52 #undef FUZZER_FLAG_STRING
53 };
54 
55 static const size_t kNumFlags =
56  sizeof(FlagDescriptions) / sizeof(FlagDescriptions[0]);
57 
58 static std::vector<std::string> inputs;
59 static const char *ProgName;
60 
61 static void PrintHelp() {
62  Printf("Usage: %s [-flag1=val1 [-flag2=val2 ...] ] [dir1 [dir2 ...] ]\n",
63  ProgName);
64  Printf("\nFlags: (strictly in form -flag=value)\n");
65  size_t MaxFlagLen = 0;
66  for (size_t F = 0; F < kNumFlags; F++)
67  MaxFlagLen = std::max(strlen(FlagDescriptions[F].Name), MaxFlagLen);
68 
69  for (size_t F = 0; F < kNumFlags; F++) {
70  const auto &D = FlagDescriptions[F];
71  Printf(" %s", D.Name);
72  for (size_t i = 0, n = MaxFlagLen - strlen(D.Name); i < n; i++)
73  Printf(" ");
74  Printf("\t");
75  Printf("%d\t%s\n", D.Default, D.Description);
76  }
77  Printf("\nFlags starting with '--' will be ignored and "
78  "will be passed verbatim to subprocesses.\n");
79 }
80 
81 static const char *FlagValue(const char *Param, const char *Name) {
82  size_t Len = strlen(Name);
83  if (Param[0] == '-' && strstr(Param + 1, Name) == Param + 1 &&
84  Param[Len + 1] == '=')
85  return &Param[Len + 2];
86  return nullptr;
87 }
88 
89 static bool ParseOneFlag(const char *Param) {
90  if (Param[0] != '-') return false;
91  if (Param[1] == '-') {
92  static bool PrintedWarning = false;
93  if (!PrintedWarning) {
94  PrintedWarning = true;
95  Printf("WARNING: libFuzzer ignores flags that start with '--'\n");
96  }
97  return true;
98  }
99  for (size_t F = 0; F < kNumFlags; F++) {
100  const char *Name = FlagDescriptions[F].Name;
101  const char *Str = FlagValue(Param, Name);
102  if (Str) {
103  if (FlagDescriptions[F].IntFlag) {
104  int Val = std::stol(Str);
105  *FlagDescriptions[F].IntFlag = Val;
106  if (Flags.verbosity >= 2)
107  Printf("Flag: %s %d\n", Name, Val);;
108  return true;
109  } else if (FlagDescriptions[F].StrFlag) {
110  *FlagDescriptions[F].StrFlag = Str;
111  if (Flags.verbosity >= 2)
112  Printf("Flag: %s %s\n", Name, Str);
113  return true;
114  }
115  }
116  }
117  PrintHelp();
118  exit(1);
119 }
120 
121 // We don't use any library to minimize dependencies.
122 static void ParseFlags(int argc, char **argv) {
123  for (size_t F = 0; F < kNumFlags; F++) {
124  if (FlagDescriptions[F].IntFlag)
125  *FlagDescriptions[F].IntFlag = FlagDescriptions[F].Default;
126  if (FlagDescriptions[F].StrFlag)
127  *FlagDescriptions[F].StrFlag = nullptr;
128  }
129  for (int A = 1; A < argc; A++) {
130  if (ParseOneFlag(argv[A])) continue;
131  inputs.push_back(argv[A]);
132  }
133 }
135 static std::mutex Mu;
136 
137 static void PulseThread() {
138  while (true) {
139  std::this_thread::sleep_for(std::chrono::seconds(600));
140  std::lock_guard<std::mutex> Lock(Mu);
141  Printf("pulse...\n");
142  }
143 }
144 
145 static void WorkerThread(const std::string &Cmd, std::atomic<int> *Counter,
146  int NumJobs, std::atomic<bool> *HasErrors) {
147  while (true) {
148  int C = (*Counter)++;
149  if (C >= NumJobs) break;
150  std::string Log = "fuzz-" + std::to_string(C) + ".log";
151  std::string ToRun = Cmd + " > " + Log + " 2>&1\n";
152  if (Flags.verbosity)
153  Printf("%s", ToRun.c_str());
154  int ExitCode = system(ToRun.c_str());
155  if (ExitCode != 0)
156  *HasErrors = true;
157  std::lock_guard<std::mutex> Lock(Mu);
158  Printf("================== Job %d exited with exit code %d ============\n",
159  C, ExitCode);
161  }
162 }
163 
164 static int RunInMultipleProcesses(int argc, char **argv, int NumWorkers,
165  int NumJobs) {
166  std::atomic<int> Counter(0);
167  std::atomic<bool> HasErrors(false);
168  std::string Cmd;
169  for (int i = 0; i < argc; i++) {
170  if (FlagValue(argv[i], "jobs") || FlagValue(argv[i], "workers")) continue;
171  Cmd += argv[i];
172  Cmd += " ";
173  }
174  std::vector<std::thread> V;
175  std::thread Pulse(PulseThread);
176  Pulse.detach();
177  for (int i = 0; i < NumWorkers; i++)
178  V.push_back(std::thread(WorkerThread, Cmd, &Counter, NumJobs, &HasErrors));
179  for (auto &T : V)
180  T.join();
181  return HasErrors ? 1 : 0;
182 }
183 
184 std::vector<std::string> ReadTokensFile(const char *TokensFilePath) {
185  if (!TokensFilePath) return {};
186  std::string TokensFileContents = FileToString(TokensFilePath);
187  std::istringstream ISS(TokensFileContents);
188  std::vector<std::string> Res = {std::istream_iterator<std::string>{ISS},
189  std::istream_iterator<std::string>{}};
190  Res.push_back(" ");
191  Res.push_back("\t");
192  Res.push_back("\n");
193  return Res;
194 }
195 
196 int ApplyTokens(const Fuzzer &F, const char *InputFilePath) {
197  Unit U = FileToVector(InputFilePath);
198  auto T = F.SubstituteTokens(U);
199  T.push_back(0);
200  Printf("%s", T.data());
201  return 0;
202 }
203 
204 int FuzzerDriver(int argc, char **argv, UserCallback Callback) {
205  SimpleUserSuppliedFuzzer SUSF(Callback);
206  return FuzzerDriver(argc, argv, SUSF);
207 }
209 int FuzzerDriver(int argc, char **argv, UserSuppliedFuzzer &USF) {
210  using namespace fuzzer;
211 
212  ProgName = argv[0];
213  ParseFlags(argc, argv);
214  if (Flags.help) {
215  PrintHelp();
216  return 0;
217  }
218 
219  if (Flags.jobs > 0 && Flags.workers == 0) {
220  Flags.workers = std::min(NumberOfCpuCores() / 2, Flags.jobs);
221  if (Flags.workers > 1)
222  Printf("Running %d workers\n", Flags.workers);
223  }
224 
225  if (Flags.workers > 0 && Flags.jobs > 0)
226  return RunInMultipleProcesses(argc, argv, Flags.workers, Flags.jobs);
227 
228  Fuzzer::FuzzingOptions Options;
229  Options.Verbosity = Flags.verbosity;
230  Options.MaxLen = Flags.max_len;
231  Options.UnitTimeoutSec = Flags.timeout;
232  Options.DoCrossOver = Flags.cross_over;
233  Options.MutateDepth = Flags.mutate_depth;
234  Options.ExitOnFirst = Flags.exit_on_first;
235  Options.UseCounters = Flags.use_counters;
236  Options.UseTraces = Flags.use_traces;
237  Options.UseFullCoverageSet = Flags.use_full_coverage_set;
238  Options.PreferSmallDuringInitialShuffle =
239  Flags.prefer_small_during_initial_shuffle;
240  Options.Tokens = ReadTokensFile(Flags.tokens);
241  Options.Reload = Flags.reload;
242  if (Flags.runs >= 0)
243  Options.MaxNumberOfRuns = Flags.runs;
244  if (!inputs.empty())
245  Options.OutputCorpus = inputs[0];
246  if (Flags.sync_command)
247  Options.SyncCommand = Flags.sync_command;
248  Options.SyncTimeout = Flags.sync_timeout;
249  Fuzzer F(USF, Options);
250 
251  if (Flags.apply_tokens)
252  return ApplyTokens(F, Flags.apply_tokens);
253 
254  unsigned Seed = Flags.seed;
255  // Initialize Seed.
256  if (Seed == 0)
257  Seed = time(0) * 10000 + getpid();
258  if (Flags.verbosity)
259  Printf("Seed: %u\n", Seed);
260  srand(Seed);
261 
262  // Timer
263  if (Flags.timeout > 0)
264  SetTimer(Flags.timeout / 2 + 1);
265 
266  if (Flags.verbosity >= 2) {
267  Printf("Tokens: {");
268  for (auto &T : Options.Tokens)
269  Printf("%s,", T.c_str());
270  Printf("}\n");
271  }
272 
274  for (auto &inp : inputs)
275  if (inp != Options.OutputCorpus)
276  F.ReadDir(inp, nullptr);
277 
278  if (F.CorpusSize() == 0)
279  F.AddToCorpus(Unit()); // Can't fuzz empty corpus, so add an empty input.
281  if (Flags.save_minimized_corpus)
282  F.SaveCorpus();
283  F.Loop(Flags.iterations < 0 ? INT_MAX : Flags.iterations);
284  if (Flags.verbosity)
285  Printf("Done %d runs in %zd second(s)\n", F.getTotalNumberOfRuns(),
287 
288  return 0;
289 }
290 
291 } // namespace fuzzer
static void PrintHelp()
int FuzzerDriver(int argc, char **argv, UserCallback Callback)
Simple C-like interface with a single user-supplied callback.
void RereadOutputCorpus()
Definition: FuzzerLoop.cpp:86
size_t getTotalNumberOfRuns()
static cl::opt< unsigned long long > Seed("rng-seed", cl::value_desc("seed"), cl::desc("Seed for the random number generator"), cl::init(0))
void ReadDir(const std::string &Path, long *Epoch)
void ShuffleAndMinimize()
Definition: FuzzerLoop.cpp:114
void SetTimer(int Seconds)
Definition: FuzzerUtil.cpp:52
static const char * ProgName
Unit SubstituteTokens(const Unit &U) const
Definition: FuzzerLoop.cpp:182
void Loop(size_t NumIterations)
Definition: FuzzerLoop.cpp:305
void(* UserCallback)(const uint8_t *Data, size_t Size)
size_t secondsSinceProcessStartUp()
static sys::Mutex Lock
static Fuzzer * F
Definition: FuzzerLoop.cpp:19
std::string FileToString(const std::string &Path)
Definition: FuzzerIO.cpp:52
Number of individual test Apply this number of consecutive mutations to each input exit after the first new interesting input is found the minimized corpus is saved into the first input directory Number of jobs to run If min(jobs, NumberOfCpuCores()/2)\" is used.") FUZZER_FLAG_INT(reload
static std::mutex Mu
size_t CorpusSize() const
static std::vector< std::string > inputs
static void ParseFlags(int argc, char **argv)
std::vector< std::string > ReadTokensFile(const char *TokensFilePath)
int NumberOfCpuCores()
Definition: FuzzerUtil.cpp:64
void Printf(const char *Fmt,...)
Definition: FuzzerIO.cpp:87
static const size_t kNumFlags
* if(!EatIfPresent(lltok::kw_thread_local)) return false
ParseOptionalThreadLocal := /*empty.
void AddToCorpus(const Unit &U)
static void WorkerThread(const std::string &Cmd, std::atomic< int > *Counter, int NumJobs, std::atomic< bool > *HasErrors)
An abstract class that allows to use user-supplied mutators with libFuzzer.
void CopyFileToErr(const std::string &Path)
Definition: FuzzerIO.cpp:58
struct fuzzer::@216 Flags
static void PulseThread()
Unit FileToVector(const std::string &Path)
Definition: FuzzerIO.cpp:46
int ApplyTokens(const Fuzzer &F, const char *InputFilePath)
std::vector< uint8_t > Unit
static bool ParseOneFlag(const char *Param)
static int RunInMultipleProcesses(int argc, char **argv, int NumWorkers, int NumJobs)
static const char * FlagValue(const char *Param, const char *Name)