10b57cec5SDimitry Andric //===- FuzzerDriver.cpp - FuzzerDriver function and flags -----------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric // FuzzerDriver and flag parsing.
90b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #include "FuzzerCommand.h"
120b57cec5SDimitry Andric #include "FuzzerCorpus.h"
130b57cec5SDimitry Andric #include "FuzzerFork.h"
140b57cec5SDimitry Andric #include "FuzzerIO.h"
150b57cec5SDimitry Andric #include "FuzzerInterface.h"
160b57cec5SDimitry Andric #include "FuzzerInternal.h"
170b57cec5SDimitry Andric #include "FuzzerMerge.h"
180b57cec5SDimitry Andric #include "FuzzerMutate.h"
195ffd83dbSDimitry Andric #include "FuzzerPlatform.h"
200b57cec5SDimitry Andric #include "FuzzerRandom.h"
210b57cec5SDimitry Andric #include "FuzzerTracePC.h"
220b57cec5SDimitry Andric #include <algorithm>
230b57cec5SDimitry Andric #include <atomic>
240b57cec5SDimitry Andric #include <chrono>
250b57cec5SDimitry Andric #include <cstdlib>
260b57cec5SDimitry Andric #include <cstring>
270b57cec5SDimitry Andric #include <mutex>
280b57cec5SDimitry Andric #include <string>
290b57cec5SDimitry Andric #include <thread>
300b57cec5SDimitry Andric #include <fstream>
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric // This function should be present in the libFuzzer so that the client
330b57cec5SDimitry Andric // binary can test for its existence.
340b57cec5SDimitry Andric #if LIBFUZZER_MSVC
__libfuzzer_is_present()350b57cec5SDimitry Andric extern "C" void __libfuzzer_is_present() {}
36e8d8bef9SDimitry Andric #if defined(_M_IX86) || defined(__i386__)
37e8d8bef9SDimitry Andric #pragma comment(linker, "/include:___libfuzzer_is_present")
38e8d8bef9SDimitry Andric #else
390b57cec5SDimitry Andric #pragma comment(linker, "/include:__libfuzzer_is_present")
40e8d8bef9SDimitry Andric #endif
410b57cec5SDimitry Andric #else
__libfuzzer_is_present()420b57cec5SDimitry Andric extern "C" __attribute__((used)) void __libfuzzer_is_present() {}
430b57cec5SDimitry Andric #endif  // LIBFUZZER_MSVC
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric namespace fuzzer {
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric // Program arguments.
480b57cec5SDimitry Andric struct FlagDescription {
490b57cec5SDimitry Andric   const char *Name;
500b57cec5SDimitry Andric   const char *Description;
510b57cec5SDimitry Andric   int   Default;
520b57cec5SDimitry Andric   int   *IntFlag;
530b57cec5SDimitry Andric   const char **StrFlag;
540b57cec5SDimitry Andric   unsigned int *UIntFlag;
550b57cec5SDimitry Andric };
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric struct {
580b57cec5SDimitry Andric #define FUZZER_DEPRECATED_FLAG(Name)
590b57cec5SDimitry Andric #define FUZZER_FLAG_INT(Name, Default, Description) int Name;
600b57cec5SDimitry Andric #define FUZZER_FLAG_UNSIGNED(Name, Default, Description) unsigned int Name;
610b57cec5SDimitry Andric #define FUZZER_FLAG_STRING(Name, Description) const char *Name;
620b57cec5SDimitry Andric #include "FuzzerFlags.def"
630b57cec5SDimitry Andric #undef FUZZER_DEPRECATED_FLAG
640b57cec5SDimitry Andric #undef FUZZER_FLAG_INT
650b57cec5SDimitry Andric #undef FUZZER_FLAG_UNSIGNED
660b57cec5SDimitry Andric #undef FUZZER_FLAG_STRING
670b57cec5SDimitry Andric } Flags;
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric static const FlagDescription FlagDescriptions [] {
700b57cec5SDimitry Andric #define FUZZER_DEPRECATED_FLAG(Name)                                           \
710b57cec5SDimitry Andric   {#Name, "Deprecated; don't use", 0, nullptr, nullptr, nullptr},
720b57cec5SDimitry Andric #define FUZZER_FLAG_INT(Name, Default, Description)                            \
730b57cec5SDimitry Andric   {#Name, Description, Default, &Flags.Name, nullptr, nullptr},
740b57cec5SDimitry Andric #define FUZZER_FLAG_UNSIGNED(Name, Default, Description)                       \
750b57cec5SDimitry Andric   {#Name,   Description, static_cast<int>(Default),                            \
760b57cec5SDimitry Andric    nullptr, nullptr, &Flags.Name},
770b57cec5SDimitry Andric #define FUZZER_FLAG_STRING(Name, Description)                                  \
780b57cec5SDimitry Andric   {#Name, Description, 0, nullptr, &Flags.Name, nullptr},
790b57cec5SDimitry Andric #include "FuzzerFlags.def"
800b57cec5SDimitry Andric #undef FUZZER_DEPRECATED_FLAG
810b57cec5SDimitry Andric #undef FUZZER_FLAG_INT
820b57cec5SDimitry Andric #undef FUZZER_FLAG_UNSIGNED
830b57cec5SDimitry Andric #undef FUZZER_FLAG_STRING
840b57cec5SDimitry Andric };
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric static const size_t kNumFlags =
870b57cec5SDimitry Andric     sizeof(FlagDescriptions) / sizeof(FlagDescriptions[0]);
880b57cec5SDimitry Andric 
89349cc55cSDimitry Andric static std::vector<std::string> *Inputs;
900b57cec5SDimitry Andric static std::string *ProgName;
910b57cec5SDimitry Andric 
PrintHelp()920b57cec5SDimitry Andric static void PrintHelp() {
930b57cec5SDimitry Andric   Printf("Usage:\n");
940b57cec5SDimitry Andric   auto Prog = ProgName->c_str();
950b57cec5SDimitry Andric   Printf("\nTo run fuzzing pass 0 or more directories.\n");
960b57cec5SDimitry Andric   Printf("%s [-flag1=val1 [-flag2=val2 ...] ] [dir1 [dir2 ...] ]\n", Prog);
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric   Printf("\nTo run individual tests without fuzzing pass 1 or more files:\n");
990b57cec5SDimitry Andric   Printf("%s [-flag1=val1 [-flag2=val2 ...] ] file1 [file2 ...]\n", Prog);
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric   Printf("\nFlags: (strictly in form -flag=value)\n");
1020b57cec5SDimitry Andric   size_t MaxFlagLen = 0;
1030b57cec5SDimitry Andric   for (size_t F = 0; F < kNumFlags; F++)
1040b57cec5SDimitry Andric     MaxFlagLen = std::max(strlen(FlagDescriptions[F].Name), MaxFlagLen);
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric   for (size_t F = 0; F < kNumFlags; F++) {
1070b57cec5SDimitry Andric     const auto &D = FlagDescriptions[F];
1080b57cec5SDimitry Andric     if (strstr(D.Description, "internal flag") == D.Description) continue;
1090b57cec5SDimitry Andric     Printf(" %s", D.Name);
1100b57cec5SDimitry Andric     for (size_t i = 0, n = MaxFlagLen - strlen(D.Name); i < n; i++)
1110b57cec5SDimitry Andric       Printf(" ");
1120b57cec5SDimitry Andric     Printf("\t");
1130b57cec5SDimitry Andric     Printf("%d\t%s\n", D.Default, D.Description);
1140b57cec5SDimitry Andric   }
1150b57cec5SDimitry Andric   Printf("\nFlags starting with '--' will be ignored and "
1160b57cec5SDimitry Andric             "will be passed verbatim to subprocesses.\n");
1170b57cec5SDimitry Andric }
1180b57cec5SDimitry Andric 
FlagValue(const char * Param,const char * Name)1190b57cec5SDimitry Andric static const char *FlagValue(const char *Param, const char *Name) {
1200b57cec5SDimitry Andric   size_t Len = strlen(Name);
1210b57cec5SDimitry Andric   if (Param[0] == '-' && strstr(Param + 1, Name) == Param + 1 &&
1220b57cec5SDimitry Andric       Param[Len + 1] == '=')
1230b57cec5SDimitry Andric       return &Param[Len + 2];
1240b57cec5SDimitry Andric   return nullptr;
1250b57cec5SDimitry Andric }
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric // Avoid calling stol as it triggers a bug in clang/glibc build.
MyStol(const char * Str)1280b57cec5SDimitry Andric static long MyStol(const char *Str) {
1290b57cec5SDimitry Andric   long Res = 0;
1300b57cec5SDimitry Andric   long Sign = 1;
1310b57cec5SDimitry Andric   if (*Str == '-') {
1320b57cec5SDimitry Andric     Str++;
1330b57cec5SDimitry Andric     Sign = -1;
1340b57cec5SDimitry Andric   }
1350b57cec5SDimitry Andric   for (size_t i = 0; Str[i]; i++) {
1360b57cec5SDimitry Andric     char Ch = Str[i];
1370b57cec5SDimitry Andric     if (Ch < '0' || Ch > '9')
1380b57cec5SDimitry Andric       return Res;
1390b57cec5SDimitry Andric     Res = Res * 10 + (Ch - '0');
1400b57cec5SDimitry Andric   }
1410b57cec5SDimitry Andric   return Res * Sign;
1420b57cec5SDimitry Andric }
1430b57cec5SDimitry Andric 
ParseOneFlag(const char * Param)1440b57cec5SDimitry Andric static bool ParseOneFlag(const char *Param) {
1450b57cec5SDimitry Andric   if (Param[0] != '-') return false;
1460b57cec5SDimitry Andric   if (Param[1] == '-') {
1470b57cec5SDimitry Andric     static bool PrintedWarning = false;
1480b57cec5SDimitry Andric     if (!PrintedWarning) {
1490b57cec5SDimitry Andric       PrintedWarning = true;
1500b57cec5SDimitry Andric       Printf("INFO: libFuzzer ignores flags that start with '--'\n");
1510b57cec5SDimitry Andric     }
1520b57cec5SDimitry Andric     for (size_t F = 0; F < kNumFlags; F++)
1530b57cec5SDimitry Andric       if (FlagValue(Param + 1, FlagDescriptions[F].Name))
1540b57cec5SDimitry Andric         Printf("WARNING: did you mean '%s' (single dash)?\n", Param + 1);
1550b57cec5SDimitry Andric     return true;
1560b57cec5SDimitry Andric   }
1570b57cec5SDimitry Andric   for (size_t F = 0; F < kNumFlags; F++) {
1580b57cec5SDimitry Andric     const char *Name = FlagDescriptions[F].Name;
1590b57cec5SDimitry Andric     const char *Str = FlagValue(Param, Name);
1600b57cec5SDimitry Andric     if (Str)  {
1610b57cec5SDimitry Andric       if (FlagDescriptions[F].IntFlag) {
162fe6060f1SDimitry Andric         auto Val = MyStol(Str);
163fe6060f1SDimitry Andric         *FlagDescriptions[F].IntFlag = static_cast<int>(Val);
1640b57cec5SDimitry Andric         if (Flags.verbosity >= 2)
1650b57cec5SDimitry Andric           Printf("Flag: %s %d\n", Name, Val);
1660b57cec5SDimitry Andric         return true;
1670b57cec5SDimitry Andric       } else if (FlagDescriptions[F].UIntFlag) {
168fe6060f1SDimitry Andric         auto Val = std::stoul(Str);
169fe6060f1SDimitry Andric         *FlagDescriptions[F].UIntFlag = static_cast<unsigned int>(Val);
1700b57cec5SDimitry Andric         if (Flags.verbosity >= 2)
1710b57cec5SDimitry Andric           Printf("Flag: %s %u\n", Name, Val);
1720b57cec5SDimitry Andric         return true;
1730b57cec5SDimitry Andric       } else if (FlagDescriptions[F].StrFlag) {
1740b57cec5SDimitry Andric         *FlagDescriptions[F].StrFlag = Str;
1750b57cec5SDimitry Andric         if (Flags.verbosity >= 2)
1760b57cec5SDimitry Andric           Printf("Flag: %s %s\n", Name, Str);
1770b57cec5SDimitry Andric         return true;
1780b57cec5SDimitry Andric       } else {  // Deprecated flag.
1790b57cec5SDimitry Andric         Printf("Flag: %s: deprecated, don't use\n", Name);
1800b57cec5SDimitry Andric         return true;
1810b57cec5SDimitry Andric       }
1820b57cec5SDimitry Andric     }
1830b57cec5SDimitry Andric   }
1840b57cec5SDimitry Andric   Printf("\n\nWARNING: unrecognized flag '%s'; "
1850b57cec5SDimitry Andric          "use -help=1 to list all flags\n\n", Param);
1860b57cec5SDimitry Andric   return true;
1870b57cec5SDimitry Andric }
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric // We don't use any library to minimize dependencies.
ParseFlags(const std::vector<std::string> & Args,const ExternalFunctions * EF)190349cc55cSDimitry Andric static void ParseFlags(const std::vector<std::string> &Args,
1910b57cec5SDimitry Andric                        const ExternalFunctions *EF) {
1920b57cec5SDimitry Andric   for (size_t F = 0; F < kNumFlags; F++) {
1930b57cec5SDimitry Andric     if (FlagDescriptions[F].IntFlag)
1940b57cec5SDimitry Andric       *FlagDescriptions[F].IntFlag = FlagDescriptions[F].Default;
1950b57cec5SDimitry Andric     if (FlagDescriptions[F].UIntFlag)
1960b57cec5SDimitry Andric       *FlagDescriptions[F].UIntFlag =
1970b57cec5SDimitry Andric           static_cast<unsigned int>(FlagDescriptions[F].Default);
1980b57cec5SDimitry Andric     if (FlagDescriptions[F].StrFlag)
1990b57cec5SDimitry Andric       *FlagDescriptions[F].StrFlag = nullptr;
2000b57cec5SDimitry Andric   }
2010b57cec5SDimitry Andric 
2020b57cec5SDimitry Andric   // Disable len_control by default, if LLVMFuzzerCustomMutator is used.
2035ffd83dbSDimitry Andric   if (EF->LLVMFuzzerCustomMutator) {
2040b57cec5SDimitry Andric     Flags.len_control = 0;
2055ffd83dbSDimitry Andric     Printf("INFO: found LLVMFuzzerCustomMutator (%p). "
2065ffd83dbSDimitry Andric            "Disabling -len_control by default.\n", EF->LLVMFuzzerCustomMutator);
2075ffd83dbSDimitry Andric   }
2080b57cec5SDimitry Andric 
209349cc55cSDimitry Andric   Inputs = new std::vector<std::string>;
2100b57cec5SDimitry Andric   for (size_t A = 1; A < Args.size(); A++) {
2110b57cec5SDimitry Andric     if (ParseOneFlag(Args[A].c_str())) {
2120b57cec5SDimitry Andric       if (Flags.ignore_remaining_args)
2130b57cec5SDimitry Andric         break;
2140b57cec5SDimitry Andric       continue;
2150b57cec5SDimitry Andric     }
2160b57cec5SDimitry Andric     Inputs->push_back(Args[A]);
2170b57cec5SDimitry Andric   }
2180b57cec5SDimitry Andric }
2190b57cec5SDimitry Andric 
2200b57cec5SDimitry Andric static std::mutex Mu;
2210b57cec5SDimitry Andric 
PulseThread()2220b57cec5SDimitry Andric static void PulseThread() {
2230b57cec5SDimitry Andric   while (true) {
2240b57cec5SDimitry Andric     SleepSeconds(600);
2250b57cec5SDimitry Andric     std::lock_guard<std::mutex> Lock(Mu);
2260b57cec5SDimitry Andric     Printf("pulse...\n");
2270b57cec5SDimitry Andric   }
2280b57cec5SDimitry Andric }
2290b57cec5SDimitry Andric 
WorkerThread(const Command & BaseCmd,std::atomic<unsigned> * Counter,unsigned NumJobs,std::atomic<bool> * HasErrors)2300b57cec5SDimitry Andric static void WorkerThread(const Command &BaseCmd, std::atomic<unsigned> *Counter,
2310b57cec5SDimitry Andric                          unsigned NumJobs, std::atomic<bool> *HasErrors) {
2320b57cec5SDimitry Andric   while (true) {
2330b57cec5SDimitry Andric     unsigned C = (*Counter)++;
2340b57cec5SDimitry Andric     if (C >= NumJobs) break;
2350b57cec5SDimitry Andric     std::string Log = "fuzz-" + std::to_string(C) + ".log";
2360b57cec5SDimitry Andric     Command Cmd(BaseCmd);
2370b57cec5SDimitry Andric     Cmd.setOutputFile(Log);
2380b57cec5SDimitry Andric     Cmd.combineOutAndErr();
2390b57cec5SDimitry Andric     if (Flags.verbosity) {
2400b57cec5SDimitry Andric       std::string CommandLine = Cmd.toString();
2410b57cec5SDimitry Andric       Printf("%s\n", CommandLine.c_str());
2420b57cec5SDimitry Andric     }
2430b57cec5SDimitry Andric     int ExitCode = ExecuteCommand(Cmd);
2440b57cec5SDimitry Andric     if (ExitCode != 0)
2450b57cec5SDimitry Andric       *HasErrors = true;
2460b57cec5SDimitry Andric     std::lock_guard<std::mutex> Lock(Mu);
2470b57cec5SDimitry Andric     Printf("================== Job %u exited with exit code %d ============\n",
2480b57cec5SDimitry Andric            C, ExitCode);
2490b57cec5SDimitry Andric     fuzzer::CopyFileToErr(Log);
2500b57cec5SDimitry Andric   }
2510b57cec5SDimitry Andric }
2520b57cec5SDimitry Andric 
ValidateDirectoryExists(const std::string & Path,bool CreateDirectory)253e8d8bef9SDimitry Andric static void ValidateDirectoryExists(const std::string &Path,
254e8d8bef9SDimitry Andric                                     bool CreateDirectory) {
255e8d8bef9SDimitry Andric   if (Path.empty()) {
256e8d8bef9SDimitry Andric     Printf("ERROR: Provided directory path is an empty string\n");
257e8d8bef9SDimitry Andric     exit(1);
258e8d8bef9SDimitry Andric   }
259e8d8bef9SDimitry Andric 
260e8d8bef9SDimitry Andric   if (IsDirectory(Path))
261e8d8bef9SDimitry Andric     return;
262e8d8bef9SDimitry Andric 
263e8d8bef9SDimitry Andric   if (CreateDirectory) {
264e8d8bef9SDimitry Andric     if (!MkDirRecursive(Path)) {
265e8d8bef9SDimitry Andric       Printf("ERROR: Failed to create directory \"%s\"\n", Path.c_str());
266e8d8bef9SDimitry Andric       exit(1);
267e8d8bef9SDimitry Andric     }
268e8d8bef9SDimitry Andric     return;
269e8d8bef9SDimitry Andric   }
270e8d8bef9SDimitry Andric 
271e8d8bef9SDimitry Andric   Printf("ERROR: The required directory \"%s\" does not exist\n", Path.c_str());
272e8d8bef9SDimitry Andric   exit(1);
273e8d8bef9SDimitry Andric }
274e8d8bef9SDimitry Andric 
CloneArgsWithoutX(const std::vector<std::string> & Args,const char * X1,const char * X2)275349cc55cSDimitry Andric std::string CloneArgsWithoutX(const std::vector<std::string> &Args,
2760b57cec5SDimitry Andric                               const char *X1, const char *X2) {
2770b57cec5SDimitry Andric   std::string Cmd;
2780b57cec5SDimitry Andric   for (auto &S : Args) {
2790b57cec5SDimitry Andric     if (FlagValue(S.c_str(), X1) || FlagValue(S.c_str(), X2))
2800b57cec5SDimitry Andric       continue;
2810b57cec5SDimitry Andric     Cmd += S + " ";
2820b57cec5SDimitry Andric   }
2830b57cec5SDimitry Andric   return Cmd;
2840b57cec5SDimitry Andric }
2850b57cec5SDimitry Andric 
RunInMultipleProcesses(const std::vector<std::string> & Args,unsigned NumWorkers,unsigned NumJobs)286349cc55cSDimitry Andric static int RunInMultipleProcesses(const std::vector<std::string> &Args,
2870b57cec5SDimitry Andric                                   unsigned NumWorkers, unsigned NumJobs) {
2880b57cec5SDimitry Andric   std::atomic<unsigned> Counter(0);
2890b57cec5SDimitry Andric   std::atomic<bool> HasErrors(false);
2900b57cec5SDimitry Andric   Command Cmd(Args);
2910b57cec5SDimitry Andric   Cmd.removeFlag("jobs");
2920b57cec5SDimitry Andric   Cmd.removeFlag("workers");
293349cc55cSDimitry Andric   std::vector<std::thread> V;
2940b57cec5SDimitry Andric   std::thread Pulse(PulseThread);
2950b57cec5SDimitry Andric   Pulse.detach();
2965f757f3fSDimitry Andric   V.resize(NumWorkers);
2975f757f3fSDimitry Andric   for (unsigned i = 0; i < NumWorkers; i++) {
2985f757f3fSDimitry Andric     V[i] = std::thread(WorkerThread, std::ref(Cmd), &Counter, NumJobs,
2995f757f3fSDimitry Andric                             &HasErrors);
3005f757f3fSDimitry Andric     SetThreadName(V[i], "FuzzerWorker");
3015f757f3fSDimitry Andric   }
3020b57cec5SDimitry Andric   for (auto &T : V)
3030b57cec5SDimitry Andric     T.join();
3040b57cec5SDimitry Andric   return HasErrors ? 1 : 0;
3050b57cec5SDimitry Andric }
3060b57cec5SDimitry Andric 
RssThread(Fuzzer * F,size_t RssLimitMb)3070b57cec5SDimitry Andric static void RssThread(Fuzzer *F, size_t RssLimitMb) {
3080b57cec5SDimitry Andric   while (true) {
3090b57cec5SDimitry Andric     SleepSeconds(1);
3100b57cec5SDimitry Andric     size_t Peak = GetPeakRSSMb();
3110b57cec5SDimitry Andric     if (Peak > RssLimitMb)
3120b57cec5SDimitry Andric       F->RssLimitCallback();
3130b57cec5SDimitry Andric   }
3140b57cec5SDimitry Andric }
3150b57cec5SDimitry Andric 
StartRssThread(Fuzzer * F,size_t RssLimitMb)3160b57cec5SDimitry Andric static void StartRssThread(Fuzzer *F, size_t RssLimitMb) {
317480093f4SDimitry Andric   if (!RssLimitMb)
318480093f4SDimitry Andric     return;
3190b57cec5SDimitry Andric   std::thread T(RssThread, F, RssLimitMb);
3200b57cec5SDimitry Andric   T.detach();
3210b57cec5SDimitry Andric }
3220b57cec5SDimitry Andric 
RunOneTest(Fuzzer * F,const char * InputFilePath,size_t MaxLen)3230b57cec5SDimitry Andric int RunOneTest(Fuzzer *F, const char *InputFilePath, size_t MaxLen) {
3240b57cec5SDimitry Andric   Unit U = FileToVector(InputFilePath);
3250b57cec5SDimitry Andric   if (MaxLen && MaxLen < U.size())
3260b57cec5SDimitry Andric     U.resize(MaxLen);
3270b57cec5SDimitry Andric   F->ExecuteCallback(U.data(), U.size());
328e8d8bef9SDimitry Andric   if (Flags.print_full_coverage) {
329e8d8bef9SDimitry Andric     // Leak detection is not needed when collecting full coverage data.
330e8d8bef9SDimitry Andric     F->TPCUpdateObservedPCs();
331e8d8bef9SDimitry Andric   } else {
3320b57cec5SDimitry Andric     F->TryDetectingAMemoryLeak(U.data(), U.size(), true);
333e8d8bef9SDimitry Andric   }
3340b57cec5SDimitry Andric   return 0;
3350b57cec5SDimitry Andric }
3360b57cec5SDimitry Andric 
AllInputsAreFiles()3370b57cec5SDimitry Andric static bool AllInputsAreFiles() {
3380b57cec5SDimitry Andric   if (Inputs->empty()) return false;
3390b57cec5SDimitry Andric   for (auto &Path : *Inputs)
3400b57cec5SDimitry Andric     if (!IsFile(Path))
3410b57cec5SDimitry Andric       return false;
3420b57cec5SDimitry Andric   return true;
3430b57cec5SDimitry Andric }
3440b57cec5SDimitry Andric 
GetDedupTokenFromCmdOutput(const std::string & S)3455ffd83dbSDimitry Andric static std::string GetDedupTokenFromCmdOutput(const std::string &S) {
3460b57cec5SDimitry Andric   auto Beg = S.find("DEDUP_TOKEN:");
3470b57cec5SDimitry Andric   if (Beg == std::string::npos)
3480b57cec5SDimitry Andric     return "";
3490b57cec5SDimitry Andric   auto End = S.find('\n', Beg);
3500b57cec5SDimitry Andric   if (End == std::string::npos)
3510b57cec5SDimitry Andric     return "";
3520b57cec5SDimitry Andric   return S.substr(Beg, End - Beg);
3530b57cec5SDimitry Andric }
3540b57cec5SDimitry Andric 
CleanseCrashInput(const std::vector<std::string> & Args,const FuzzingOptions & Options)355349cc55cSDimitry Andric int CleanseCrashInput(const std::vector<std::string> &Args,
3560b57cec5SDimitry Andric                       const FuzzingOptions &Options) {
3570b57cec5SDimitry Andric   if (Inputs->size() != 1 || !Flags.exact_artifact_path) {
3580b57cec5SDimitry Andric     Printf("ERROR: -cleanse_crash should be given one input file and"
3590b57cec5SDimitry Andric           " -exact_artifact_path\n");
3600b57cec5SDimitry Andric     exit(1);
3610b57cec5SDimitry Andric   }
3620b57cec5SDimitry Andric   std::string InputFilePath = Inputs->at(0);
3630b57cec5SDimitry Andric   std::string OutputFilePath = Flags.exact_artifact_path;
3640b57cec5SDimitry Andric   Command Cmd(Args);
3650b57cec5SDimitry Andric   Cmd.removeFlag("cleanse_crash");
3660b57cec5SDimitry Andric 
3670b57cec5SDimitry Andric   assert(Cmd.hasArgument(InputFilePath));
3680b57cec5SDimitry Andric   Cmd.removeArgument(InputFilePath);
3690b57cec5SDimitry Andric 
3705ffd83dbSDimitry Andric   auto TmpFilePath = TempPath("CleanseCrashInput", ".repro");
3710b57cec5SDimitry Andric   Cmd.addArgument(TmpFilePath);
3725ffd83dbSDimitry Andric   Cmd.setOutputFile(getDevNull());
3730b57cec5SDimitry Andric   Cmd.combineOutAndErr();
3740b57cec5SDimitry Andric 
3750b57cec5SDimitry Andric   std::string CurrentFilePath = InputFilePath;
3760b57cec5SDimitry Andric   auto U = FileToVector(CurrentFilePath);
3770b57cec5SDimitry Andric   size_t Size = U.size();
3780b57cec5SDimitry Andric 
379349cc55cSDimitry Andric   const std::vector<uint8_t> ReplacementBytes = {' ', 0xff};
3800b57cec5SDimitry Andric   for (int NumAttempts = 0; NumAttempts < 5; NumAttempts++) {
3810b57cec5SDimitry Andric     bool Changed = false;
3820b57cec5SDimitry Andric     for (size_t Idx = 0; Idx < Size; Idx++) {
3830b57cec5SDimitry Andric       Printf("CLEANSE[%d]: Trying to replace byte %zd of %zd\n", NumAttempts,
3840b57cec5SDimitry Andric              Idx, Size);
3850b57cec5SDimitry Andric       uint8_t OriginalByte = U[Idx];
3860b57cec5SDimitry Andric       if (ReplacementBytes.end() != std::find(ReplacementBytes.begin(),
3870b57cec5SDimitry Andric                                               ReplacementBytes.end(),
3880b57cec5SDimitry Andric                                               OriginalByte))
3890b57cec5SDimitry Andric         continue;
3900b57cec5SDimitry Andric       for (auto NewByte : ReplacementBytes) {
3910b57cec5SDimitry Andric         U[Idx] = NewByte;
3920b57cec5SDimitry Andric         WriteToFile(U, TmpFilePath);
3930b57cec5SDimitry Andric         auto ExitCode = ExecuteCommand(Cmd);
3940b57cec5SDimitry Andric         RemoveFile(TmpFilePath);
3950b57cec5SDimitry Andric         if (!ExitCode) {
3960b57cec5SDimitry Andric           U[Idx] = OriginalByte;
3970b57cec5SDimitry Andric         } else {
3980b57cec5SDimitry Andric           Changed = true;
3990b57cec5SDimitry Andric           Printf("CLEANSE: Replaced byte %zd with 0x%x\n", Idx, NewByte);
4000b57cec5SDimitry Andric           WriteToFile(U, OutputFilePath);
4010b57cec5SDimitry Andric           break;
4020b57cec5SDimitry Andric         }
4030b57cec5SDimitry Andric       }
4040b57cec5SDimitry Andric     }
4050b57cec5SDimitry Andric     if (!Changed) break;
4060b57cec5SDimitry Andric   }
4070b57cec5SDimitry Andric   return 0;
4080b57cec5SDimitry Andric }
4090b57cec5SDimitry Andric 
MinimizeCrashInput(const std::vector<std::string> & Args,const FuzzingOptions & Options)410349cc55cSDimitry Andric int MinimizeCrashInput(const std::vector<std::string> &Args,
4110b57cec5SDimitry Andric                        const FuzzingOptions &Options) {
4120b57cec5SDimitry Andric   if (Inputs->size() != 1) {
4130b57cec5SDimitry Andric     Printf("ERROR: -minimize_crash should be given one input file\n");
4140b57cec5SDimitry Andric     exit(1);
4150b57cec5SDimitry Andric   }
4160b57cec5SDimitry Andric   std::string InputFilePath = Inputs->at(0);
4170b57cec5SDimitry Andric   Command BaseCmd(Args);
4180b57cec5SDimitry Andric   BaseCmd.removeFlag("minimize_crash");
4190b57cec5SDimitry Andric   BaseCmd.removeFlag("exact_artifact_path");
4200b57cec5SDimitry Andric   assert(BaseCmd.hasArgument(InputFilePath));
4210b57cec5SDimitry Andric   BaseCmd.removeArgument(InputFilePath);
4220b57cec5SDimitry Andric   if (Flags.runs <= 0 && Flags.max_total_time == 0) {
4230b57cec5SDimitry Andric     Printf("INFO: you need to specify -runs=N or "
4240b57cec5SDimitry Andric            "-max_total_time=N with -minimize_crash=1\n"
4250b57cec5SDimitry Andric            "INFO: defaulting to -max_total_time=600\n");
4260b57cec5SDimitry Andric     BaseCmd.addFlag("max_total_time", "600");
4270b57cec5SDimitry Andric   }
4280b57cec5SDimitry Andric 
4290b57cec5SDimitry Andric   BaseCmd.combineOutAndErr();
4300b57cec5SDimitry Andric 
4310b57cec5SDimitry Andric   std::string CurrentFilePath = InputFilePath;
4320b57cec5SDimitry Andric   while (true) {
4330b57cec5SDimitry Andric     Unit U = FileToVector(CurrentFilePath);
4340b57cec5SDimitry Andric     Printf("CRASH_MIN: minimizing crash input: '%s' (%zd bytes)\n",
4350b57cec5SDimitry Andric            CurrentFilePath.c_str(), U.size());
4360b57cec5SDimitry Andric 
4370b57cec5SDimitry Andric     Command Cmd(BaseCmd);
4380b57cec5SDimitry Andric     Cmd.addArgument(CurrentFilePath);
4390b57cec5SDimitry Andric 
4405ffd83dbSDimitry Andric     Printf("CRASH_MIN: executing: %s\n", Cmd.toString().c_str());
4415ffd83dbSDimitry Andric     std::string CmdOutput;
4425ffd83dbSDimitry Andric     bool Success = ExecuteCommand(Cmd, &CmdOutput);
4435ffd83dbSDimitry Andric     if (Success) {
4440b57cec5SDimitry Andric       Printf("ERROR: the input %s did not crash\n", CurrentFilePath.c_str());
4450b57cec5SDimitry Andric       exit(1);
4460b57cec5SDimitry Andric     }
4470b57cec5SDimitry Andric     Printf("CRASH_MIN: '%s' (%zd bytes) caused a crash. Will try to minimize "
4480b57cec5SDimitry Andric            "it further\n",
4490b57cec5SDimitry Andric            CurrentFilePath.c_str(), U.size());
4505ffd83dbSDimitry Andric     auto DedupToken1 = GetDedupTokenFromCmdOutput(CmdOutput);
4510b57cec5SDimitry Andric     if (!DedupToken1.empty())
4520b57cec5SDimitry Andric       Printf("CRASH_MIN: DedupToken1: %s\n", DedupToken1.c_str());
4530b57cec5SDimitry Andric 
4540b57cec5SDimitry Andric     std::string ArtifactPath =
4550b57cec5SDimitry Andric         Flags.exact_artifact_path
4560b57cec5SDimitry Andric             ? Flags.exact_artifact_path
4570b57cec5SDimitry Andric             : Options.ArtifactPrefix + "minimized-from-" + Hash(U);
4580b57cec5SDimitry Andric     Cmd.addFlag("minimize_crash_internal_step", "1");
4590b57cec5SDimitry Andric     Cmd.addFlag("exact_artifact_path", ArtifactPath);
4605ffd83dbSDimitry Andric     Printf("CRASH_MIN: executing: %s\n", Cmd.toString().c_str());
4615ffd83dbSDimitry Andric     CmdOutput.clear();
4625ffd83dbSDimitry Andric     Success = ExecuteCommand(Cmd, &CmdOutput);
4635ffd83dbSDimitry Andric     Printf("%s", CmdOutput.c_str());
4645ffd83dbSDimitry Andric     if (Success) {
4650b57cec5SDimitry Andric       if (Flags.exact_artifact_path) {
4660b57cec5SDimitry Andric         CurrentFilePath = Flags.exact_artifact_path;
4670b57cec5SDimitry Andric         WriteToFile(U, CurrentFilePath);
4680b57cec5SDimitry Andric       }
46906c3fb27SDimitry Andric       Printf("CRASH_MIN: failed to minimize beyond %s (%zu bytes), exiting\n",
4700b57cec5SDimitry Andric              CurrentFilePath.c_str(), U.size());
4710b57cec5SDimitry Andric       break;
4720b57cec5SDimitry Andric     }
4735ffd83dbSDimitry Andric     auto DedupToken2 = GetDedupTokenFromCmdOutput(CmdOutput);
4740b57cec5SDimitry Andric     if (!DedupToken2.empty())
4750b57cec5SDimitry Andric       Printf("CRASH_MIN: DedupToken2: %s\n", DedupToken2.c_str());
4760b57cec5SDimitry Andric 
4770b57cec5SDimitry Andric     if (DedupToken1 != DedupToken2) {
4780b57cec5SDimitry Andric       if (Flags.exact_artifact_path) {
4790b57cec5SDimitry Andric         CurrentFilePath = Flags.exact_artifact_path;
4800b57cec5SDimitry Andric         WriteToFile(U, CurrentFilePath);
4810b57cec5SDimitry Andric       }
4820b57cec5SDimitry Andric       Printf("CRASH_MIN: mismatch in dedup tokens"
4830b57cec5SDimitry Andric              " (looks like a different bug). Won't minimize further\n");
4840b57cec5SDimitry Andric       break;
4850b57cec5SDimitry Andric     }
4860b57cec5SDimitry Andric 
4870b57cec5SDimitry Andric     CurrentFilePath = ArtifactPath;
4880b57cec5SDimitry Andric     Printf("*********************************\n");
4890b57cec5SDimitry Andric   }
4900b57cec5SDimitry Andric   return 0;
4910b57cec5SDimitry Andric }
4920b57cec5SDimitry Andric 
MinimizeCrashInputInternalStep(Fuzzer * F,InputCorpus * Corpus)4930b57cec5SDimitry Andric int MinimizeCrashInputInternalStep(Fuzzer *F, InputCorpus *Corpus) {
4940b57cec5SDimitry Andric   assert(Inputs->size() == 1);
4950b57cec5SDimitry Andric   std::string InputFilePath = Inputs->at(0);
4960b57cec5SDimitry Andric   Unit U = FileToVector(InputFilePath);
4970b57cec5SDimitry Andric   Printf("INFO: Starting MinimizeCrashInputInternalStep: %zd\n", U.size());
4980b57cec5SDimitry Andric   if (U.size() < 2) {
4990b57cec5SDimitry Andric     Printf("INFO: The input is small enough, exiting\n");
5000b57cec5SDimitry Andric     exit(0);
5010b57cec5SDimitry Andric   }
5020b57cec5SDimitry Andric   F->SetMaxInputLen(U.size());
5030b57cec5SDimitry Andric   F->SetMaxMutationLen(U.size() - 1);
5040b57cec5SDimitry Andric   F->MinimizeCrashLoop(U);
5050b57cec5SDimitry Andric   Printf("INFO: Done MinimizeCrashInputInternalStep, no crashes found\n");
5060b57cec5SDimitry Andric   exit(0);
5070b57cec5SDimitry Andric }
5080b57cec5SDimitry Andric 
Merge(Fuzzer * F,FuzzingOptions & Options,const std::vector<std::string> & Args,const std::vector<std::string> & Corpora,const char * CFPathOrNull)509349cc55cSDimitry Andric void Merge(Fuzzer *F, FuzzingOptions &Options,
510349cc55cSDimitry Andric            const std::vector<std::string> &Args,
511349cc55cSDimitry Andric            const std::vector<std::string> &Corpora, const char *CFPathOrNull) {
5120b57cec5SDimitry Andric   if (Corpora.size() < 2) {
5130b57cec5SDimitry Andric     Printf("INFO: Merge requires two or more corpus dirs\n");
5140b57cec5SDimitry Andric     exit(0);
5150b57cec5SDimitry Andric   }
5160b57cec5SDimitry Andric 
517349cc55cSDimitry Andric   std::vector<SizedFile> OldCorpus, NewCorpus;
5180b57cec5SDimitry Andric   GetSizedFilesFromDir(Corpora[0], &OldCorpus);
5190b57cec5SDimitry Andric   for (size_t i = 1; i < Corpora.size(); i++)
5200b57cec5SDimitry Andric     GetSizedFilesFromDir(Corpora[i], &NewCorpus);
5210b57cec5SDimitry Andric   std::sort(OldCorpus.begin(), OldCorpus.end());
5220b57cec5SDimitry Andric   std::sort(NewCorpus.begin(), NewCorpus.end());
5230b57cec5SDimitry Andric 
5245ffd83dbSDimitry Andric   std::string CFPath = CFPathOrNull ? CFPathOrNull : TempPath("Merge", ".txt");
525349cc55cSDimitry Andric   std::vector<std::string> NewFiles;
526349cc55cSDimitry Andric   std::set<uint32_t> NewFeatures, NewCov;
5270b57cec5SDimitry Andric   CrashResistantMerge(Args, OldCorpus, NewCorpus, &NewFiles, {}, &NewFeatures,
528349cc55cSDimitry Andric                       {}, &NewCov, CFPath, true, Flags.set_cover_merge);
5290b57cec5SDimitry Andric   for (auto &Path : NewFiles)
5300b57cec5SDimitry Andric     F->WriteToOutputCorpus(FileToVector(Path, Options.MaxLen));
5310b57cec5SDimitry Andric   // We are done, delete the control file if it was a temporary one.
5320b57cec5SDimitry Andric   if (!Flags.merge_control_file)
5330b57cec5SDimitry Andric     RemoveFile(CFPath);
5340b57cec5SDimitry Andric 
5350b57cec5SDimitry Andric   exit(0);
5360b57cec5SDimitry Andric }
5370b57cec5SDimitry Andric 
AnalyzeDictionary(Fuzzer * F,const std::vector<Unit> & Dict,UnitVector & Corpus)538349cc55cSDimitry Andric int AnalyzeDictionary(Fuzzer *F, const std::vector<Unit> &Dict,
5390b57cec5SDimitry Andric                       UnitVector &Corpus) {
54006c3fb27SDimitry Andric   Printf("Started dictionary minimization (up to %zu tests)\n",
5410b57cec5SDimitry Andric          Dict.size() * Corpus.size() * 2);
5420b57cec5SDimitry Andric 
5430b57cec5SDimitry Andric   // Scores and usage count for each dictionary unit.
544349cc55cSDimitry Andric   std::vector<int> Scores(Dict.size());
545349cc55cSDimitry Andric   std::vector<int> Usages(Dict.size());
5460b57cec5SDimitry Andric 
547349cc55cSDimitry Andric   std::vector<size_t> InitialFeatures;
548349cc55cSDimitry Andric   std::vector<size_t> ModifiedFeatures;
5490b57cec5SDimitry Andric   for (auto &C : Corpus) {
5500b57cec5SDimitry Andric     // Get coverage for the testcase without modifications.
5510b57cec5SDimitry Andric     F->ExecuteCallback(C.data(), C.size());
5520b57cec5SDimitry Andric     InitialFeatures.clear();
5530b57cec5SDimitry Andric     TPC.CollectFeatures([&](size_t Feature) {
5540b57cec5SDimitry Andric       InitialFeatures.push_back(Feature);
5550b57cec5SDimitry Andric     });
5560b57cec5SDimitry Andric 
5570b57cec5SDimitry Andric     for (size_t i = 0; i < Dict.size(); ++i) {
558349cc55cSDimitry Andric       std::vector<uint8_t> Data = C;
5590b57cec5SDimitry Andric       auto StartPos = std::search(Data.begin(), Data.end(),
5600b57cec5SDimitry Andric                                   Dict[i].begin(), Dict[i].end());
5610b57cec5SDimitry Andric       // Skip dictionary unit, if the testcase does not contain it.
5620b57cec5SDimitry Andric       if (StartPos == Data.end())
5630b57cec5SDimitry Andric         continue;
5640b57cec5SDimitry Andric 
5650b57cec5SDimitry Andric       ++Usages[i];
5660b57cec5SDimitry Andric       while (StartPos != Data.end()) {
5670b57cec5SDimitry Andric         // Replace all occurrences of dictionary unit in the testcase.
5680b57cec5SDimitry Andric         auto EndPos = StartPos + Dict[i].size();
5690b57cec5SDimitry Andric         for (auto It = StartPos; It != EndPos; ++It)
5700b57cec5SDimitry Andric           *It ^= 0xFF;
5710b57cec5SDimitry Andric 
5720b57cec5SDimitry Andric         StartPos = std::search(EndPos, Data.end(),
5730b57cec5SDimitry Andric                                Dict[i].begin(), Dict[i].end());
5740b57cec5SDimitry Andric       }
5750b57cec5SDimitry Andric 
5760b57cec5SDimitry Andric       // Get coverage for testcase with masked occurrences of dictionary unit.
5770b57cec5SDimitry Andric       F->ExecuteCallback(Data.data(), Data.size());
5780b57cec5SDimitry Andric       ModifiedFeatures.clear();
5790b57cec5SDimitry Andric       TPC.CollectFeatures([&](size_t Feature) {
5800b57cec5SDimitry Andric         ModifiedFeatures.push_back(Feature);
5810b57cec5SDimitry Andric       });
5820b57cec5SDimitry Andric 
5830b57cec5SDimitry Andric       if (InitialFeatures == ModifiedFeatures)
5840b57cec5SDimitry Andric         --Scores[i];
5850b57cec5SDimitry Andric       else
5860b57cec5SDimitry Andric         Scores[i] += 2;
5870b57cec5SDimitry Andric     }
5880b57cec5SDimitry Andric   }
5890b57cec5SDimitry Andric 
5900b57cec5SDimitry Andric   Printf("###### Useless dictionary elements. ######\n");
5910b57cec5SDimitry Andric   for (size_t i = 0; i < Dict.size(); ++i) {
5920b57cec5SDimitry Andric     // Dictionary units with positive score are treated as useful ones.
5930b57cec5SDimitry Andric     if (Scores[i] > 0)
5940b57cec5SDimitry Andric        continue;
5950b57cec5SDimitry Andric 
5960b57cec5SDimitry Andric     Printf("\"");
5970b57cec5SDimitry Andric     PrintASCII(Dict[i].data(), Dict[i].size(), "\"");
5980b57cec5SDimitry Andric     Printf(" # Score: %d, Used: %d\n", Scores[i], Usages[i]);
5990b57cec5SDimitry Andric   }
6000b57cec5SDimitry Andric   Printf("###### End of useless dictionary elements. ######\n");
6010b57cec5SDimitry Andric   return 0;
6020b57cec5SDimitry Andric }
6030b57cec5SDimitry Andric 
ParseSeedInuts(const char * seed_inputs)604349cc55cSDimitry Andric std::vector<std::string> ParseSeedInuts(const char *seed_inputs) {
6050b57cec5SDimitry Andric   // Parse -seed_inputs=file1,file2,... or -seed_inputs=@seed_inputs_file
606349cc55cSDimitry Andric   std::vector<std::string> Files;
6070b57cec5SDimitry Andric   if (!seed_inputs) return Files;
6080b57cec5SDimitry Andric   std::string SeedInputs;
6090b57cec5SDimitry Andric   if (Flags.seed_inputs[0] == '@')
6100b57cec5SDimitry Andric     SeedInputs = FileToString(Flags.seed_inputs + 1); // File contains list.
6110b57cec5SDimitry Andric   else
6120b57cec5SDimitry Andric     SeedInputs = Flags.seed_inputs; // seed_inputs contains the list.
6130b57cec5SDimitry Andric   if (SeedInputs.empty()) {
6140b57cec5SDimitry Andric     Printf("seed_inputs is empty or @file does not exist.\n");
6150b57cec5SDimitry Andric     exit(1);
6160b57cec5SDimitry Andric   }
6170b57cec5SDimitry Andric   // Parse SeedInputs.
6180b57cec5SDimitry Andric   size_t comma_pos = 0;
6190b57cec5SDimitry Andric   while ((comma_pos = SeedInputs.find_last_of(',')) != std::string::npos) {
6200b57cec5SDimitry Andric     Files.push_back(SeedInputs.substr(comma_pos + 1));
6210b57cec5SDimitry Andric     SeedInputs = SeedInputs.substr(0, comma_pos);
6220b57cec5SDimitry Andric   }
6230b57cec5SDimitry Andric   Files.push_back(SeedInputs);
6240b57cec5SDimitry Andric   return Files;
6250b57cec5SDimitry Andric }
6260b57cec5SDimitry Andric 
627349cc55cSDimitry Andric static std::vector<SizedFile>
ReadCorpora(const std::vector<std::string> & CorpusDirs,const std::vector<std::string> & ExtraSeedFiles)628349cc55cSDimitry Andric ReadCorpora(const std::vector<std::string> &CorpusDirs,
629349cc55cSDimitry Andric             const std::vector<std::string> &ExtraSeedFiles) {
630349cc55cSDimitry Andric   std::vector<SizedFile> SizedFiles;
6310b57cec5SDimitry Andric   size_t LastNumFiles = 0;
6320b57cec5SDimitry Andric   for (auto &Dir : CorpusDirs) {
6330b57cec5SDimitry Andric     GetSizedFilesFromDir(Dir, &SizedFiles);
6340b57cec5SDimitry Andric     Printf("INFO: % 8zd files found in %s\n", SizedFiles.size() - LastNumFiles,
6350b57cec5SDimitry Andric            Dir.c_str());
6360b57cec5SDimitry Andric     LastNumFiles = SizedFiles.size();
6370b57cec5SDimitry Andric   }
6380b57cec5SDimitry Andric   for (auto &File : ExtraSeedFiles)
6390b57cec5SDimitry Andric     if (auto Size = FileSize(File))
6400b57cec5SDimitry Andric       SizedFiles.push_back({File, Size});
6410b57cec5SDimitry Andric   return SizedFiles;
6420b57cec5SDimitry Andric }
6430b57cec5SDimitry Andric 
FuzzerDriver(int * argc,char *** argv,UserCallback Callback)6440b57cec5SDimitry Andric int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
6450b57cec5SDimitry Andric   using namespace fuzzer;
6460b57cec5SDimitry Andric   assert(argc && argv && "Argument pointers cannot be nullptr");
6470b57cec5SDimitry Andric   std::string Argv0((*argv)[0]);
6480b57cec5SDimitry Andric   EF = new ExternalFunctions();
6490b57cec5SDimitry Andric   if (EF->LLVMFuzzerInitialize)
6500b57cec5SDimitry Andric     EF->LLVMFuzzerInitialize(argc, argv);
6510b57cec5SDimitry Andric   if (EF->__msan_scoped_disable_interceptor_checks)
6520b57cec5SDimitry Andric     EF->__msan_scoped_disable_interceptor_checks();
653349cc55cSDimitry Andric   const std::vector<std::string> Args(*argv, *argv + *argc);
6540b57cec5SDimitry Andric   assert(!Args.empty());
6550b57cec5SDimitry Andric   ProgName = new std::string(Args[0]);
6560b57cec5SDimitry Andric   if (Argv0 != *ProgName) {
6570b57cec5SDimitry Andric     Printf("ERROR: argv[0] has been modified in LLVMFuzzerInitialize\n");
6580b57cec5SDimitry Andric     exit(1);
6590b57cec5SDimitry Andric   }
6600b57cec5SDimitry Andric   ParseFlags(Args, EF);
6610b57cec5SDimitry Andric   if (Flags.help) {
6620b57cec5SDimitry Andric     PrintHelp();
6630b57cec5SDimitry Andric     return 0;
6640b57cec5SDimitry Andric   }
6650b57cec5SDimitry Andric 
6660b57cec5SDimitry Andric   if (Flags.close_fd_mask & 2)
6670b57cec5SDimitry Andric     DupAndCloseStderr();
6680b57cec5SDimitry Andric   if (Flags.close_fd_mask & 1)
6690b57cec5SDimitry Andric     CloseStdout();
6700b57cec5SDimitry Andric 
6710b57cec5SDimitry Andric   if (Flags.jobs > 0 && Flags.workers == 0) {
6720b57cec5SDimitry Andric     Flags.workers = std::min(NumberOfCpuCores() / 2, Flags.jobs);
6730b57cec5SDimitry Andric     if (Flags.workers > 1)
6740b57cec5SDimitry Andric       Printf("Running %u workers\n", Flags.workers);
6750b57cec5SDimitry Andric   }
6760b57cec5SDimitry Andric 
6770b57cec5SDimitry Andric   if (Flags.workers > 0 && Flags.jobs > 0)
6780b57cec5SDimitry Andric     return RunInMultipleProcesses(Args, Flags.workers, Flags.jobs);
6790b57cec5SDimitry Andric 
6800b57cec5SDimitry Andric   FuzzingOptions Options;
6810b57cec5SDimitry Andric   Options.Verbosity = Flags.verbosity;
6820b57cec5SDimitry Andric   Options.MaxLen = Flags.max_len;
6830b57cec5SDimitry Andric   Options.LenControl = Flags.len_control;
684e8d8bef9SDimitry Andric   Options.KeepSeed = Flags.keep_seed;
6850b57cec5SDimitry Andric   Options.UnitTimeoutSec = Flags.timeout;
6860b57cec5SDimitry Andric   Options.ErrorExitCode = Flags.error_exitcode;
6870b57cec5SDimitry Andric   Options.TimeoutExitCode = Flags.timeout_exitcode;
6880b57cec5SDimitry Andric   Options.IgnoreTimeouts = Flags.ignore_timeouts;
6890b57cec5SDimitry Andric   Options.IgnoreOOMs = Flags.ignore_ooms;
6900b57cec5SDimitry Andric   Options.IgnoreCrashes = Flags.ignore_crashes;
6910b57cec5SDimitry Andric   Options.MaxTotalTimeSec = Flags.max_total_time;
6920b57cec5SDimitry Andric   Options.DoCrossOver = Flags.cross_over;
693e8d8bef9SDimitry Andric   Options.CrossOverUniformDist = Flags.cross_over_uniform_dist;
6940b57cec5SDimitry Andric   Options.MutateDepth = Flags.mutate_depth;
6950b57cec5SDimitry Andric   Options.ReduceDepth = Flags.reduce_depth;
6960b57cec5SDimitry Andric   Options.UseCounters = Flags.use_counters;
6970b57cec5SDimitry Andric   Options.UseMemmem = Flags.use_memmem;
6980b57cec5SDimitry Andric   Options.UseCmp = Flags.use_cmp;
6990b57cec5SDimitry Andric   Options.UseValueProfile = Flags.use_value_profile;
7000b57cec5SDimitry Andric   Options.Shrink = Flags.shrink;
7010b57cec5SDimitry Andric   Options.ReduceInputs = Flags.reduce_inputs;
7020b57cec5SDimitry Andric   Options.ShuffleAtStartUp = Flags.shuffle;
7030b57cec5SDimitry Andric   Options.PreferSmall = Flags.prefer_small;
7040b57cec5SDimitry Andric   Options.ReloadIntervalSec = Flags.reload;
7050b57cec5SDimitry Andric   Options.OnlyASCII = Flags.only_ascii;
7060b57cec5SDimitry Andric   Options.DetectLeaks = Flags.detect_leaks;
7070b57cec5SDimitry Andric   Options.PurgeAllocatorIntervalSec = Flags.purge_allocator_interval;
7080b57cec5SDimitry Andric   Options.TraceMalloc = Flags.trace_malloc;
7090b57cec5SDimitry Andric   Options.RssLimitMb = Flags.rss_limit_mb;
7100b57cec5SDimitry Andric   Options.MallocLimitMb = Flags.malloc_limit_mb;
7110b57cec5SDimitry Andric   if (!Options.MallocLimitMb)
7120b57cec5SDimitry Andric     Options.MallocLimitMb = Options.RssLimitMb;
7130b57cec5SDimitry Andric   if (Flags.runs >= 0)
7140b57cec5SDimitry Andric     Options.MaxNumberOfRuns = Flags.runs;
715e8d8bef9SDimitry Andric   if (!Inputs->empty() && !Flags.minimize_crash_internal_step) {
716e8d8bef9SDimitry Andric     // Ensure output corpus assumed to be the first arbitrary argument input
717e8d8bef9SDimitry Andric     // is not a path to an existing file.
718e8d8bef9SDimitry Andric     std::string OutputCorpusDir = (*Inputs)[0];
719e8d8bef9SDimitry Andric     if (!IsFile(OutputCorpusDir)) {
720e8d8bef9SDimitry Andric       Options.OutputCorpus = OutputCorpusDir;
721e8d8bef9SDimitry Andric       ValidateDirectoryExists(Options.OutputCorpus, Flags.create_missing_dirs);
722e8d8bef9SDimitry Andric     }
723e8d8bef9SDimitry Andric   }
7240b57cec5SDimitry Andric   Options.ReportSlowUnits = Flags.report_slow_units;
725e8d8bef9SDimitry Andric   if (Flags.artifact_prefix) {
7260b57cec5SDimitry Andric     Options.ArtifactPrefix = Flags.artifact_prefix;
727e8d8bef9SDimitry Andric 
728e8d8bef9SDimitry Andric     // Since the prefix could be a full path to a file name prefix, assume
729e8d8bef9SDimitry Andric     // that if the path ends with the platform's separator that a directory
730e8d8bef9SDimitry Andric     // is desired
731e8d8bef9SDimitry Andric     std::string ArtifactPathDir = Options.ArtifactPrefix;
732e8d8bef9SDimitry Andric     if (!IsSeparator(ArtifactPathDir[ArtifactPathDir.length() - 1])) {
733e8d8bef9SDimitry Andric       ArtifactPathDir = DirName(ArtifactPathDir);
734e8d8bef9SDimitry Andric     }
735e8d8bef9SDimitry Andric     ValidateDirectoryExists(ArtifactPathDir, Flags.create_missing_dirs);
736e8d8bef9SDimitry Andric   }
737e8d8bef9SDimitry Andric   if (Flags.exact_artifact_path) {
7380b57cec5SDimitry Andric     Options.ExactArtifactPath = Flags.exact_artifact_path;
739e8d8bef9SDimitry Andric     ValidateDirectoryExists(DirName(Options.ExactArtifactPath),
740e8d8bef9SDimitry Andric                             Flags.create_missing_dirs);
741e8d8bef9SDimitry Andric   }
742349cc55cSDimitry Andric   std::vector<Unit> Dictionary;
7430b57cec5SDimitry Andric   if (Flags.dict)
7440b57cec5SDimitry Andric     if (!ParseDictionaryFile(FileToString(Flags.dict), &Dictionary))
7450b57cec5SDimitry Andric       return 1;
7460b57cec5SDimitry Andric   if (Flags.verbosity > 0 && !Dictionary.empty())
7470b57cec5SDimitry Andric     Printf("Dictionary: %zd entries\n", Dictionary.size());
7480b57cec5SDimitry Andric   bool RunIndividualFiles = AllInputsAreFiles();
7490b57cec5SDimitry Andric   Options.SaveArtifacts =
7500b57cec5SDimitry Andric       !RunIndividualFiles || Flags.minimize_crash_internal_step;
7510b57cec5SDimitry Andric   Options.PrintNewCovPcs = Flags.print_pcs;
7520b57cec5SDimitry Andric   Options.PrintNewCovFuncs = Flags.print_funcs;
7530b57cec5SDimitry Andric   Options.PrintFinalStats = Flags.print_final_stats;
7540b57cec5SDimitry Andric   Options.PrintCorpusStats = Flags.print_corpus_stats;
7550b57cec5SDimitry Andric   Options.PrintCoverage = Flags.print_coverage;
756e8d8bef9SDimitry Andric   Options.PrintFullCoverage = Flags.print_full_coverage;
7570b57cec5SDimitry Andric   if (Flags.exit_on_src_pos)
7580b57cec5SDimitry Andric     Options.ExitOnSrcPos = Flags.exit_on_src_pos;
7590b57cec5SDimitry Andric   if (Flags.exit_on_item)
7600b57cec5SDimitry Andric     Options.ExitOnItem = Flags.exit_on_item;
7610b57cec5SDimitry Andric   if (Flags.focus_function)
7620b57cec5SDimitry Andric     Options.FocusFunction = Flags.focus_function;
7630b57cec5SDimitry Andric   if (Flags.data_flow_trace)
7640b57cec5SDimitry Andric     Options.DataFlowTrace = Flags.data_flow_trace;
765e8d8bef9SDimitry Andric   if (Flags.features_dir) {
7660b57cec5SDimitry Andric     Options.FeaturesDir = Flags.features_dir;
767e8d8bef9SDimitry Andric     ValidateDirectoryExists(Options.FeaturesDir, Flags.create_missing_dirs);
768e8d8bef9SDimitry Andric   }
769e8d8bef9SDimitry Andric   if (Flags.mutation_graph_file)
770e8d8bef9SDimitry Andric     Options.MutationGraphFile = Flags.mutation_graph_file;
7710b57cec5SDimitry Andric   if (Flags.collect_data_flow)
7720b57cec5SDimitry Andric     Options.CollectDataFlow = Flags.collect_data_flow;
7730b57cec5SDimitry Andric   if (Flags.stop_file)
7740b57cec5SDimitry Andric     Options.StopFile = Flags.stop_file;
7755ffd83dbSDimitry Andric   Options.Entropic = Flags.entropic;
7765ffd83dbSDimitry Andric   Options.EntropicFeatureFrequencyThreshold =
7775ffd83dbSDimitry Andric       (size_t)Flags.entropic_feature_frequency_threshold;
7785ffd83dbSDimitry Andric   Options.EntropicNumberOfRarestFeatures =
7795ffd83dbSDimitry Andric       (size_t)Flags.entropic_number_of_rarest_features;
780e8d8bef9SDimitry Andric   Options.EntropicScalePerExecTime = Flags.entropic_scale_per_exec_time;
781e8d8bef9SDimitry Andric   if (!Options.FocusFunction.empty())
782e8d8bef9SDimitry Andric     Options.Entropic = false; // FocusFunction overrides entropic scheduling.
783e8d8bef9SDimitry Andric   if (Options.Entropic)
78406c3fb27SDimitry Andric     Printf("INFO: Running with entropic power schedule (0x%zX, %zu).\n",
7855ffd83dbSDimitry Andric            Options.EntropicFeatureFrequencyThreshold,
7865ffd83dbSDimitry Andric            Options.EntropicNumberOfRarestFeatures);
7875ffd83dbSDimitry Andric   struct EntropicOptions Entropic;
7885ffd83dbSDimitry Andric   Entropic.Enabled = Options.Entropic;
7895ffd83dbSDimitry Andric   Entropic.FeatureFrequencyThreshold =
7905ffd83dbSDimitry Andric       Options.EntropicFeatureFrequencyThreshold;
7915ffd83dbSDimitry Andric   Entropic.NumberOfRarestFeatures = Options.EntropicNumberOfRarestFeatures;
792e8d8bef9SDimitry Andric   Entropic.ScalePerExecTime = Options.EntropicScalePerExecTime;
7930b57cec5SDimitry Andric 
7940b57cec5SDimitry Andric   unsigned Seed = Flags.seed;
7950b57cec5SDimitry Andric   // Initialize Seed.
7960b57cec5SDimitry Andric   if (Seed == 0)
797fe6060f1SDimitry Andric     Seed = static_cast<unsigned>(
798fe6060f1SDimitry Andric         std::chrono::system_clock::now().time_since_epoch().count() + GetPid());
7990b57cec5SDimitry Andric   if (Flags.verbosity)
8000b57cec5SDimitry Andric     Printf("INFO: Seed: %u\n", Seed);
8010b57cec5SDimitry Andric 
80206c3fb27SDimitry Andric   if (Flags.collect_data_flow && Flags.data_flow_trace && !Flags.fork &&
803349cc55cSDimitry Andric       !(Flags.merge || Flags.set_cover_merge)) {
8040b57cec5SDimitry Andric     if (RunIndividualFiles)
8050b57cec5SDimitry Andric       return CollectDataFlow(Flags.collect_data_flow, Flags.data_flow_trace,
8060b57cec5SDimitry Andric                         ReadCorpora({}, *Inputs));
8070b57cec5SDimitry Andric     else
8080b57cec5SDimitry Andric       return CollectDataFlow(Flags.collect_data_flow, Flags.data_flow_trace,
8090b57cec5SDimitry Andric                         ReadCorpora(*Inputs, {}));
8100b57cec5SDimitry Andric   }
8110b57cec5SDimitry Andric 
8120b57cec5SDimitry Andric   Random Rand(Seed);
8130b57cec5SDimitry Andric   auto *MD = new MutationDispatcher(Rand, Options);
8145ffd83dbSDimitry Andric   auto *Corpus = new InputCorpus(Options.OutputCorpus, Entropic);
8150b57cec5SDimitry Andric   auto *F = new Fuzzer(Callback, *Corpus, *MD, Options);
8160b57cec5SDimitry Andric 
8170b57cec5SDimitry Andric   for (auto &U: Dictionary)
8180b57cec5SDimitry Andric     if (U.size() <= Word::GetMaxSize())
8190b57cec5SDimitry Andric       MD->AddWordToManualDictionary(Word(U.data(), U.size()));
8200b57cec5SDimitry Andric 
821480093f4SDimitry Andric       // Threads are only supported by Chrome. Don't use them with emscripten
822480093f4SDimitry Andric       // for now.
823480093f4SDimitry Andric #if !LIBFUZZER_EMSCRIPTEN
8240b57cec5SDimitry Andric   StartRssThread(F, Flags.rss_limit_mb);
825480093f4SDimitry Andric #endif // LIBFUZZER_EMSCRIPTEN
8260b57cec5SDimitry Andric 
8270b57cec5SDimitry Andric   Options.HandleAbrt = Flags.handle_abrt;
828e8d8bef9SDimitry Andric   Options.HandleAlrm = !Flags.minimize_crash;
8290b57cec5SDimitry Andric   Options.HandleBus = Flags.handle_bus;
8300b57cec5SDimitry Andric   Options.HandleFpe = Flags.handle_fpe;
8310b57cec5SDimitry Andric   Options.HandleIll = Flags.handle_ill;
8320b57cec5SDimitry Andric   Options.HandleInt = Flags.handle_int;
8330b57cec5SDimitry Andric   Options.HandleSegv = Flags.handle_segv;
8340b57cec5SDimitry Andric   Options.HandleTerm = Flags.handle_term;
8350b57cec5SDimitry Andric   Options.HandleXfsz = Flags.handle_xfsz;
8360b57cec5SDimitry Andric   Options.HandleUsr1 = Flags.handle_usr1;
8370b57cec5SDimitry Andric   Options.HandleUsr2 = Flags.handle_usr2;
838e8d8bef9SDimitry Andric   Options.HandleWinExcept = Flags.handle_winexcept;
839e8d8bef9SDimitry Andric 
8400b57cec5SDimitry Andric   SetSignalHandler(Options);
8410b57cec5SDimitry Andric 
8420b57cec5SDimitry Andric   std::atexit(Fuzzer::StaticExitCallback);
8430b57cec5SDimitry Andric 
8440b57cec5SDimitry Andric   if (Flags.minimize_crash)
8450b57cec5SDimitry Andric     return MinimizeCrashInput(Args, Options);
8460b57cec5SDimitry Andric 
8470b57cec5SDimitry Andric   if (Flags.minimize_crash_internal_step)
8480b57cec5SDimitry Andric     return MinimizeCrashInputInternalStep(F, Corpus);
8490b57cec5SDimitry Andric 
8500b57cec5SDimitry Andric   if (Flags.cleanse_crash)
8510b57cec5SDimitry Andric     return CleanseCrashInput(Args, Options);
8520b57cec5SDimitry Andric 
8530b57cec5SDimitry Andric   if (RunIndividualFiles) {
8540b57cec5SDimitry Andric     Options.SaveArtifacts = false;
8550b57cec5SDimitry Andric     int Runs = std::max(1, Flags.runs);
8560b57cec5SDimitry Andric     Printf("%s: Running %zd inputs %d time(s) each.\n", ProgName->c_str(),
8570b57cec5SDimitry Andric            Inputs->size(), Runs);
8580b57cec5SDimitry Andric     for (auto &Path : *Inputs) {
8590b57cec5SDimitry Andric       auto StartTime = system_clock::now();
8600b57cec5SDimitry Andric       Printf("Running: %s\n", Path.c_str());
8610b57cec5SDimitry Andric       for (int Iter = 0; Iter < Runs; Iter++)
8620b57cec5SDimitry Andric         RunOneTest(F, Path.c_str(), Options.MaxLen);
8630b57cec5SDimitry Andric       auto StopTime = system_clock::now();
8640b57cec5SDimitry Andric       auto MS = duration_cast<milliseconds>(StopTime - StartTime).count();
86506c3fb27SDimitry Andric       Printf("Executed %s in %ld ms\n", Path.c_str(), (long)MS);
8660b57cec5SDimitry Andric     }
8670b57cec5SDimitry Andric     Printf("***\n"
8680b57cec5SDimitry Andric            "*** NOTE: fuzzing was not performed, you have only\n"
8690b57cec5SDimitry Andric            "***       executed the target code on a fixed set of inputs.\n"
8700b57cec5SDimitry Andric            "***\n");
8710b57cec5SDimitry Andric     F->PrintFinalStats();
8720b57cec5SDimitry Andric     exit(0);
8730b57cec5SDimitry Andric   }
8740b57cec5SDimitry Andric 
875349cc55cSDimitry Andric   Options.ForkCorpusGroups = Flags.fork_corpus_groups;
8760b57cec5SDimitry Andric   if (Flags.fork)
8770b57cec5SDimitry Andric     FuzzWithFork(F->GetMD().GetRand(), Options, Args, *Inputs, Flags.fork);
8780b57cec5SDimitry Andric 
879349cc55cSDimitry Andric   if (Flags.merge || Flags.set_cover_merge)
8800b57cec5SDimitry Andric     Merge(F, Options, Args, *Inputs, Flags.merge_control_file);
8810b57cec5SDimitry Andric 
8820b57cec5SDimitry Andric   if (Flags.merge_inner) {
8830b57cec5SDimitry Andric     const size_t kDefaultMaxMergeLen = 1 << 20;
8840b57cec5SDimitry Andric     if (Options.MaxLen == 0)
8850b57cec5SDimitry Andric       F->SetMaxInputLen(kDefaultMaxMergeLen);
8860b57cec5SDimitry Andric     assert(Flags.merge_control_file);
887349cc55cSDimitry Andric     F->CrashResistantMergeInternalStep(Flags.merge_control_file,
888349cc55cSDimitry Andric                                        !strncmp(Flags.merge_inner, "2", 1));
8890b57cec5SDimitry Andric     exit(0);
8900b57cec5SDimitry Andric   }
8910b57cec5SDimitry Andric 
8920b57cec5SDimitry Andric   if (Flags.analyze_dict) {
8930b57cec5SDimitry Andric     size_t MaxLen = INT_MAX;  // Large max length.
8940b57cec5SDimitry Andric     UnitVector InitialCorpus;
8950b57cec5SDimitry Andric     for (auto &Inp : *Inputs) {
8960b57cec5SDimitry Andric       Printf("Loading corpus dir: %s\n", Inp.c_str());
8970b57cec5SDimitry Andric       ReadDirToVectorOfUnits(Inp.c_str(), &InitialCorpus, nullptr,
8980b57cec5SDimitry Andric                              MaxLen, /*ExitOnError=*/false);
8990b57cec5SDimitry Andric     }
9000b57cec5SDimitry Andric 
9010b57cec5SDimitry Andric     if (Dictionary.empty() || Inputs->empty()) {
9020b57cec5SDimitry Andric       Printf("ERROR: can't analyze dict without dict and corpus provided\n");
9030b57cec5SDimitry Andric       return 1;
9040b57cec5SDimitry Andric     }
9050b57cec5SDimitry Andric     if (AnalyzeDictionary(F, Dictionary, InitialCorpus)) {
9060b57cec5SDimitry Andric       Printf("Dictionary analysis failed\n");
9070b57cec5SDimitry Andric       exit(1);
9080b57cec5SDimitry Andric     }
9090b57cec5SDimitry Andric     Printf("Dictionary analysis succeeded\n");
9100b57cec5SDimitry Andric     exit(0);
9110b57cec5SDimitry Andric   }
9120b57cec5SDimitry Andric 
9130b57cec5SDimitry Andric   auto CorporaFiles = ReadCorpora(*Inputs, ParseSeedInuts(Flags.seed_inputs));
9140b57cec5SDimitry Andric   F->Loop(CorporaFiles);
9150b57cec5SDimitry Andric 
9160b57cec5SDimitry Andric   if (Flags.verbosity)
9170b57cec5SDimitry Andric     Printf("Done %zd runs in %zd second(s)\n", F->getTotalNumberOfRuns(),
9180b57cec5SDimitry Andric            F->secondsSinceProcessStartUp());
9190b57cec5SDimitry Andric   F->PrintFinalStats();
9200b57cec5SDimitry Andric 
9210b57cec5SDimitry Andric   exit(0);  // Don't let F destroy itself.
9220b57cec5SDimitry Andric }
9230b57cec5SDimitry Andric 
924e8d8bef9SDimitry Andric extern "C" ATTRIBUTE_INTERFACE int
LLVMFuzzerRunDriver(int * argc,char *** argv,int (* UserCb)(const uint8_t * Data,size_t Size))925e8d8bef9SDimitry Andric LLVMFuzzerRunDriver(int *argc, char ***argv,
926e8d8bef9SDimitry Andric                     int (*UserCb)(const uint8_t *Data, size_t Size)) {
927e8d8bef9SDimitry Andric   return FuzzerDriver(argc, argv, UserCb);
928e8d8bef9SDimitry Andric }
929e8d8bef9SDimitry Andric 
9300b57cec5SDimitry Andric // Storage for global ExternalFunctions object.
9310b57cec5SDimitry Andric ExternalFunctions *EF = nullptr;
9320b57cec5SDimitry Andric 
9330b57cec5SDimitry Andric }  // namespace fuzzer
934