xref: /openbsd-src/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerDriver.cpp (revision 810390e339a5425391477d5d41c78d7cab2424ac)
13cab2bb3Spatrick //===- FuzzerDriver.cpp - FuzzerDriver function and flags -----------------===//
23cab2bb3Spatrick //
33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information.
53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63cab2bb3Spatrick //
73cab2bb3Spatrick //===----------------------------------------------------------------------===//
83cab2bb3Spatrick // FuzzerDriver and flag parsing.
93cab2bb3Spatrick //===----------------------------------------------------------------------===//
103cab2bb3Spatrick 
113cab2bb3Spatrick #include "FuzzerCommand.h"
123cab2bb3Spatrick #include "FuzzerCorpus.h"
133cab2bb3Spatrick #include "FuzzerFork.h"
143cab2bb3Spatrick #include "FuzzerIO.h"
153cab2bb3Spatrick #include "FuzzerInterface.h"
163cab2bb3Spatrick #include "FuzzerInternal.h"
173cab2bb3Spatrick #include "FuzzerMerge.h"
183cab2bb3Spatrick #include "FuzzerMutate.h"
191f9cb04fSpatrick #include "FuzzerPlatform.h"
203cab2bb3Spatrick #include "FuzzerRandom.h"
213cab2bb3Spatrick #include "FuzzerTracePC.h"
223cab2bb3Spatrick #include <algorithm>
233cab2bb3Spatrick #include <atomic>
243cab2bb3Spatrick #include <chrono>
253cab2bb3Spatrick #include <cstdlib>
263cab2bb3Spatrick #include <cstring>
273cab2bb3Spatrick #include <mutex>
283cab2bb3Spatrick #include <string>
293cab2bb3Spatrick #include <thread>
303cab2bb3Spatrick #include <fstream>
313cab2bb3Spatrick 
323cab2bb3Spatrick // This function should be present in the libFuzzer so that the client
333cab2bb3Spatrick // binary can test for its existence.
343cab2bb3Spatrick #if LIBFUZZER_MSVC
__libfuzzer_is_present()353cab2bb3Spatrick extern "C" void __libfuzzer_is_present() {}
36d89ec533Spatrick #if defined(_M_IX86) || defined(__i386__)
37d89ec533Spatrick #pragma comment(linker, "/include:___libfuzzer_is_present")
38d89ec533Spatrick #else
393cab2bb3Spatrick #pragma comment(linker, "/include:__libfuzzer_is_present")
40d89ec533Spatrick #endif
413cab2bb3Spatrick #else
__libfuzzer_is_present()423cab2bb3Spatrick extern "C" __attribute__((used)) void __libfuzzer_is_present() {}
433cab2bb3Spatrick #endif  // LIBFUZZER_MSVC
443cab2bb3Spatrick 
453cab2bb3Spatrick namespace fuzzer {
463cab2bb3Spatrick 
473cab2bb3Spatrick // Program arguments.
483cab2bb3Spatrick struct FlagDescription {
493cab2bb3Spatrick   const char *Name;
503cab2bb3Spatrick   const char *Description;
513cab2bb3Spatrick   int   Default;
523cab2bb3Spatrick   int   *IntFlag;
533cab2bb3Spatrick   const char **StrFlag;
543cab2bb3Spatrick   unsigned int *UIntFlag;
553cab2bb3Spatrick };
563cab2bb3Spatrick 
573cab2bb3Spatrick struct {
583cab2bb3Spatrick #define FUZZER_DEPRECATED_FLAG(Name)
593cab2bb3Spatrick #define FUZZER_FLAG_INT(Name, Default, Description) int Name;
603cab2bb3Spatrick #define FUZZER_FLAG_UNSIGNED(Name, Default, Description) unsigned int Name;
613cab2bb3Spatrick #define FUZZER_FLAG_STRING(Name, Description) const char *Name;
623cab2bb3Spatrick #include "FuzzerFlags.def"
633cab2bb3Spatrick #undef FUZZER_DEPRECATED_FLAG
643cab2bb3Spatrick #undef FUZZER_FLAG_INT
653cab2bb3Spatrick #undef FUZZER_FLAG_UNSIGNED
663cab2bb3Spatrick #undef FUZZER_FLAG_STRING
673cab2bb3Spatrick } Flags;
683cab2bb3Spatrick 
693cab2bb3Spatrick static const FlagDescription FlagDescriptions [] {
703cab2bb3Spatrick #define FUZZER_DEPRECATED_FLAG(Name)                                           \
713cab2bb3Spatrick   {#Name, "Deprecated; don't use", 0, nullptr, nullptr, nullptr},
723cab2bb3Spatrick #define FUZZER_FLAG_INT(Name, Default, Description)                            \
733cab2bb3Spatrick   {#Name, Description, Default, &Flags.Name, nullptr, nullptr},
743cab2bb3Spatrick #define FUZZER_FLAG_UNSIGNED(Name, Default, Description)                       \
753cab2bb3Spatrick   {#Name,   Description, static_cast<int>(Default),                            \
763cab2bb3Spatrick    nullptr, nullptr, &Flags.Name},
773cab2bb3Spatrick #define FUZZER_FLAG_STRING(Name, Description)                                  \
783cab2bb3Spatrick   {#Name, Description, 0, nullptr, &Flags.Name, nullptr},
793cab2bb3Spatrick #include "FuzzerFlags.def"
803cab2bb3Spatrick #undef FUZZER_DEPRECATED_FLAG
813cab2bb3Spatrick #undef FUZZER_FLAG_INT
823cab2bb3Spatrick #undef FUZZER_FLAG_UNSIGNED
833cab2bb3Spatrick #undef FUZZER_FLAG_STRING
843cab2bb3Spatrick };
853cab2bb3Spatrick 
863cab2bb3Spatrick static const size_t kNumFlags =
873cab2bb3Spatrick     sizeof(FlagDescriptions) / sizeof(FlagDescriptions[0]);
883cab2bb3Spatrick 
89*810390e3Srobert static std::vector<std::string> *Inputs;
903cab2bb3Spatrick static std::string *ProgName;
913cab2bb3Spatrick 
PrintHelp()923cab2bb3Spatrick static void PrintHelp() {
933cab2bb3Spatrick   Printf("Usage:\n");
943cab2bb3Spatrick   auto Prog = ProgName->c_str();
953cab2bb3Spatrick   Printf("\nTo run fuzzing pass 0 or more directories.\n");
963cab2bb3Spatrick   Printf("%s [-flag1=val1 [-flag2=val2 ...] ] [dir1 [dir2 ...] ]\n", Prog);
973cab2bb3Spatrick 
983cab2bb3Spatrick   Printf("\nTo run individual tests without fuzzing pass 1 or more files:\n");
993cab2bb3Spatrick   Printf("%s [-flag1=val1 [-flag2=val2 ...] ] file1 [file2 ...]\n", Prog);
1003cab2bb3Spatrick 
1013cab2bb3Spatrick   Printf("\nFlags: (strictly in form -flag=value)\n");
1023cab2bb3Spatrick   size_t MaxFlagLen = 0;
1033cab2bb3Spatrick   for (size_t F = 0; F < kNumFlags; F++)
1043cab2bb3Spatrick     MaxFlagLen = std::max(strlen(FlagDescriptions[F].Name), MaxFlagLen);
1053cab2bb3Spatrick 
1063cab2bb3Spatrick   for (size_t F = 0; F < kNumFlags; F++) {
1073cab2bb3Spatrick     const auto &D = FlagDescriptions[F];
1083cab2bb3Spatrick     if (strstr(D.Description, "internal flag") == D.Description) continue;
1093cab2bb3Spatrick     Printf(" %s", D.Name);
1103cab2bb3Spatrick     for (size_t i = 0, n = MaxFlagLen - strlen(D.Name); i < n; i++)
1113cab2bb3Spatrick       Printf(" ");
1123cab2bb3Spatrick     Printf("\t");
1133cab2bb3Spatrick     Printf("%d\t%s\n", D.Default, D.Description);
1143cab2bb3Spatrick   }
1153cab2bb3Spatrick   Printf("\nFlags starting with '--' will be ignored and "
1163cab2bb3Spatrick             "will be passed verbatim to subprocesses.\n");
1173cab2bb3Spatrick }
1183cab2bb3Spatrick 
FlagValue(const char * Param,const char * Name)1193cab2bb3Spatrick static const char *FlagValue(const char *Param, const char *Name) {
1203cab2bb3Spatrick   size_t Len = strlen(Name);
1213cab2bb3Spatrick   if (Param[0] == '-' && strstr(Param + 1, Name) == Param + 1 &&
1223cab2bb3Spatrick       Param[Len + 1] == '=')
1233cab2bb3Spatrick       return &Param[Len + 2];
1243cab2bb3Spatrick   return nullptr;
1253cab2bb3Spatrick }
1263cab2bb3Spatrick 
1273cab2bb3Spatrick // Avoid calling stol as it triggers a bug in clang/glibc build.
MyStol(const char * Str)1283cab2bb3Spatrick static long MyStol(const char *Str) {
1293cab2bb3Spatrick   long Res = 0;
1303cab2bb3Spatrick   long Sign = 1;
1313cab2bb3Spatrick   if (*Str == '-') {
1323cab2bb3Spatrick     Str++;
1333cab2bb3Spatrick     Sign = -1;
1343cab2bb3Spatrick   }
1353cab2bb3Spatrick   for (size_t i = 0; Str[i]; i++) {
1363cab2bb3Spatrick     char Ch = Str[i];
1373cab2bb3Spatrick     if (Ch < '0' || Ch > '9')
1383cab2bb3Spatrick       return Res;
1393cab2bb3Spatrick     Res = Res * 10 + (Ch - '0');
1403cab2bb3Spatrick   }
1413cab2bb3Spatrick   return Res * Sign;
1423cab2bb3Spatrick }
1433cab2bb3Spatrick 
ParseOneFlag(const char * Param)1443cab2bb3Spatrick static bool ParseOneFlag(const char *Param) {
1453cab2bb3Spatrick   if (Param[0] != '-') return false;
1463cab2bb3Spatrick   if (Param[1] == '-') {
1473cab2bb3Spatrick     static bool PrintedWarning = false;
1483cab2bb3Spatrick     if (!PrintedWarning) {
1493cab2bb3Spatrick       PrintedWarning = true;
1503cab2bb3Spatrick       Printf("INFO: libFuzzer ignores flags that start with '--'\n");
1513cab2bb3Spatrick     }
1523cab2bb3Spatrick     for (size_t F = 0; F < kNumFlags; F++)
1533cab2bb3Spatrick       if (FlagValue(Param + 1, FlagDescriptions[F].Name))
1543cab2bb3Spatrick         Printf("WARNING: did you mean '%s' (single dash)?\n", Param + 1);
1553cab2bb3Spatrick     return true;
1563cab2bb3Spatrick   }
1573cab2bb3Spatrick   for (size_t F = 0; F < kNumFlags; F++) {
1583cab2bb3Spatrick     const char *Name = FlagDescriptions[F].Name;
1593cab2bb3Spatrick     const char *Str = FlagValue(Param, Name);
1603cab2bb3Spatrick     if (Str)  {
1613cab2bb3Spatrick       if (FlagDescriptions[F].IntFlag) {
162d89ec533Spatrick         auto Val = MyStol(Str);
163d89ec533Spatrick         *FlagDescriptions[F].IntFlag = static_cast<int>(Val);
1643cab2bb3Spatrick         if (Flags.verbosity >= 2)
1653cab2bb3Spatrick           Printf("Flag: %s %d\n", Name, Val);
1663cab2bb3Spatrick         return true;
1673cab2bb3Spatrick       } else if (FlagDescriptions[F].UIntFlag) {
168d89ec533Spatrick         auto Val = std::stoul(Str);
169d89ec533Spatrick         *FlagDescriptions[F].UIntFlag = static_cast<unsigned int>(Val);
1703cab2bb3Spatrick         if (Flags.verbosity >= 2)
1713cab2bb3Spatrick           Printf("Flag: %s %u\n", Name, Val);
1723cab2bb3Spatrick         return true;
1733cab2bb3Spatrick       } else if (FlagDescriptions[F].StrFlag) {
1743cab2bb3Spatrick         *FlagDescriptions[F].StrFlag = Str;
1753cab2bb3Spatrick         if (Flags.verbosity >= 2)
1763cab2bb3Spatrick           Printf("Flag: %s %s\n", Name, Str);
1773cab2bb3Spatrick         return true;
1783cab2bb3Spatrick       } else {  // Deprecated flag.
1793cab2bb3Spatrick         Printf("Flag: %s: deprecated, don't use\n", Name);
1803cab2bb3Spatrick         return true;
1813cab2bb3Spatrick       }
1823cab2bb3Spatrick     }
1833cab2bb3Spatrick   }
1843cab2bb3Spatrick   Printf("\n\nWARNING: unrecognized flag '%s'; "
1853cab2bb3Spatrick          "use -help=1 to list all flags\n\n", Param);
1863cab2bb3Spatrick   return true;
1873cab2bb3Spatrick }
1883cab2bb3Spatrick 
1893cab2bb3Spatrick // We don't use any library to minimize dependencies.
ParseFlags(const std::vector<std::string> & Args,const ExternalFunctions * EF)190*810390e3Srobert static void ParseFlags(const std::vector<std::string> &Args,
1913cab2bb3Spatrick                        const ExternalFunctions *EF) {
1923cab2bb3Spatrick   for (size_t F = 0; F < kNumFlags; F++) {
1933cab2bb3Spatrick     if (FlagDescriptions[F].IntFlag)
1943cab2bb3Spatrick       *FlagDescriptions[F].IntFlag = FlagDescriptions[F].Default;
1953cab2bb3Spatrick     if (FlagDescriptions[F].UIntFlag)
1963cab2bb3Spatrick       *FlagDescriptions[F].UIntFlag =
1973cab2bb3Spatrick           static_cast<unsigned int>(FlagDescriptions[F].Default);
1983cab2bb3Spatrick     if (FlagDescriptions[F].StrFlag)
1993cab2bb3Spatrick       *FlagDescriptions[F].StrFlag = nullptr;
2003cab2bb3Spatrick   }
2013cab2bb3Spatrick 
2023cab2bb3Spatrick   // Disable len_control by default, if LLVMFuzzerCustomMutator is used.
2031f9cb04fSpatrick   if (EF->LLVMFuzzerCustomMutator) {
2043cab2bb3Spatrick     Flags.len_control = 0;
2051f9cb04fSpatrick     Printf("INFO: found LLVMFuzzerCustomMutator (%p). "
2061f9cb04fSpatrick            "Disabling -len_control by default.\n", EF->LLVMFuzzerCustomMutator);
2071f9cb04fSpatrick   }
2083cab2bb3Spatrick 
209*810390e3Srobert   Inputs = new std::vector<std::string>;
2103cab2bb3Spatrick   for (size_t A = 1; A < Args.size(); A++) {
2113cab2bb3Spatrick     if (ParseOneFlag(Args[A].c_str())) {
2123cab2bb3Spatrick       if (Flags.ignore_remaining_args)
2133cab2bb3Spatrick         break;
2143cab2bb3Spatrick       continue;
2153cab2bb3Spatrick     }
2163cab2bb3Spatrick     Inputs->push_back(Args[A]);
2173cab2bb3Spatrick   }
2183cab2bb3Spatrick }
2193cab2bb3Spatrick 
2203cab2bb3Spatrick static std::mutex Mu;
2213cab2bb3Spatrick 
PulseThread()2223cab2bb3Spatrick static void PulseThread() {
2233cab2bb3Spatrick   while (true) {
2243cab2bb3Spatrick     SleepSeconds(600);
2253cab2bb3Spatrick     std::lock_guard<std::mutex> Lock(Mu);
2263cab2bb3Spatrick     Printf("pulse...\n");
2273cab2bb3Spatrick   }
2283cab2bb3Spatrick }
2293cab2bb3Spatrick 
WorkerThread(const Command & BaseCmd,std::atomic<unsigned> * Counter,unsigned NumJobs,std::atomic<bool> * HasErrors)2303cab2bb3Spatrick static void WorkerThread(const Command &BaseCmd, std::atomic<unsigned> *Counter,
2313cab2bb3Spatrick                          unsigned NumJobs, std::atomic<bool> *HasErrors) {
2323cab2bb3Spatrick   while (true) {
2333cab2bb3Spatrick     unsigned C = (*Counter)++;
2343cab2bb3Spatrick     if (C >= NumJobs) break;
2353cab2bb3Spatrick     std::string Log = "fuzz-" + std::to_string(C) + ".log";
2363cab2bb3Spatrick     Command Cmd(BaseCmd);
2373cab2bb3Spatrick     Cmd.setOutputFile(Log);
2383cab2bb3Spatrick     Cmd.combineOutAndErr();
2393cab2bb3Spatrick     if (Flags.verbosity) {
2403cab2bb3Spatrick       std::string CommandLine = Cmd.toString();
2413cab2bb3Spatrick       Printf("%s\n", CommandLine.c_str());
2423cab2bb3Spatrick     }
2433cab2bb3Spatrick     int ExitCode = ExecuteCommand(Cmd);
2443cab2bb3Spatrick     if (ExitCode != 0)
2453cab2bb3Spatrick       *HasErrors = true;
2463cab2bb3Spatrick     std::lock_guard<std::mutex> Lock(Mu);
2473cab2bb3Spatrick     Printf("================== Job %u exited with exit code %d ============\n",
2483cab2bb3Spatrick            C, ExitCode);
2493cab2bb3Spatrick     fuzzer::CopyFileToErr(Log);
2503cab2bb3Spatrick   }
2513cab2bb3Spatrick }
2523cab2bb3Spatrick 
ValidateDirectoryExists(const std::string & Path,bool CreateDirectory)253d89ec533Spatrick static void ValidateDirectoryExists(const std::string &Path,
254d89ec533Spatrick                                     bool CreateDirectory) {
255d89ec533Spatrick   if (Path.empty()) {
256d89ec533Spatrick     Printf("ERROR: Provided directory path is an empty string\n");
257d89ec533Spatrick     exit(1);
258d89ec533Spatrick   }
259d89ec533Spatrick 
260d89ec533Spatrick   if (IsDirectory(Path))
261d89ec533Spatrick     return;
262d89ec533Spatrick 
263d89ec533Spatrick   if (CreateDirectory) {
264d89ec533Spatrick     if (!MkDirRecursive(Path)) {
265d89ec533Spatrick       Printf("ERROR: Failed to create directory \"%s\"\n", Path.c_str());
266d89ec533Spatrick       exit(1);
267d89ec533Spatrick     }
268d89ec533Spatrick     return;
269d89ec533Spatrick   }
270d89ec533Spatrick 
271d89ec533Spatrick   Printf("ERROR: The required directory \"%s\" does not exist\n", Path.c_str());
272d89ec533Spatrick   exit(1);
273d89ec533Spatrick }
274d89ec533Spatrick 
CloneArgsWithoutX(const std::vector<std::string> & Args,const char * X1,const char * X2)275*810390e3Srobert std::string CloneArgsWithoutX(const std::vector<std::string> &Args,
2763cab2bb3Spatrick                               const char *X1, const char *X2) {
2773cab2bb3Spatrick   std::string Cmd;
2783cab2bb3Spatrick   for (auto &S : Args) {
2793cab2bb3Spatrick     if (FlagValue(S.c_str(), X1) || FlagValue(S.c_str(), X2))
2803cab2bb3Spatrick       continue;
2813cab2bb3Spatrick     Cmd += S + " ";
2823cab2bb3Spatrick   }
2833cab2bb3Spatrick   return Cmd;
2843cab2bb3Spatrick }
2853cab2bb3Spatrick 
RunInMultipleProcesses(const std::vector<std::string> & Args,unsigned NumWorkers,unsigned NumJobs)286*810390e3Srobert static int RunInMultipleProcesses(const std::vector<std::string> &Args,
2873cab2bb3Spatrick                                   unsigned NumWorkers, unsigned NumJobs) {
2883cab2bb3Spatrick   std::atomic<unsigned> Counter(0);
2893cab2bb3Spatrick   std::atomic<bool> HasErrors(false);
2903cab2bb3Spatrick   Command Cmd(Args);
2913cab2bb3Spatrick   Cmd.removeFlag("jobs");
2923cab2bb3Spatrick   Cmd.removeFlag("workers");
293*810390e3Srobert   std::vector<std::thread> V;
2943cab2bb3Spatrick   std::thread Pulse(PulseThread);
2953cab2bb3Spatrick   Pulse.detach();
2963cab2bb3Spatrick   for (unsigned i = 0; i < NumWorkers; i++)
297*810390e3Srobert     V.push_back(std::thread(WorkerThread, std::ref(Cmd), &Counter, NumJobs,
298*810390e3Srobert                             &HasErrors));
2993cab2bb3Spatrick   for (auto &T : V)
3003cab2bb3Spatrick     T.join();
3013cab2bb3Spatrick   return HasErrors ? 1 : 0;
3023cab2bb3Spatrick }
3033cab2bb3Spatrick 
RssThread(Fuzzer * F,size_t RssLimitMb)3043cab2bb3Spatrick static void RssThread(Fuzzer *F, size_t RssLimitMb) {
3053cab2bb3Spatrick   while (true) {
3063cab2bb3Spatrick     SleepSeconds(1);
3073cab2bb3Spatrick     size_t Peak = GetPeakRSSMb();
3083cab2bb3Spatrick     if (Peak > RssLimitMb)
3093cab2bb3Spatrick       F->RssLimitCallback();
3103cab2bb3Spatrick   }
3113cab2bb3Spatrick }
3123cab2bb3Spatrick 
StartRssThread(Fuzzer * F,size_t RssLimitMb)3133cab2bb3Spatrick static void StartRssThread(Fuzzer *F, size_t RssLimitMb) {
3143cab2bb3Spatrick   if (!RssLimitMb)
3153cab2bb3Spatrick     return;
3163cab2bb3Spatrick   std::thread T(RssThread, F, RssLimitMb);
3173cab2bb3Spatrick   T.detach();
3183cab2bb3Spatrick }
3193cab2bb3Spatrick 
RunOneTest(Fuzzer * F,const char * InputFilePath,size_t MaxLen)3203cab2bb3Spatrick int RunOneTest(Fuzzer *F, const char *InputFilePath, size_t MaxLen) {
3213cab2bb3Spatrick   Unit U = FileToVector(InputFilePath);
3223cab2bb3Spatrick   if (MaxLen && MaxLen < U.size())
3233cab2bb3Spatrick     U.resize(MaxLen);
3243cab2bb3Spatrick   F->ExecuteCallback(U.data(), U.size());
325d89ec533Spatrick   if (Flags.print_full_coverage) {
326d89ec533Spatrick     // Leak detection is not needed when collecting full coverage data.
327d89ec533Spatrick     F->TPCUpdateObservedPCs();
328d89ec533Spatrick   } else {
3293cab2bb3Spatrick     F->TryDetectingAMemoryLeak(U.data(), U.size(), true);
330d89ec533Spatrick   }
3313cab2bb3Spatrick   return 0;
3323cab2bb3Spatrick }
3333cab2bb3Spatrick 
AllInputsAreFiles()3343cab2bb3Spatrick static bool AllInputsAreFiles() {
3353cab2bb3Spatrick   if (Inputs->empty()) return false;
3363cab2bb3Spatrick   for (auto &Path : *Inputs)
3373cab2bb3Spatrick     if (!IsFile(Path))
3383cab2bb3Spatrick       return false;
3393cab2bb3Spatrick   return true;
3403cab2bb3Spatrick }
3413cab2bb3Spatrick 
GetDedupTokenFromCmdOutput(const std::string & S)3421f9cb04fSpatrick static std::string GetDedupTokenFromCmdOutput(const std::string &S) {
3433cab2bb3Spatrick   auto Beg = S.find("DEDUP_TOKEN:");
3443cab2bb3Spatrick   if (Beg == std::string::npos)
3453cab2bb3Spatrick     return "";
3463cab2bb3Spatrick   auto End = S.find('\n', Beg);
3473cab2bb3Spatrick   if (End == std::string::npos)
3483cab2bb3Spatrick     return "";
3493cab2bb3Spatrick   return S.substr(Beg, End - Beg);
3503cab2bb3Spatrick }
3513cab2bb3Spatrick 
CleanseCrashInput(const std::vector<std::string> & Args,const FuzzingOptions & Options)352*810390e3Srobert int CleanseCrashInput(const std::vector<std::string> &Args,
3533cab2bb3Spatrick                       const FuzzingOptions &Options) {
3543cab2bb3Spatrick   if (Inputs->size() != 1 || !Flags.exact_artifact_path) {
3553cab2bb3Spatrick     Printf("ERROR: -cleanse_crash should be given one input file and"
3563cab2bb3Spatrick           " -exact_artifact_path\n");
3573cab2bb3Spatrick     exit(1);
3583cab2bb3Spatrick   }
3593cab2bb3Spatrick   std::string InputFilePath = Inputs->at(0);
3603cab2bb3Spatrick   std::string OutputFilePath = Flags.exact_artifact_path;
3613cab2bb3Spatrick   Command Cmd(Args);
3623cab2bb3Spatrick   Cmd.removeFlag("cleanse_crash");
3633cab2bb3Spatrick 
3643cab2bb3Spatrick   assert(Cmd.hasArgument(InputFilePath));
3653cab2bb3Spatrick   Cmd.removeArgument(InputFilePath);
3663cab2bb3Spatrick 
3671f9cb04fSpatrick   auto TmpFilePath = TempPath("CleanseCrashInput", ".repro");
3683cab2bb3Spatrick   Cmd.addArgument(TmpFilePath);
3691f9cb04fSpatrick   Cmd.setOutputFile(getDevNull());
3703cab2bb3Spatrick   Cmd.combineOutAndErr();
3713cab2bb3Spatrick 
3723cab2bb3Spatrick   std::string CurrentFilePath = InputFilePath;
3733cab2bb3Spatrick   auto U = FileToVector(CurrentFilePath);
3743cab2bb3Spatrick   size_t Size = U.size();
3753cab2bb3Spatrick 
376*810390e3Srobert   const std::vector<uint8_t> ReplacementBytes = {' ', 0xff};
3773cab2bb3Spatrick   for (int NumAttempts = 0; NumAttempts < 5; NumAttempts++) {
3783cab2bb3Spatrick     bool Changed = false;
3793cab2bb3Spatrick     for (size_t Idx = 0; Idx < Size; Idx++) {
3803cab2bb3Spatrick       Printf("CLEANSE[%d]: Trying to replace byte %zd of %zd\n", NumAttempts,
3813cab2bb3Spatrick              Idx, Size);
3823cab2bb3Spatrick       uint8_t OriginalByte = U[Idx];
3833cab2bb3Spatrick       if (ReplacementBytes.end() != std::find(ReplacementBytes.begin(),
3843cab2bb3Spatrick                                               ReplacementBytes.end(),
3853cab2bb3Spatrick                                               OriginalByte))
3863cab2bb3Spatrick         continue;
3873cab2bb3Spatrick       for (auto NewByte : ReplacementBytes) {
3883cab2bb3Spatrick         U[Idx] = NewByte;
3893cab2bb3Spatrick         WriteToFile(U, TmpFilePath);
3903cab2bb3Spatrick         auto ExitCode = ExecuteCommand(Cmd);
3913cab2bb3Spatrick         RemoveFile(TmpFilePath);
3923cab2bb3Spatrick         if (!ExitCode) {
3933cab2bb3Spatrick           U[Idx] = OriginalByte;
3943cab2bb3Spatrick         } else {
3953cab2bb3Spatrick           Changed = true;
3963cab2bb3Spatrick           Printf("CLEANSE: Replaced byte %zd with 0x%x\n", Idx, NewByte);
3973cab2bb3Spatrick           WriteToFile(U, OutputFilePath);
3983cab2bb3Spatrick           break;
3993cab2bb3Spatrick         }
4003cab2bb3Spatrick       }
4013cab2bb3Spatrick     }
4023cab2bb3Spatrick     if (!Changed) break;
4033cab2bb3Spatrick   }
4043cab2bb3Spatrick   return 0;
4053cab2bb3Spatrick }
4063cab2bb3Spatrick 
MinimizeCrashInput(const std::vector<std::string> & Args,const FuzzingOptions & Options)407*810390e3Srobert int MinimizeCrashInput(const std::vector<std::string> &Args,
4083cab2bb3Spatrick                        const FuzzingOptions &Options) {
4093cab2bb3Spatrick   if (Inputs->size() != 1) {
4103cab2bb3Spatrick     Printf("ERROR: -minimize_crash should be given one input file\n");
4113cab2bb3Spatrick     exit(1);
4123cab2bb3Spatrick   }
4133cab2bb3Spatrick   std::string InputFilePath = Inputs->at(0);
4143cab2bb3Spatrick   Command BaseCmd(Args);
4153cab2bb3Spatrick   BaseCmd.removeFlag("minimize_crash");
4163cab2bb3Spatrick   BaseCmd.removeFlag("exact_artifact_path");
4173cab2bb3Spatrick   assert(BaseCmd.hasArgument(InputFilePath));
4183cab2bb3Spatrick   BaseCmd.removeArgument(InputFilePath);
4193cab2bb3Spatrick   if (Flags.runs <= 0 && Flags.max_total_time == 0) {
4203cab2bb3Spatrick     Printf("INFO: you need to specify -runs=N or "
4213cab2bb3Spatrick            "-max_total_time=N with -minimize_crash=1\n"
4223cab2bb3Spatrick            "INFO: defaulting to -max_total_time=600\n");
4233cab2bb3Spatrick     BaseCmd.addFlag("max_total_time", "600");
4243cab2bb3Spatrick   }
4253cab2bb3Spatrick 
4263cab2bb3Spatrick   BaseCmd.combineOutAndErr();
4273cab2bb3Spatrick 
4283cab2bb3Spatrick   std::string CurrentFilePath = InputFilePath;
4293cab2bb3Spatrick   while (true) {
4303cab2bb3Spatrick     Unit U = FileToVector(CurrentFilePath);
4313cab2bb3Spatrick     Printf("CRASH_MIN: minimizing crash input: '%s' (%zd bytes)\n",
4323cab2bb3Spatrick            CurrentFilePath.c_str(), U.size());
4333cab2bb3Spatrick 
4343cab2bb3Spatrick     Command Cmd(BaseCmd);
4353cab2bb3Spatrick     Cmd.addArgument(CurrentFilePath);
4363cab2bb3Spatrick 
4371f9cb04fSpatrick     Printf("CRASH_MIN: executing: %s\n", Cmd.toString().c_str());
4381f9cb04fSpatrick     std::string CmdOutput;
4391f9cb04fSpatrick     bool Success = ExecuteCommand(Cmd, &CmdOutput);
4401f9cb04fSpatrick     if (Success) {
4413cab2bb3Spatrick       Printf("ERROR: the input %s did not crash\n", CurrentFilePath.c_str());
4423cab2bb3Spatrick       exit(1);
4433cab2bb3Spatrick     }
4443cab2bb3Spatrick     Printf("CRASH_MIN: '%s' (%zd bytes) caused a crash. Will try to minimize "
4453cab2bb3Spatrick            "it further\n",
4463cab2bb3Spatrick            CurrentFilePath.c_str(), U.size());
4471f9cb04fSpatrick     auto DedupToken1 = GetDedupTokenFromCmdOutput(CmdOutput);
4483cab2bb3Spatrick     if (!DedupToken1.empty())
4493cab2bb3Spatrick       Printf("CRASH_MIN: DedupToken1: %s\n", DedupToken1.c_str());
4503cab2bb3Spatrick 
4513cab2bb3Spatrick     std::string ArtifactPath =
4523cab2bb3Spatrick         Flags.exact_artifact_path
4533cab2bb3Spatrick             ? Flags.exact_artifact_path
4543cab2bb3Spatrick             : Options.ArtifactPrefix + "minimized-from-" + Hash(U);
4553cab2bb3Spatrick     Cmd.addFlag("minimize_crash_internal_step", "1");
4563cab2bb3Spatrick     Cmd.addFlag("exact_artifact_path", ArtifactPath);
4571f9cb04fSpatrick     Printf("CRASH_MIN: executing: %s\n", Cmd.toString().c_str());
4581f9cb04fSpatrick     CmdOutput.clear();
4591f9cb04fSpatrick     Success = ExecuteCommand(Cmd, &CmdOutput);
4601f9cb04fSpatrick     Printf("%s", CmdOutput.c_str());
4611f9cb04fSpatrick     if (Success) {
4623cab2bb3Spatrick       if (Flags.exact_artifact_path) {
4633cab2bb3Spatrick         CurrentFilePath = Flags.exact_artifact_path;
4643cab2bb3Spatrick         WriteToFile(U, CurrentFilePath);
4653cab2bb3Spatrick       }
4663cab2bb3Spatrick       Printf("CRASH_MIN: failed to minimize beyond %s (%d bytes), exiting\n",
4673cab2bb3Spatrick              CurrentFilePath.c_str(), U.size());
4683cab2bb3Spatrick       break;
4693cab2bb3Spatrick     }
4701f9cb04fSpatrick     auto DedupToken2 = GetDedupTokenFromCmdOutput(CmdOutput);
4713cab2bb3Spatrick     if (!DedupToken2.empty())
4723cab2bb3Spatrick       Printf("CRASH_MIN: DedupToken2: %s\n", DedupToken2.c_str());
4733cab2bb3Spatrick 
4743cab2bb3Spatrick     if (DedupToken1 != DedupToken2) {
4753cab2bb3Spatrick       if (Flags.exact_artifact_path) {
4763cab2bb3Spatrick         CurrentFilePath = Flags.exact_artifact_path;
4773cab2bb3Spatrick         WriteToFile(U, CurrentFilePath);
4783cab2bb3Spatrick       }
4793cab2bb3Spatrick       Printf("CRASH_MIN: mismatch in dedup tokens"
4803cab2bb3Spatrick              " (looks like a different bug). Won't minimize further\n");
4813cab2bb3Spatrick       break;
4823cab2bb3Spatrick     }
4833cab2bb3Spatrick 
4843cab2bb3Spatrick     CurrentFilePath = ArtifactPath;
4853cab2bb3Spatrick     Printf("*********************************\n");
4863cab2bb3Spatrick   }
4873cab2bb3Spatrick   return 0;
4883cab2bb3Spatrick }
4893cab2bb3Spatrick 
MinimizeCrashInputInternalStep(Fuzzer * F,InputCorpus * Corpus)4903cab2bb3Spatrick int MinimizeCrashInputInternalStep(Fuzzer *F, InputCorpus *Corpus) {
4913cab2bb3Spatrick   assert(Inputs->size() == 1);
4923cab2bb3Spatrick   std::string InputFilePath = Inputs->at(0);
4933cab2bb3Spatrick   Unit U = FileToVector(InputFilePath);
4943cab2bb3Spatrick   Printf("INFO: Starting MinimizeCrashInputInternalStep: %zd\n", U.size());
4953cab2bb3Spatrick   if (U.size() < 2) {
4963cab2bb3Spatrick     Printf("INFO: The input is small enough, exiting\n");
4973cab2bb3Spatrick     exit(0);
4983cab2bb3Spatrick   }
4993cab2bb3Spatrick   F->SetMaxInputLen(U.size());
5003cab2bb3Spatrick   F->SetMaxMutationLen(U.size() - 1);
5013cab2bb3Spatrick   F->MinimizeCrashLoop(U);
5023cab2bb3Spatrick   Printf("INFO: Done MinimizeCrashInputInternalStep, no crashes found\n");
5033cab2bb3Spatrick   exit(0);
5043cab2bb3Spatrick   return 0;
5053cab2bb3Spatrick }
5063cab2bb3Spatrick 
Merge(Fuzzer * F,FuzzingOptions & Options,const std::vector<std::string> & Args,const std::vector<std::string> & Corpora,const char * CFPathOrNull)507*810390e3Srobert void Merge(Fuzzer *F, FuzzingOptions &Options,
508*810390e3Srobert            const std::vector<std::string> &Args,
509*810390e3Srobert            const std::vector<std::string> &Corpora, const char *CFPathOrNull) {
5103cab2bb3Spatrick   if (Corpora.size() < 2) {
5113cab2bb3Spatrick     Printf("INFO: Merge requires two or more corpus dirs\n");
5123cab2bb3Spatrick     exit(0);
5133cab2bb3Spatrick   }
5143cab2bb3Spatrick 
515*810390e3Srobert   std::vector<SizedFile> OldCorpus, NewCorpus;
5163cab2bb3Spatrick   GetSizedFilesFromDir(Corpora[0], &OldCorpus);
5173cab2bb3Spatrick   for (size_t i = 1; i < Corpora.size(); i++)
5183cab2bb3Spatrick     GetSizedFilesFromDir(Corpora[i], &NewCorpus);
5193cab2bb3Spatrick   std::sort(OldCorpus.begin(), OldCorpus.end());
5203cab2bb3Spatrick   std::sort(NewCorpus.begin(), NewCorpus.end());
5213cab2bb3Spatrick 
5221f9cb04fSpatrick   std::string CFPath = CFPathOrNull ? CFPathOrNull : TempPath("Merge", ".txt");
523*810390e3Srobert   std::vector<std::string> NewFiles;
524*810390e3Srobert   std::set<uint32_t> NewFeatures, NewCov;
5253cab2bb3Spatrick   CrashResistantMerge(Args, OldCorpus, NewCorpus, &NewFiles, {}, &NewFeatures,
526*810390e3Srobert                       {}, &NewCov, CFPath, true, Flags.set_cover_merge);
5273cab2bb3Spatrick   for (auto &Path : NewFiles)
5283cab2bb3Spatrick     F->WriteToOutputCorpus(FileToVector(Path, Options.MaxLen));
5293cab2bb3Spatrick   // We are done, delete the control file if it was a temporary one.
5303cab2bb3Spatrick   if (!Flags.merge_control_file)
5313cab2bb3Spatrick     RemoveFile(CFPath);
5323cab2bb3Spatrick 
5333cab2bb3Spatrick   exit(0);
5343cab2bb3Spatrick }
5353cab2bb3Spatrick 
AnalyzeDictionary(Fuzzer * F,const std::vector<Unit> & Dict,UnitVector & Corpus)536*810390e3Srobert int AnalyzeDictionary(Fuzzer *F, const std::vector<Unit> &Dict,
5373cab2bb3Spatrick                       UnitVector &Corpus) {
5383cab2bb3Spatrick   Printf("Started dictionary minimization (up to %d tests)\n",
5393cab2bb3Spatrick          Dict.size() * Corpus.size() * 2);
5403cab2bb3Spatrick 
5413cab2bb3Spatrick   // Scores and usage count for each dictionary unit.
542*810390e3Srobert   std::vector<int> Scores(Dict.size());
543*810390e3Srobert   std::vector<int> Usages(Dict.size());
5443cab2bb3Spatrick 
545*810390e3Srobert   std::vector<size_t> InitialFeatures;
546*810390e3Srobert   std::vector<size_t> ModifiedFeatures;
5473cab2bb3Spatrick   for (auto &C : Corpus) {
5483cab2bb3Spatrick     // Get coverage for the testcase without modifications.
5493cab2bb3Spatrick     F->ExecuteCallback(C.data(), C.size());
5503cab2bb3Spatrick     InitialFeatures.clear();
5513cab2bb3Spatrick     TPC.CollectFeatures([&](size_t Feature) {
5523cab2bb3Spatrick       InitialFeatures.push_back(Feature);
5533cab2bb3Spatrick     });
5543cab2bb3Spatrick 
5553cab2bb3Spatrick     for (size_t i = 0; i < Dict.size(); ++i) {
556*810390e3Srobert       std::vector<uint8_t> Data = C;
5573cab2bb3Spatrick       auto StartPos = std::search(Data.begin(), Data.end(),
5583cab2bb3Spatrick                                   Dict[i].begin(), Dict[i].end());
5593cab2bb3Spatrick       // Skip dictionary unit, if the testcase does not contain it.
5603cab2bb3Spatrick       if (StartPos == Data.end())
5613cab2bb3Spatrick         continue;
5623cab2bb3Spatrick 
5633cab2bb3Spatrick       ++Usages[i];
5643cab2bb3Spatrick       while (StartPos != Data.end()) {
5653cab2bb3Spatrick         // Replace all occurrences of dictionary unit in the testcase.
5663cab2bb3Spatrick         auto EndPos = StartPos + Dict[i].size();
5673cab2bb3Spatrick         for (auto It = StartPos; It != EndPos; ++It)
5683cab2bb3Spatrick           *It ^= 0xFF;
5693cab2bb3Spatrick 
5703cab2bb3Spatrick         StartPos = std::search(EndPos, Data.end(),
5713cab2bb3Spatrick                                Dict[i].begin(), Dict[i].end());
5723cab2bb3Spatrick       }
5733cab2bb3Spatrick 
5743cab2bb3Spatrick       // Get coverage for testcase with masked occurrences of dictionary unit.
5753cab2bb3Spatrick       F->ExecuteCallback(Data.data(), Data.size());
5763cab2bb3Spatrick       ModifiedFeatures.clear();
5773cab2bb3Spatrick       TPC.CollectFeatures([&](size_t Feature) {
5783cab2bb3Spatrick         ModifiedFeatures.push_back(Feature);
5793cab2bb3Spatrick       });
5803cab2bb3Spatrick 
5813cab2bb3Spatrick       if (InitialFeatures == ModifiedFeatures)
5823cab2bb3Spatrick         --Scores[i];
5833cab2bb3Spatrick       else
5843cab2bb3Spatrick         Scores[i] += 2;
5853cab2bb3Spatrick     }
5863cab2bb3Spatrick   }
5873cab2bb3Spatrick 
5883cab2bb3Spatrick   Printf("###### Useless dictionary elements. ######\n");
5893cab2bb3Spatrick   for (size_t i = 0; i < Dict.size(); ++i) {
5903cab2bb3Spatrick     // Dictionary units with positive score are treated as useful ones.
5913cab2bb3Spatrick     if (Scores[i] > 0)
5923cab2bb3Spatrick        continue;
5933cab2bb3Spatrick 
5943cab2bb3Spatrick     Printf("\"");
5953cab2bb3Spatrick     PrintASCII(Dict[i].data(), Dict[i].size(), "\"");
5963cab2bb3Spatrick     Printf(" # Score: %d, Used: %d\n", Scores[i], Usages[i]);
5973cab2bb3Spatrick   }
5983cab2bb3Spatrick   Printf("###### End of useless dictionary elements. ######\n");
5993cab2bb3Spatrick   return 0;
6003cab2bb3Spatrick }
6013cab2bb3Spatrick 
ParseSeedInuts(const char * seed_inputs)602*810390e3Srobert std::vector<std::string> ParseSeedInuts(const char *seed_inputs) {
6033cab2bb3Spatrick   // Parse -seed_inputs=file1,file2,... or -seed_inputs=@seed_inputs_file
604*810390e3Srobert   std::vector<std::string> Files;
6053cab2bb3Spatrick   if (!seed_inputs) return Files;
6063cab2bb3Spatrick   std::string SeedInputs;
6073cab2bb3Spatrick   if (Flags.seed_inputs[0] == '@')
6083cab2bb3Spatrick     SeedInputs = FileToString(Flags.seed_inputs + 1); // File contains list.
6093cab2bb3Spatrick   else
6103cab2bb3Spatrick     SeedInputs = Flags.seed_inputs; // seed_inputs contains the list.
6113cab2bb3Spatrick   if (SeedInputs.empty()) {
6123cab2bb3Spatrick     Printf("seed_inputs is empty or @file does not exist.\n");
6133cab2bb3Spatrick     exit(1);
6143cab2bb3Spatrick   }
6153cab2bb3Spatrick   // Parse SeedInputs.
6163cab2bb3Spatrick   size_t comma_pos = 0;
6173cab2bb3Spatrick   while ((comma_pos = SeedInputs.find_last_of(',')) != std::string::npos) {
6183cab2bb3Spatrick     Files.push_back(SeedInputs.substr(comma_pos + 1));
6193cab2bb3Spatrick     SeedInputs = SeedInputs.substr(0, comma_pos);
6203cab2bb3Spatrick   }
6213cab2bb3Spatrick   Files.push_back(SeedInputs);
6223cab2bb3Spatrick   return Files;
6233cab2bb3Spatrick }
6243cab2bb3Spatrick 
625*810390e3Srobert static std::vector<SizedFile>
ReadCorpora(const std::vector<std::string> & CorpusDirs,const std::vector<std::string> & ExtraSeedFiles)626*810390e3Srobert ReadCorpora(const std::vector<std::string> &CorpusDirs,
627*810390e3Srobert             const std::vector<std::string> &ExtraSeedFiles) {
628*810390e3Srobert   std::vector<SizedFile> SizedFiles;
6293cab2bb3Spatrick   size_t LastNumFiles = 0;
6303cab2bb3Spatrick   for (auto &Dir : CorpusDirs) {
6313cab2bb3Spatrick     GetSizedFilesFromDir(Dir, &SizedFiles);
6323cab2bb3Spatrick     Printf("INFO: % 8zd files found in %s\n", SizedFiles.size() - LastNumFiles,
6333cab2bb3Spatrick            Dir.c_str());
6343cab2bb3Spatrick     LastNumFiles = SizedFiles.size();
6353cab2bb3Spatrick   }
6363cab2bb3Spatrick   for (auto &File : ExtraSeedFiles)
6373cab2bb3Spatrick     if (auto Size = FileSize(File))
6383cab2bb3Spatrick       SizedFiles.push_back({File, Size});
6393cab2bb3Spatrick   return SizedFiles;
6403cab2bb3Spatrick }
6413cab2bb3Spatrick 
FuzzerDriver(int * argc,char *** argv,UserCallback Callback)6423cab2bb3Spatrick int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
6433cab2bb3Spatrick   using namespace fuzzer;
6443cab2bb3Spatrick   assert(argc && argv && "Argument pointers cannot be nullptr");
6453cab2bb3Spatrick   std::string Argv0((*argv)[0]);
6463cab2bb3Spatrick   EF = new ExternalFunctions();
6473cab2bb3Spatrick   if (EF->LLVMFuzzerInitialize)
6483cab2bb3Spatrick     EF->LLVMFuzzerInitialize(argc, argv);
6493cab2bb3Spatrick   if (EF->__msan_scoped_disable_interceptor_checks)
6503cab2bb3Spatrick     EF->__msan_scoped_disable_interceptor_checks();
651*810390e3Srobert   const std::vector<std::string> Args(*argv, *argv + *argc);
6523cab2bb3Spatrick   assert(!Args.empty());
6533cab2bb3Spatrick   ProgName = new std::string(Args[0]);
6543cab2bb3Spatrick   if (Argv0 != *ProgName) {
6553cab2bb3Spatrick     Printf("ERROR: argv[0] has been modified in LLVMFuzzerInitialize\n");
6563cab2bb3Spatrick     exit(1);
6573cab2bb3Spatrick   }
6583cab2bb3Spatrick   ParseFlags(Args, EF);
6593cab2bb3Spatrick   if (Flags.help) {
6603cab2bb3Spatrick     PrintHelp();
6613cab2bb3Spatrick     return 0;
6623cab2bb3Spatrick   }
6633cab2bb3Spatrick 
6643cab2bb3Spatrick   if (Flags.close_fd_mask & 2)
6653cab2bb3Spatrick     DupAndCloseStderr();
6663cab2bb3Spatrick   if (Flags.close_fd_mask & 1)
6673cab2bb3Spatrick     CloseStdout();
6683cab2bb3Spatrick 
6693cab2bb3Spatrick   if (Flags.jobs > 0 && Flags.workers == 0) {
6703cab2bb3Spatrick     Flags.workers = std::min(NumberOfCpuCores() / 2, Flags.jobs);
6713cab2bb3Spatrick     if (Flags.workers > 1)
6723cab2bb3Spatrick       Printf("Running %u workers\n", Flags.workers);
6733cab2bb3Spatrick   }
6743cab2bb3Spatrick 
6753cab2bb3Spatrick   if (Flags.workers > 0 && Flags.jobs > 0)
6763cab2bb3Spatrick     return RunInMultipleProcesses(Args, Flags.workers, Flags.jobs);
6773cab2bb3Spatrick 
6783cab2bb3Spatrick   FuzzingOptions Options;
6793cab2bb3Spatrick   Options.Verbosity = Flags.verbosity;
6803cab2bb3Spatrick   Options.MaxLen = Flags.max_len;
6813cab2bb3Spatrick   Options.LenControl = Flags.len_control;
682d89ec533Spatrick   Options.KeepSeed = Flags.keep_seed;
6833cab2bb3Spatrick   Options.UnitTimeoutSec = Flags.timeout;
6843cab2bb3Spatrick   Options.ErrorExitCode = Flags.error_exitcode;
6853cab2bb3Spatrick   Options.TimeoutExitCode = Flags.timeout_exitcode;
6863cab2bb3Spatrick   Options.IgnoreTimeouts = Flags.ignore_timeouts;
6873cab2bb3Spatrick   Options.IgnoreOOMs = Flags.ignore_ooms;
6883cab2bb3Spatrick   Options.IgnoreCrashes = Flags.ignore_crashes;
6893cab2bb3Spatrick   Options.MaxTotalTimeSec = Flags.max_total_time;
6903cab2bb3Spatrick   Options.DoCrossOver = Flags.cross_over;
691d89ec533Spatrick   Options.CrossOverUniformDist = Flags.cross_over_uniform_dist;
6923cab2bb3Spatrick   Options.MutateDepth = Flags.mutate_depth;
6933cab2bb3Spatrick   Options.ReduceDepth = Flags.reduce_depth;
6943cab2bb3Spatrick   Options.UseCounters = Flags.use_counters;
6953cab2bb3Spatrick   Options.UseMemmem = Flags.use_memmem;
6963cab2bb3Spatrick   Options.UseCmp = Flags.use_cmp;
6973cab2bb3Spatrick   Options.UseValueProfile = Flags.use_value_profile;
6983cab2bb3Spatrick   Options.Shrink = Flags.shrink;
6993cab2bb3Spatrick   Options.ReduceInputs = Flags.reduce_inputs;
7003cab2bb3Spatrick   Options.ShuffleAtStartUp = Flags.shuffle;
7013cab2bb3Spatrick   Options.PreferSmall = Flags.prefer_small;
7023cab2bb3Spatrick   Options.ReloadIntervalSec = Flags.reload;
7033cab2bb3Spatrick   Options.OnlyASCII = Flags.only_ascii;
7043cab2bb3Spatrick   Options.DetectLeaks = Flags.detect_leaks;
7053cab2bb3Spatrick   Options.PurgeAllocatorIntervalSec = Flags.purge_allocator_interval;
7063cab2bb3Spatrick   Options.TraceMalloc = Flags.trace_malloc;
7073cab2bb3Spatrick   Options.RssLimitMb = Flags.rss_limit_mb;
7083cab2bb3Spatrick   Options.MallocLimitMb = Flags.malloc_limit_mb;
7093cab2bb3Spatrick   if (!Options.MallocLimitMb)
7103cab2bb3Spatrick     Options.MallocLimitMb = Options.RssLimitMb;
7113cab2bb3Spatrick   if (Flags.runs >= 0)
7123cab2bb3Spatrick     Options.MaxNumberOfRuns = Flags.runs;
713d89ec533Spatrick   if (!Inputs->empty() && !Flags.minimize_crash_internal_step) {
714d89ec533Spatrick     // Ensure output corpus assumed to be the first arbitrary argument input
715d89ec533Spatrick     // is not a path to an existing file.
716d89ec533Spatrick     std::string OutputCorpusDir = (*Inputs)[0];
717d89ec533Spatrick     if (!IsFile(OutputCorpusDir)) {
718d89ec533Spatrick       Options.OutputCorpus = OutputCorpusDir;
719d89ec533Spatrick       ValidateDirectoryExists(Options.OutputCorpus, Flags.create_missing_dirs);
720d89ec533Spatrick     }
721d89ec533Spatrick   }
7223cab2bb3Spatrick   Options.ReportSlowUnits = Flags.report_slow_units;
723d89ec533Spatrick   if (Flags.artifact_prefix) {
7243cab2bb3Spatrick     Options.ArtifactPrefix = Flags.artifact_prefix;
725d89ec533Spatrick 
726d89ec533Spatrick     // Since the prefix could be a full path to a file name prefix, assume
727d89ec533Spatrick     // that if the path ends with the platform's separator that a directory
728d89ec533Spatrick     // is desired
729d89ec533Spatrick     std::string ArtifactPathDir = Options.ArtifactPrefix;
730d89ec533Spatrick     if (!IsSeparator(ArtifactPathDir[ArtifactPathDir.length() - 1])) {
731d89ec533Spatrick       ArtifactPathDir = DirName(ArtifactPathDir);
732d89ec533Spatrick     }
733d89ec533Spatrick     ValidateDirectoryExists(ArtifactPathDir, Flags.create_missing_dirs);
734d89ec533Spatrick   }
735d89ec533Spatrick   if (Flags.exact_artifact_path) {
7363cab2bb3Spatrick     Options.ExactArtifactPath = Flags.exact_artifact_path;
737d89ec533Spatrick     ValidateDirectoryExists(DirName(Options.ExactArtifactPath),
738d89ec533Spatrick                             Flags.create_missing_dirs);
739d89ec533Spatrick   }
740*810390e3Srobert   std::vector<Unit> Dictionary;
7413cab2bb3Spatrick   if (Flags.dict)
7423cab2bb3Spatrick     if (!ParseDictionaryFile(FileToString(Flags.dict), &Dictionary))
7433cab2bb3Spatrick       return 1;
7443cab2bb3Spatrick   if (Flags.verbosity > 0 && !Dictionary.empty())
7453cab2bb3Spatrick     Printf("Dictionary: %zd entries\n", Dictionary.size());
7463cab2bb3Spatrick   bool RunIndividualFiles = AllInputsAreFiles();
7473cab2bb3Spatrick   Options.SaveArtifacts =
7483cab2bb3Spatrick       !RunIndividualFiles || Flags.minimize_crash_internal_step;
7493cab2bb3Spatrick   Options.PrintNewCovPcs = Flags.print_pcs;
7503cab2bb3Spatrick   Options.PrintNewCovFuncs = Flags.print_funcs;
7513cab2bb3Spatrick   Options.PrintFinalStats = Flags.print_final_stats;
7523cab2bb3Spatrick   Options.PrintCorpusStats = Flags.print_corpus_stats;
7533cab2bb3Spatrick   Options.PrintCoverage = Flags.print_coverage;
754d89ec533Spatrick   Options.PrintFullCoverage = Flags.print_full_coverage;
7553cab2bb3Spatrick   if (Flags.exit_on_src_pos)
7563cab2bb3Spatrick     Options.ExitOnSrcPos = Flags.exit_on_src_pos;
7573cab2bb3Spatrick   if (Flags.exit_on_item)
7583cab2bb3Spatrick     Options.ExitOnItem = Flags.exit_on_item;
7593cab2bb3Spatrick   if (Flags.focus_function)
7603cab2bb3Spatrick     Options.FocusFunction = Flags.focus_function;
7613cab2bb3Spatrick   if (Flags.data_flow_trace)
7623cab2bb3Spatrick     Options.DataFlowTrace = Flags.data_flow_trace;
763d89ec533Spatrick   if (Flags.features_dir) {
7643cab2bb3Spatrick     Options.FeaturesDir = Flags.features_dir;
765d89ec533Spatrick     ValidateDirectoryExists(Options.FeaturesDir, Flags.create_missing_dirs);
766d89ec533Spatrick   }
767d89ec533Spatrick   if (Flags.mutation_graph_file)
768d89ec533Spatrick     Options.MutationGraphFile = Flags.mutation_graph_file;
7693cab2bb3Spatrick   if (Flags.collect_data_flow)
7703cab2bb3Spatrick     Options.CollectDataFlow = Flags.collect_data_flow;
7713cab2bb3Spatrick   if (Flags.stop_file)
7723cab2bb3Spatrick     Options.StopFile = Flags.stop_file;
7731f9cb04fSpatrick   Options.Entropic = Flags.entropic;
7741f9cb04fSpatrick   Options.EntropicFeatureFrequencyThreshold =
7751f9cb04fSpatrick       (size_t)Flags.entropic_feature_frequency_threshold;
7761f9cb04fSpatrick   Options.EntropicNumberOfRarestFeatures =
7771f9cb04fSpatrick       (size_t)Flags.entropic_number_of_rarest_features;
778d89ec533Spatrick   Options.EntropicScalePerExecTime = Flags.entropic_scale_per_exec_time;
779d89ec533Spatrick   if (!Options.FocusFunction.empty())
780d89ec533Spatrick     Options.Entropic = false; // FocusFunction overrides entropic scheduling.
781d89ec533Spatrick   if (Options.Entropic)
7821f9cb04fSpatrick     Printf("INFO: Running with entropic power schedule (0x%X, %d).\n",
7831f9cb04fSpatrick            Options.EntropicFeatureFrequencyThreshold,
7841f9cb04fSpatrick            Options.EntropicNumberOfRarestFeatures);
7851f9cb04fSpatrick   struct EntropicOptions Entropic;
7861f9cb04fSpatrick   Entropic.Enabled = Options.Entropic;
7871f9cb04fSpatrick   Entropic.FeatureFrequencyThreshold =
7881f9cb04fSpatrick       Options.EntropicFeatureFrequencyThreshold;
7891f9cb04fSpatrick   Entropic.NumberOfRarestFeatures = Options.EntropicNumberOfRarestFeatures;
790d89ec533Spatrick   Entropic.ScalePerExecTime = Options.EntropicScalePerExecTime;
7913cab2bb3Spatrick 
7923cab2bb3Spatrick   unsigned Seed = Flags.seed;
7933cab2bb3Spatrick   // Initialize Seed.
7943cab2bb3Spatrick   if (Seed == 0)
795d89ec533Spatrick     Seed = static_cast<unsigned>(
796d89ec533Spatrick         std::chrono::system_clock::now().time_since_epoch().count() + GetPid());
7973cab2bb3Spatrick   if (Flags.verbosity)
7983cab2bb3Spatrick     Printf("INFO: Seed: %u\n", Seed);
7993cab2bb3Spatrick 
800*810390e3Srobert   if (Flags.collect_data_flow && !Flags.fork &&
801*810390e3Srobert       !(Flags.merge || Flags.set_cover_merge)) {
8023cab2bb3Spatrick     if (RunIndividualFiles)
8033cab2bb3Spatrick       return CollectDataFlow(Flags.collect_data_flow, Flags.data_flow_trace,
8043cab2bb3Spatrick                         ReadCorpora({}, *Inputs));
8053cab2bb3Spatrick     else
8063cab2bb3Spatrick       return CollectDataFlow(Flags.collect_data_flow, Flags.data_flow_trace,
8073cab2bb3Spatrick                         ReadCorpora(*Inputs, {}));
8083cab2bb3Spatrick   }
8093cab2bb3Spatrick 
8103cab2bb3Spatrick   Random Rand(Seed);
8113cab2bb3Spatrick   auto *MD = new MutationDispatcher(Rand, Options);
8121f9cb04fSpatrick   auto *Corpus = new InputCorpus(Options.OutputCorpus, Entropic);
8133cab2bb3Spatrick   auto *F = new Fuzzer(Callback, *Corpus, *MD, Options);
8143cab2bb3Spatrick 
8153cab2bb3Spatrick   for (auto &U: Dictionary)
8163cab2bb3Spatrick     if (U.size() <= Word::GetMaxSize())
8173cab2bb3Spatrick       MD->AddWordToManualDictionary(Word(U.data(), U.size()));
8183cab2bb3Spatrick 
8193cab2bb3Spatrick       // Threads are only supported by Chrome. Don't use them with emscripten
8203cab2bb3Spatrick       // for now.
8213cab2bb3Spatrick #if !LIBFUZZER_EMSCRIPTEN
8223cab2bb3Spatrick   StartRssThread(F, Flags.rss_limit_mb);
8233cab2bb3Spatrick #endif // LIBFUZZER_EMSCRIPTEN
8243cab2bb3Spatrick 
8253cab2bb3Spatrick   Options.HandleAbrt = Flags.handle_abrt;
826d89ec533Spatrick   Options.HandleAlrm = !Flags.minimize_crash;
8273cab2bb3Spatrick   Options.HandleBus = Flags.handle_bus;
8283cab2bb3Spatrick   Options.HandleFpe = Flags.handle_fpe;
8293cab2bb3Spatrick   Options.HandleIll = Flags.handle_ill;
8303cab2bb3Spatrick   Options.HandleInt = Flags.handle_int;
8313cab2bb3Spatrick   Options.HandleSegv = Flags.handle_segv;
8323cab2bb3Spatrick   Options.HandleTerm = Flags.handle_term;
8333cab2bb3Spatrick   Options.HandleXfsz = Flags.handle_xfsz;
8343cab2bb3Spatrick   Options.HandleUsr1 = Flags.handle_usr1;
8353cab2bb3Spatrick   Options.HandleUsr2 = Flags.handle_usr2;
836d89ec533Spatrick   Options.HandleWinExcept = Flags.handle_winexcept;
837d89ec533Spatrick 
8383cab2bb3Spatrick   SetSignalHandler(Options);
8393cab2bb3Spatrick 
8403cab2bb3Spatrick   std::atexit(Fuzzer::StaticExitCallback);
8413cab2bb3Spatrick 
8423cab2bb3Spatrick   if (Flags.minimize_crash)
8433cab2bb3Spatrick     return MinimizeCrashInput(Args, Options);
8443cab2bb3Spatrick 
8453cab2bb3Spatrick   if (Flags.minimize_crash_internal_step)
8463cab2bb3Spatrick     return MinimizeCrashInputInternalStep(F, Corpus);
8473cab2bb3Spatrick 
8483cab2bb3Spatrick   if (Flags.cleanse_crash)
8493cab2bb3Spatrick     return CleanseCrashInput(Args, Options);
8503cab2bb3Spatrick 
8513cab2bb3Spatrick   if (RunIndividualFiles) {
8523cab2bb3Spatrick     Options.SaveArtifacts = false;
8533cab2bb3Spatrick     int Runs = std::max(1, Flags.runs);
8543cab2bb3Spatrick     Printf("%s: Running %zd inputs %d time(s) each.\n", ProgName->c_str(),
8553cab2bb3Spatrick            Inputs->size(), Runs);
8563cab2bb3Spatrick     for (auto &Path : *Inputs) {
8573cab2bb3Spatrick       auto StartTime = system_clock::now();
8583cab2bb3Spatrick       Printf("Running: %s\n", Path.c_str());
8593cab2bb3Spatrick       for (int Iter = 0; Iter < Runs; Iter++)
8603cab2bb3Spatrick         RunOneTest(F, Path.c_str(), Options.MaxLen);
8613cab2bb3Spatrick       auto StopTime = system_clock::now();
8623cab2bb3Spatrick       auto MS = duration_cast<milliseconds>(StopTime - StartTime).count();
8633cab2bb3Spatrick       Printf("Executed %s in %zd ms\n", Path.c_str(), (long)MS);
8643cab2bb3Spatrick     }
8653cab2bb3Spatrick     Printf("***\n"
8663cab2bb3Spatrick            "*** NOTE: fuzzing was not performed, you have only\n"
8673cab2bb3Spatrick            "***       executed the target code on a fixed set of inputs.\n"
8683cab2bb3Spatrick            "***\n");
8693cab2bb3Spatrick     F->PrintFinalStats();
8703cab2bb3Spatrick     exit(0);
8713cab2bb3Spatrick   }
8723cab2bb3Spatrick 
873*810390e3Srobert   Options.ForkCorpusGroups = Flags.fork_corpus_groups;
8743cab2bb3Spatrick   if (Flags.fork)
8753cab2bb3Spatrick     FuzzWithFork(F->GetMD().GetRand(), Options, Args, *Inputs, Flags.fork);
8763cab2bb3Spatrick 
877*810390e3Srobert   if (Flags.merge || Flags.set_cover_merge)
8783cab2bb3Spatrick     Merge(F, Options, Args, *Inputs, Flags.merge_control_file);
8793cab2bb3Spatrick 
8803cab2bb3Spatrick   if (Flags.merge_inner) {
8813cab2bb3Spatrick     const size_t kDefaultMaxMergeLen = 1 << 20;
8823cab2bb3Spatrick     if (Options.MaxLen == 0)
8833cab2bb3Spatrick       F->SetMaxInputLen(kDefaultMaxMergeLen);
8843cab2bb3Spatrick     assert(Flags.merge_control_file);
885*810390e3Srobert     F->CrashResistantMergeInternalStep(Flags.merge_control_file,
886*810390e3Srobert                                        !strncmp(Flags.merge_inner, "2", 1));
8873cab2bb3Spatrick     exit(0);
8883cab2bb3Spatrick   }
8893cab2bb3Spatrick 
8903cab2bb3Spatrick   if (Flags.analyze_dict) {
8913cab2bb3Spatrick     size_t MaxLen = INT_MAX;  // Large max length.
8923cab2bb3Spatrick     UnitVector InitialCorpus;
8933cab2bb3Spatrick     for (auto &Inp : *Inputs) {
8943cab2bb3Spatrick       Printf("Loading corpus dir: %s\n", Inp.c_str());
8953cab2bb3Spatrick       ReadDirToVectorOfUnits(Inp.c_str(), &InitialCorpus, nullptr,
8963cab2bb3Spatrick                              MaxLen, /*ExitOnError=*/false);
8973cab2bb3Spatrick     }
8983cab2bb3Spatrick 
8993cab2bb3Spatrick     if (Dictionary.empty() || Inputs->empty()) {
9003cab2bb3Spatrick       Printf("ERROR: can't analyze dict without dict and corpus provided\n");
9013cab2bb3Spatrick       return 1;
9023cab2bb3Spatrick     }
9033cab2bb3Spatrick     if (AnalyzeDictionary(F, Dictionary, InitialCorpus)) {
9043cab2bb3Spatrick       Printf("Dictionary analysis failed\n");
9053cab2bb3Spatrick       exit(1);
9063cab2bb3Spatrick     }
9073cab2bb3Spatrick     Printf("Dictionary analysis succeeded\n");
9083cab2bb3Spatrick     exit(0);
9093cab2bb3Spatrick   }
9103cab2bb3Spatrick 
9113cab2bb3Spatrick   auto CorporaFiles = ReadCorpora(*Inputs, ParseSeedInuts(Flags.seed_inputs));
9123cab2bb3Spatrick   F->Loop(CorporaFiles);
9133cab2bb3Spatrick 
9143cab2bb3Spatrick   if (Flags.verbosity)
9153cab2bb3Spatrick     Printf("Done %zd runs in %zd second(s)\n", F->getTotalNumberOfRuns(),
9163cab2bb3Spatrick            F->secondsSinceProcessStartUp());
9173cab2bb3Spatrick   F->PrintFinalStats();
9183cab2bb3Spatrick 
9193cab2bb3Spatrick   exit(0);  // Don't let F destroy itself.
9203cab2bb3Spatrick }
9213cab2bb3Spatrick 
922d89ec533Spatrick extern "C" ATTRIBUTE_INTERFACE int
LLVMFuzzerRunDriver(int * argc,char *** argv,int (* UserCb)(const uint8_t * Data,size_t Size))923d89ec533Spatrick LLVMFuzzerRunDriver(int *argc, char ***argv,
924d89ec533Spatrick                     int (*UserCb)(const uint8_t *Data, size_t Size)) {
925d89ec533Spatrick   return FuzzerDriver(argc, argv, UserCb);
926d89ec533Spatrick }
927d89ec533Spatrick 
9283cab2bb3Spatrick // Storage for global ExternalFunctions object.
9293cab2bb3Spatrick ExternalFunctions *EF = nullptr;
9303cab2bb3Spatrick 
9313cab2bb3Spatrick }  // namespace fuzzer
932