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 "FuzzerCorpus.h"
13#include "FuzzerInterface.h"
14#include "FuzzerInternal.h"
15#include "FuzzerIO.h"
16#include "FuzzerMutate.h"
17#include "FuzzerRandom.h"
18#include "FuzzerTracePC.h"
19#include <algorithm>
20#include <atomic>
21#include <chrono>
22#include <cstring>
23#include <mutex>
24#include <string>
25#include <thread>
26
27// This function should be present in the libFuzzer so that the client
28// binary can test for its existence.
29extern "C" __attribute__((used)) void __libfuzzer_is_present() {}
30
31namespace fuzzer {
32
33// Program arguments.
34struct FlagDescription {
35  const char *Name;
36  const char *Description;
37  int   Default;
38  int   *IntFlag;
39  const char **StrFlag;
40  unsigned int *UIntFlag;
41};
42
43struct {
44#define FUZZER_DEPRECATED_FLAG(Name)
45#define FUZZER_FLAG_INT(Name, Default, Description) int Name;
46#define FUZZER_FLAG_UNSIGNED(Name, Default, Description) unsigned int Name;
47#define FUZZER_FLAG_STRING(Name, Description) const char *Name;
48#include "FuzzerFlags.def"
49#undef FUZZER_DEPRECATED_FLAG
50#undef FUZZER_FLAG_INT
51#undef FUZZER_FLAG_UNSIGNED
52#undef FUZZER_FLAG_STRING
53} Flags;
54
55static const FlagDescription FlagDescriptions [] {
56#define FUZZER_DEPRECATED_FLAG(Name)                                           \
57  {#Name, "Deprecated; don't use", 0, nullptr, nullptr, nullptr},
58#define FUZZER_FLAG_INT(Name, Default, Description)                            \
59  {#Name, Description, Default, &Flags.Name, nullptr, nullptr},
60#define FUZZER_FLAG_UNSIGNED(Name, Default, Description)                       \
61  {#Name,   Description, static_cast<int>(Default),                            \
62   nullptr, nullptr, &Flags.Name},
63#define FUZZER_FLAG_STRING(Name, Description)                                  \
64  {#Name, Description, 0, nullptr, &Flags.Name, nullptr},
65#include "FuzzerFlags.def"
66#undef FUZZER_DEPRECATED_FLAG
67#undef FUZZER_FLAG_INT
68#undef FUZZER_FLAG_UNSIGNED
69#undef FUZZER_FLAG_STRING
70};
71
72static const size_t kNumFlags =
73    sizeof(FlagDescriptions) / sizeof(FlagDescriptions[0]);
74
75static std::vector<std::string> *Inputs;
76static std::string *ProgName;
77
78static void PrintHelp() {
79  Printf("Usage:\n");
80  auto Prog = ProgName->c_str();
81  Printf("\nTo run fuzzing pass 0 or more directories.\n");
82  Printf("%s [-flag1=val1 [-flag2=val2 ...] ] [dir1 [dir2 ...] ]\n", Prog);
83
84  Printf("\nTo run individual tests without fuzzing pass 1 or more files:\n");
85  Printf("%s [-flag1=val1 [-flag2=val2 ...] ] file1 [file2 ...]\n", Prog);
86
87  Printf("\nFlags: (strictly in form -flag=value)\n");
88  size_t MaxFlagLen = 0;
89  for (size_t F = 0; F < kNumFlags; F++)
90    MaxFlagLen = std::max(strlen(FlagDescriptions[F].Name), MaxFlagLen);
91
92  for (size_t F = 0; F < kNumFlags; F++) {
93    const auto &D = FlagDescriptions[F];
94    if (strstr(D.Description, "internal flag") == D.Description) continue;
95    Printf(" %s", D.Name);
96    for (size_t i = 0, n = MaxFlagLen - strlen(D.Name); i < n; i++)
97      Printf(" ");
98    Printf("\t");
99    Printf("%d\t%s\n", D.Default, D.Description);
100  }
101  Printf("\nFlags starting with '--' will be ignored and "
102            "will be passed verbatim to subprocesses.\n");
103}
104
105static const char *FlagValue(const char *Param, const char *Name) {
106  size_t Len = strlen(Name);
107  if (Param[0] == '-' && strstr(Param + 1, Name) == Param + 1 &&
108      Param[Len + 1] == '=')
109      return &Param[Len + 2];
110  return nullptr;
111}
112
113// Avoid calling stol as it triggers a bug in clang/glibc build.
114static long MyStol(const char *Str) {
115  long Res = 0;
116  long Sign = 1;
117  if (*Str == '-') {
118    Str++;
119    Sign = -1;
120  }
121  for (size_t i = 0; Str[i]; i++) {
122    char Ch = Str[i];
123    if (Ch < '0' || Ch > '9')
124      return Res;
125    Res = Res * 10 + (Ch - '0');
126  }
127  return Res * Sign;
128}
129
130static bool ParseOneFlag(const char *Param) {
131  if (Param[0] != '-') return false;
132  if (Param[1] == '-') {
133    static bool PrintedWarning = false;
134    if (!PrintedWarning) {
135      PrintedWarning = true;
136      Printf("INFO: libFuzzer ignores flags that start with '--'\n");
137    }
138    for (size_t F = 0; F < kNumFlags; F++)
139      if (FlagValue(Param + 1, FlagDescriptions[F].Name))
140        Printf("WARNING: did you mean '%s' (single dash)?\n", Param + 1);
141    return true;
142  }
143  for (size_t F = 0; F < kNumFlags; F++) {
144    const char *Name = FlagDescriptions[F].Name;
145    const char *Str = FlagValue(Param, Name);
146    if (Str)  {
147      if (FlagDescriptions[F].IntFlag) {
148        int Val = MyStol(Str);
149        *FlagDescriptions[F].IntFlag = Val;
150        if (Flags.verbosity >= 2)
151          Printf("Flag: %s %d\n", Name, Val);
152        return true;
153      } else if (FlagDescriptions[F].UIntFlag) {
154        unsigned int Val = std::stoul(Str);
155        *FlagDescriptions[F].UIntFlag = Val;
156        if (Flags.verbosity >= 2)
157          Printf("Flag: %s %u\n", Name, Val);
158        return true;
159      } else if (FlagDescriptions[F].StrFlag) {
160        *FlagDescriptions[F].StrFlag = Str;
161        if (Flags.verbosity >= 2)
162          Printf("Flag: %s %s\n", Name, Str);
163        return true;
164      } else {  // Deprecated flag.
165        Printf("Flag: %s: deprecated, don't use\n", Name);
166        return true;
167      }
168    }
169  }
170  Printf("\n\nWARNING: unrecognized flag '%s'; "
171         "use -help=1 to list all flags\n\n", Param);
172  return true;
173}
174
175// We don't use any library to minimize dependencies.
176static void ParseFlags(const std::vector<std::string> &Args) {
177  for (size_t F = 0; F < kNumFlags; F++) {
178    if (FlagDescriptions[F].IntFlag)
179      *FlagDescriptions[F].IntFlag = FlagDescriptions[F].Default;
180    if (FlagDescriptions[F].UIntFlag)
181      *FlagDescriptions[F].UIntFlag =
182          static_cast<unsigned int>(FlagDescriptions[F].Default);
183    if (FlagDescriptions[F].StrFlag)
184      *FlagDescriptions[F].StrFlag = nullptr;
185  }
186  Inputs = new std::vector<std::string>;
187  for (size_t A = 1; A < Args.size(); A++) {
188    if (ParseOneFlag(Args[A].c_str())) continue;
189    Inputs->push_back(Args[A]);
190  }
191}
192
193static std::mutex Mu;
194
195static void PulseThread() {
196  while (true) {
197    SleepSeconds(600);
198    std::lock_guard<std::mutex> Lock(Mu);
199    Printf("pulse...\n");
200  }
201}
202
203static void WorkerThread(const std::string &Cmd, std::atomic<unsigned> *Counter,
204                         unsigned NumJobs, std::atomic<bool> *HasErrors) {
205  while (true) {
206    unsigned C = (*Counter)++;
207    if (C >= NumJobs) break;
208    std::string Log = "fuzz-" + std::to_string(C) + ".log";
209    std::string ToRun = Cmd + " > " + Log + " 2>&1\n";
210    if (Flags.verbosity)
211      Printf("%s", ToRun.c_str());
212    int ExitCode = ExecuteCommand(ToRun);
213    if (ExitCode != 0)
214      *HasErrors = true;
215    std::lock_guard<std::mutex> Lock(Mu);
216    Printf("================== Job %u exited with exit code %d ============\n",
217           C, ExitCode);
218    fuzzer::CopyFileToErr(Log);
219  }
220}
221
222std::string CloneArgsWithoutX(const std::vector<std::string> &Args,
223                              const char *X1, const char *X2) {
224  std::string Cmd;
225  for (auto &S : Args) {
226    if (FlagValue(S.c_str(), X1) || FlagValue(S.c_str(), X2))
227      continue;
228    Cmd += S + " ";
229  }
230  return Cmd;
231}
232
233static int RunInMultipleProcesses(const std::vector<std::string> &Args,
234                                  unsigned NumWorkers, unsigned NumJobs) {
235  std::atomic<unsigned> Counter(0);
236  std::atomic<bool> HasErrors(false);
237  std::string Cmd = CloneArgsWithoutX(Args, "jobs", "workers");
238  std::vector<std::thread> V;
239  std::thread Pulse(PulseThread);
240  Pulse.detach();
241  for (unsigned i = 0; i < NumWorkers; i++)
242    V.push_back(std::thread(WorkerThread, Cmd, &Counter, NumJobs, &HasErrors));
243  for (auto &T : V)
244    T.join();
245  return HasErrors ? 1 : 0;
246}
247
248static void RssThread(Fuzzer *F, size_t RssLimitMb) {
249  while (true) {
250    SleepSeconds(1);
251    size_t Peak = GetPeakRSSMb();
252    if (Peak > RssLimitMb)
253      F->RssLimitCallback();
254  }
255}
256
257static void StartRssThread(Fuzzer *F, size_t RssLimitMb) {
258  if (!RssLimitMb) return;
259  std::thread T(RssThread, F, RssLimitMb);
260  T.detach();
261}
262
263int RunOneTest(Fuzzer *F, const char *InputFilePath, size_t MaxLen) {
264  Unit U = FileToVector(InputFilePath);
265  if (MaxLen && MaxLen < U.size())
266    U.resize(MaxLen);
267  F->RunOne(U.data(), U.size());
268  F->TryDetectingAMemoryLeak(U.data(), U.size(), true);
269  return 0;
270}
271
272static bool AllInputsAreFiles() {
273  if (Inputs->empty()) return false;
274  for (auto &Path : *Inputs)
275    if (!IsFile(Path))
276      return false;
277  return true;
278}
279
280int MinimizeCrashInput(const std::vector<std::string> &Args) {
281  if (Inputs->size() != 1) {
282    Printf("ERROR: -minimize_crash should be given one input file\n");
283    exit(1);
284  }
285  std::string InputFilePath = Inputs->at(0);
286  std::string BaseCmd =
287      CloneArgsWithoutX(Args, "minimize_crash", "exact_artifact_path");
288  auto InputPos = BaseCmd.find(" " + InputFilePath + " ");
289  assert(InputPos != std::string::npos);
290  BaseCmd.erase(InputPos, InputFilePath.size() + 1);
291  if (Flags.runs <= 0 && Flags.max_total_time == 0) {
292    Printf("INFO: you need to specify -runs=N or "
293           "-max_total_time=N with -minimize_crash=1\n"
294           "INFO: defaulting to -max_total_time=600\n");
295    BaseCmd += " -max_total_time=600";
296  }
297  // BaseCmd += " >  /dev/null 2>&1 ";
298
299  std::string CurrentFilePath = InputFilePath;
300  while (true) {
301    Unit U = FileToVector(CurrentFilePath);
302    if (U.size() < 2) {
303      Printf("CRASH_MIN: '%s' is small enough\n", CurrentFilePath.c_str());
304      return 0;
305    }
306    Printf("CRASH_MIN: minimizing crash input: '%s' (%zd bytes)\n",
307           CurrentFilePath.c_str(), U.size());
308
309    auto Cmd = BaseCmd + " " + CurrentFilePath;
310
311    Printf("CRASH_MIN: executing: %s\n", Cmd.c_str());
312    int ExitCode = ExecuteCommand(Cmd);
313    if (ExitCode == 0) {
314      Printf("ERROR: the input %s did not crash\n", CurrentFilePath.c_str());
315      exit(1);
316    }
317    Printf("CRASH_MIN: '%s' (%zd bytes) caused a crash. Will try to minimize "
318           "it further\n",
319           CurrentFilePath.c_str(), U.size());
320
321    std::string ArtifactPath = "minimized-from-" + Hash(U);
322    Cmd += " -minimize_crash_internal_step=1 -exact_artifact_path=" +
323        ArtifactPath;
324    Printf("CRASH_MIN: executing: %s\n", Cmd.c_str());
325    ExitCode = ExecuteCommand(Cmd);
326    if (ExitCode == 0) {
327      if (Flags.exact_artifact_path) {
328        CurrentFilePath = Flags.exact_artifact_path;
329        WriteToFile(U, CurrentFilePath);
330      }
331      Printf("CRASH_MIN: failed to minimize beyond %s (%d bytes), exiting\n",
332             CurrentFilePath.c_str(), U.size());
333      return 0;
334    }
335    CurrentFilePath = ArtifactPath;
336    Printf("\n\n\n\n\n\n*********************************\n");
337  }
338  return 0;
339}
340
341int MinimizeCrashInputInternalStep(Fuzzer *F, InputCorpus *Corpus) {
342  assert(Inputs->size() == 1);
343  std::string InputFilePath = Inputs->at(0);
344  Unit U = FileToVector(InputFilePath);
345  assert(U.size() > 2);
346  Printf("INFO: Starting MinimizeCrashInputInternalStep: %zd\n", U.size());
347  Corpus->AddToCorpus(U, 0);
348  F->SetMaxInputLen(U.size());
349  F->SetMaxMutationLen(U.size() - 1);
350  F->MinimizeCrashLoop(U);
351  Printf("INFO: Done MinimizeCrashInputInternalStep, no crashes found\n");
352  exit(0);
353  return 0;
354}
355
356int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
357  using namespace fuzzer;
358  assert(argc && argv && "Argument pointers cannot be nullptr");
359  EF = new ExternalFunctions();
360  if (EF->LLVMFuzzerInitialize)
361    EF->LLVMFuzzerInitialize(argc, argv);
362  const std::vector<std::string> Args(*argv, *argv + *argc);
363  assert(!Args.empty());
364  ProgName = new std::string(Args[0]);
365  ParseFlags(Args);
366  if (Flags.help) {
367    PrintHelp();
368    return 0;
369  }
370
371  if (Flags.minimize_crash)
372    return MinimizeCrashInput(Args);
373
374  if (Flags.close_fd_mask & 2)
375    DupAndCloseStderr();
376  if (Flags.close_fd_mask & 1)
377    CloseStdout();
378
379  if (Flags.jobs > 0 && Flags.workers == 0) {
380    Flags.workers = std::min(NumberOfCpuCores() / 2, Flags.jobs);
381    if (Flags.workers > 1)
382      Printf("Running %u workers\n", Flags.workers);
383  }
384
385  if (Flags.workers > 0 && Flags.jobs > 0)
386    return RunInMultipleProcesses(Args, Flags.workers, Flags.jobs);
387
388  const size_t kMaxSaneLen = 1 << 20;
389  const size_t kMinDefaultLen = 64;
390  FuzzingOptions Options;
391  Options.Verbosity = Flags.verbosity;
392  Options.MaxLen = Flags.max_len;
393  Options.UnitTimeoutSec = Flags.timeout;
394  Options.ErrorExitCode = Flags.error_exitcode;
395  Options.TimeoutExitCode = Flags.timeout_exitcode;
396  Options.MaxTotalTimeSec = Flags.max_total_time;
397  Options.DoCrossOver = Flags.cross_over;
398  Options.MutateDepth = Flags.mutate_depth;
399  Options.UseCounters = Flags.use_counters;
400  Options.UseIndirCalls = Flags.use_indir_calls;
401  Options.UseMemcmp = Flags.use_memcmp;
402  Options.UseMemmem = Flags.use_memmem;
403  Options.UseCmp = Flags.use_cmp;
404  Options.UseValueProfile = Flags.use_value_profile;
405  Options.Shrink = Flags.shrink;
406  Options.ShuffleAtStartUp = Flags.shuffle;
407  Options.PreferSmall = Flags.prefer_small;
408  Options.ReloadIntervalSec = Flags.reload;
409  Options.OnlyASCII = Flags.only_ascii;
410  Options.OutputCSV = Flags.output_csv;
411  Options.DetectLeaks = Flags.detect_leaks;
412  Options.TraceMalloc = Flags.trace_malloc;
413  Options.RssLimitMb = Flags.rss_limit_mb;
414  if (Flags.runs >= 0)
415    Options.MaxNumberOfRuns = Flags.runs;
416  if (!Inputs->empty() && !Flags.minimize_crash_internal_step)
417    Options.OutputCorpus = (*Inputs)[0];
418  Options.ReportSlowUnits = Flags.report_slow_units;
419  if (Flags.artifact_prefix)
420    Options.ArtifactPrefix = Flags.artifact_prefix;
421  if (Flags.exact_artifact_path)
422    Options.ExactArtifactPath = Flags.exact_artifact_path;
423  std::vector<Unit> Dictionary;
424  if (Flags.dict)
425    if (!ParseDictionaryFile(FileToString(Flags.dict), &Dictionary))
426      return 1;
427  if (Flags.verbosity > 0 && !Dictionary.empty())
428    Printf("Dictionary: %zd entries\n", Dictionary.size());
429  bool DoPlainRun = AllInputsAreFiles();
430  Options.SaveArtifacts =
431      !DoPlainRun || Flags.minimize_crash_internal_step;
432  Options.PrintNewCovPcs = Flags.print_pcs;
433  Options.PrintFinalStats = Flags.print_final_stats;
434  Options.PrintCorpusStats = Flags.print_corpus_stats;
435  Options.PrintCoverage = Flags.print_coverage;
436  Options.DumpCoverage = Flags.dump_coverage;
437  if (Flags.exit_on_src_pos)
438    Options.ExitOnSrcPos = Flags.exit_on_src_pos;
439  if (Flags.exit_on_item)
440    Options.ExitOnItem = Flags.exit_on_item;
441
442  unsigned Seed = Flags.seed;
443  // Initialize Seed.
444  if (Seed == 0)
445    Seed = (std::chrono::system_clock::now().time_since_epoch().count() << 10) +
446           GetPid();
447  if (Flags.verbosity)
448    Printf("INFO: Seed: %u\n", Seed);
449
450  Random Rand(Seed);
451  auto *MD = new MutationDispatcher(Rand, Options);
452  auto *Corpus = new InputCorpus(Options.OutputCorpus);
453  auto *F = new Fuzzer(Callback, *Corpus, *MD, Options);
454
455  for (auto &U: Dictionary)
456    if (U.size() <= Word::GetMaxSize())
457      MD->AddWordToManualDictionary(Word(U.data(), U.size()));
458
459  StartRssThread(F, Flags.rss_limit_mb);
460
461  Options.HandleAbrt = Flags.handle_abrt;
462  Options.HandleBus = Flags.handle_bus;
463  Options.HandleFpe = Flags.handle_fpe;
464  Options.HandleIll = Flags.handle_ill;
465  Options.HandleInt = Flags.handle_int;
466  Options.HandleSegv = Flags.handle_segv;
467  Options.HandleTerm = Flags.handle_term;
468  SetSignalHandler(Options);
469
470  if (Flags.minimize_crash_internal_step)
471    return MinimizeCrashInputInternalStep(F, Corpus);
472
473  if (DoPlainRun) {
474    Options.SaveArtifacts = false;
475    int Runs = std::max(1, Flags.runs);
476    Printf("%s: Running %zd inputs %d time(s) each.\n", ProgName->c_str(),
477           Inputs->size(), Runs);
478    for (auto &Path : *Inputs) {
479      auto StartTime = system_clock::now();
480      Printf("Running: %s\n", Path.c_str());
481      for (int Iter = 0; Iter < Runs; Iter++)
482        RunOneTest(F, Path.c_str(), Options.MaxLen);
483      auto StopTime = system_clock::now();
484      auto MS = duration_cast<milliseconds>(StopTime - StartTime).count();
485      Printf("Executed %s in %zd ms\n", Path.c_str(), (long)MS);
486    }
487    Printf("***\n"
488           "*** NOTE: fuzzing was not performed, you have only\n"
489           "***       executed the target code on a fixed set of inputs.\n"
490           "***\n");
491    F->PrintFinalStats();
492    exit(0);
493  }
494
495  if (Flags.merge) {
496    if (Options.MaxLen == 0)
497      F->SetMaxInputLen(kMaxSaneLen);
498    if (TPC.UsingTracePcGuard()) {
499      if (Flags.merge_control_file)
500        F->CrashResistantMergeInternalStep(Flags.merge_control_file);
501      else
502        F->CrashResistantMerge(Args, *Inputs);
503    } else {
504      F->Merge(*Inputs);
505    }
506    exit(0);
507  }
508
509  size_t TemporaryMaxLen = Options.MaxLen ? Options.MaxLen : kMaxSaneLen;
510
511  UnitVector InitialCorpus;
512  for (auto &Inp : *Inputs) {
513    Printf("Loading corpus dir: %s\n", Inp.c_str());
514    ReadDirToVectorOfUnits(Inp.c_str(), &InitialCorpus, nullptr,
515                           TemporaryMaxLen, /*ExitOnError=*/false);
516  }
517
518  if (Options.MaxLen == 0) {
519    size_t MaxLen = 0;
520    for (auto &U : InitialCorpus)
521      MaxLen = std::max(U.size(), MaxLen);
522    F->SetMaxInputLen(std::min(std::max(kMinDefaultLen, MaxLen), kMaxSaneLen));
523  }
524
525  if (InitialCorpus.empty()) {
526    InitialCorpus.push_back(Unit({'\n'}));  // Valid ASCII input.
527    if (Options.Verbosity)
528      Printf("INFO: A corpus is not provided, starting from an empty corpus\n");
529  }
530  F->ShuffleAndMinimize(&InitialCorpus);
531  InitialCorpus.clear();  // Don't need this memory any more.
532  F->Loop();
533
534  if (Flags.verbosity)
535    Printf("Done %d runs in %zd second(s)\n", F->getTotalNumberOfRuns(),
536           F->secondsSinceProcessStartUp());
537  F->PrintFinalStats();
538
539  exit(0);  // Don't let F destroy itself.
540}
541
542// Storage for global ExternalFunctions object.
543ExternalFunctions *EF = nullptr;
544
545}  // namespace fuzzer
546