Index: compiler-rt/lib/fuzzer/FuzzerDriver.cpp =================================================================== --- compiler-rt/lib/fuzzer/FuzzerDriver.cpp +++ compiler-rt/lib/fuzzer/FuzzerDriver.cpp @@ -41,7 +41,7 @@ #endif #else extern "C" __attribute__((used)) void __libfuzzer_is_present() {} -#endif // LIBFUZZER_MSVC +#endif // LIBFUZZER_MSVC namespace fuzzer { @@ -68,14 +68,14 @@ } Flags; static const FlagDescription FlagDescriptions[]{ -#define FUZZER_DEPRECATED_FLAG(Name) \ +#define FUZZER_DEPRECATED_FLAG(Name) \ {#Name, "Deprecated; don't use", 0, nullptr, nullptr, nullptr}, -#define FUZZER_FLAG_INT(Name, Default, Description) \ +#define FUZZER_FLAG_INT(Name, Default, Description) \ {#Name, Description, Default, &Flags.Name, nullptr, nullptr}, -#define FUZZER_FLAG_UNSIGNED(Name, Default, Description) \ - {#Name, Description, static_cast(Default), \ +#define FUZZER_FLAG_UNSIGNED(Name, Default, Description) \ + {#Name, Description, static_cast(Default), \ nullptr, nullptr, &Flags.Name}, -#define FUZZER_FLAG_STRING(Name, Description) \ +#define FUZZER_FLAG_STRING(Name, Description) \ {#Name, Description, 0, nullptr, &Flags.Name, nullptr}, #include "FuzzerFlags.def" #undef FUZZER_DEPRECATED_FLAG @@ -106,15 +106,16 @@ for (size_t F = 0; F < kNumFlags; F++) { const auto &D = FlagDescriptions[F]; - if (strstr(D.Description, "internal flag") == D.Description) continue; + if (strstr(D.Description, "internal flag") == D.Description) + continue; Printf(" %s", D.Name); - for (size_t i = 0, n = MaxFlagLen - strlen(D.Name); i < n; i++) Printf(" "); + for (size_t i = 0, n = MaxFlagLen - strlen(D.Name); i < n; i++) + Printf(" "); Printf("\t"); Printf("%d\t%s\n", D.Default, D.Description); } - Printf( - "\nFlags starting with '--' will be ignored and " - "will be passed verbatim to subprocesses.\n"); + Printf("\nFlags starting with '--' will be ignored and " + "will be passed verbatim to subprocesses.\n"); } static const char *FlagValue(const char *Param, const char *Name) { @@ -135,14 +136,16 @@ } for (size_t i = 0; Str[i]; i++) { char Ch = Str[i]; - if (Ch < '0' || Ch > '9') return Res; + if (Ch < '0' || Ch > '9') + return Res; Res = Res * 10 + (Ch - '0'); } return Res * Sign; } static bool ParseOneFlag(const char *Param) { - if (Param[0] != '-') return false; + if (Param[0] != '-') + return false; if (Param[1] == '-') { static bool PrintedWarning = false; if (!PrintedWarning) { @@ -161,27 +164,29 @@ if (FlagDescriptions[F].IntFlag) { auto Val = MyStol(Str); *FlagDescriptions[F].IntFlag = static_cast(Val); - if (Flags.verbosity >= 2) Printf("Flag: %s %d\n", Name, Val); + if (Flags.verbosity >= 2) + Printf("Flag: %s %d\n", Name, Val); return true; } else if (FlagDescriptions[F].UIntFlag) { auto Val = std::stoul(Str); *FlagDescriptions[F].UIntFlag = static_cast(Val); - if (Flags.verbosity >= 2) Printf("Flag: %s %u\n", Name, Val); + if (Flags.verbosity >= 2) + Printf("Flag: %s %u\n", Name, Val); return true; } else if (FlagDescriptions[F].StrFlag) { *FlagDescriptions[F].StrFlag = Str; - if (Flags.verbosity >= 2) Printf("Flag: %s %s\n", Name, Str); + if (Flags.verbosity >= 2) + Printf("Flag: %s %s\n", Name, Str); return true; - } else { // Deprecated flag. + } else { // Deprecated flag. Printf("Flag: %s: deprecated, don't use\n", Name); return true; } } } - Printf( - "\n\nWARNING: unrecognized flag '%s'; " - "use -help=1 to list all flags\n\n", - Param); + Printf("\n\nWARNING: unrecognized flag '%s'; " + "use -help=1 to list all flags\n\n", + Param); return true; } @@ -194,22 +199,23 @@ if (FlagDescriptions[F].UIntFlag) *FlagDescriptions[F].UIntFlag = static_cast(FlagDescriptions[F].Default); - if (FlagDescriptions[F].StrFlag) *FlagDescriptions[F].StrFlag = nullptr; + if (FlagDescriptions[F].StrFlag) + *FlagDescriptions[F].StrFlag = nullptr; } // Disable len_control by default, if LLVMFuzzerCustomMutator is used. if (EF->LLVMFuzzerCustomMutator) { Flags.len_control = 0; - Printf( - "INFO: found LLVMFuzzerCustomMutator (%p). " - "Disabling -len_control by default.\n", - EF->LLVMFuzzerCustomMutator); + Printf("INFO: found LLVMFuzzerCustomMutator (%p). " + "Disabling -len_control by default.\n", + EF->LLVMFuzzerCustomMutator); } Inputs = new Vector; for (size_t A = 1; A < Args.size(); A++) { if (ParseOneFlag(Args[A].c_str())) { - if (Flags.ignore_remaining_args) break; + if (Flags.ignore_remaining_args) + break; continue; } Inputs->push_back(Args[A]); @@ -230,7 +236,8 @@ unsigned NumJobs, std::atomic *HasErrors) { while (true) { unsigned C = (*Counter)++; - if (C >= NumJobs) break; + if (C >= NumJobs) + break; std::string Log = "fuzz-" + std::to_string(C) + ".log"; Command Cmd(BaseCmd); Cmd.setOutputFile(Log); @@ -240,7 +247,8 @@ Printf("%s\n", CommandLine.c_str()); } int ExitCode = ExecuteCommand(Cmd); - if (ExitCode != 0) *HasErrors = true; + if (ExitCode != 0) + *HasErrors = true; std::lock_guard Lock(Mu); Printf("================== Job %u exited with exit code %d ============\n", C, ExitCode); @@ -255,7 +263,8 @@ exit(1); } - if (IsDirectory(Path)) return; + if (IsDirectory(Path)) + return; if (CreateDirectory) { if (!MkDirRecursive(Path)) { @@ -273,7 +282,8 @@ const char *X2) { std::string Cmd; for (auto &S : Args) { - if (FlagValue(S.c_str(), X1) || FlagValue(S.c_str(), X2)) continue; + if (FlagValue(S.c_str(), X1) || FlagValue(S.c_str(), X2)) + continue; Cmd += S + " "; } return Cmd; @@ -292,7 +302,8 @@ for (unsigned i = 0; i < NumWorkers; i++) V.push_back(std::thread(WorkerThread, std::ref(Cmd), &Counter, NumJobs, &HasErrors)); - for (auto &T : V) T.join(); + for (auto &T : V) + T.join(); return HasErrors ? 1 : 0; } @@ -300,19 +311,22 @@ while (true) { SleepSeconds(1); size_t Peak = GetPeakRSSMb(); - if (Peak > RssLimitMb) F->RssLimitCallback(); + if (Peak > RssLimitMb) + F->RssLimitCallback(); } } static void StartRssThread(Fuzzer *F, size_t RssLimitMb) { - if (!RssLimitMb) return; + if (!RssLimitMb) + return; std::thread T(RssThread, F, RssLimitMb); T.detach(); } int RunOneTest(Fuzzer *F, const char *InputFilePath, size_t MaxLen) { Unit U = FileToVector(InputFilePath); - if (MaxLen && MaxLen < U.size()) U.resize(MaxLen); + if (MaxLen && MaxLen < U.size()) + U.resize(MaxLen); F->ExecuteCallback(U.data(), U.size()); if (Flags.print_full_coverage) { // Leak detection is not needed when collecting full coverage data. @@ -324,26 +338,29 @@ } static bool AllInputsAreFiles() { - if (Inputs->empty()) return false; + if (Inputs->empty()) + return false; for (auto &Path : *Inputs) - if (!IsFile(Path)) return false; + if (!IsFile(Path)) + return false; return true; } static std::string GetDedupTokenFromCmdOutput(const std::string &S) { auto Beg = S.find("DEDUP_TOKEN:"); - if (Beg == std::string::npos) return ""; + if (Beg == std::string::npos) + return ""; auto End = S.find('\n', Beg); - if (End == std::string::npos) return ""; + if (End == std::string::npos) + return ""; return S.substr(Beg, End - Beg); } int CleanseCrashInput(const Vector &Args, const FuzzingOptions &Options) { if (Inputs->size() != 1 || !Flags.exact_artifact_path) { - Printf( - "ERROR: -cleanse_crash should be given one input file and" - " -exact_artifact_path\n"); + Printf("ERROR: -cleanse_crash should be given one input file and" + " -exact_artifact_path\n"); exit(1); } std::string InputFilePath = Inputs->at(0); @@ -389,7 +406,8 @@ } } } - if (!Changed) break; + if (!Changed) + break; } return 0; } @@ -407,10 +425,9 @@ assert(BaseCmd.hasArgument(InputFilePath)); BaseCmd.removeArgument(InputFilePath); if (Flags.runs <= 0 && Flags.max_total_time == 0) { - Printf( - "INFO: you need to specify -runs=N or " - "-max_total_time=N with -minimize_crash=1\n" - "INFO: defaulting to -max_total_time=600\n"); + Printf("INFO: you need to specify -runs=N or " + "-max_total_time=N with -minimize_crash=1\n" + "INFO: defaulting to -max_total_time=600\n"); BaseCmd.addFlag("max_total_time", "600"); } @@ -432,10 +449,9 @@ Printf("ERROR: the input %s did not crash\n", CurrentFilePath.c_str()); exit(1); } - Printf( - "CRASH_MIN: '%s' (%zd bytes) caused a crash. Will try to minimize " - "it further\n", - CurrentFilePath.c_str(), U.size()); + Printf("CRASH_MIN: '%s' (%zd bytes) caused a crash. Will try to minimize " + "it further\n", + CurrentFilePath.c_str(), U.size()); auto DedupToken1 = GetDedupTokenFromCmdOutput(CmdOutput); if (!DedupToken1.empty()) Printf("CRASH_MIN: DedupToken1: %s\n", DedupToken1.c_str()); @@ -468,9 +484,8 @@ CurrentFilePath = Flags.exact_artifact_path; WriteToFile(U, CurrentFilePath); } - Printf( - "CRASH_MIN: mismatch in dedup tokens" - " (looks like a different bug). Won't minimize further\n"); + Printf("CRASH_MIN: mismatch in dedup tokens" + " (looks like a different bug). Won't minimize further\n"); break; } @@ -519,7 +534,8 @@ for (auto &Path : NewFiles) F->WriteToOutputCorpus(FileToVector(Path, Options.MaxLen)); // We are done, delete the control file if it was a temporary one. - if (!Flags.merge_control_file) RemoveFile(CFPath); + if (!Flags.merge_control_file) + RemoveFile(CFPath); exit(0); } @@ -546,13 +562,15 @@ auto StartPos = std::search(Data.begin(), Data.end(), Dict[i].begin(), Dict[i].end()); // Skip dictionary unit, if the testcase does not contain it. - if (StartPos == Data.end()) continue; + if (StartPos == Data.end()) + continue; ++Usages[i]; while (StartPos != Data.end()) { // Replace all occurrences of dictionary unit in the testcase. auto EndPos = StartPos + Dict[i].size(); - for (auto It = StartPos; It != EndPos; ++It) *It ^= 0xFF; + for (auto It = StartPos; It != EndPos; ++It) + *It ^= 0xFF; StartPos = std::search(EndPos, Data.end(), Dict[i].begin(), Dict[i].end()); @@ -574,7 +592,8 @@ Printf("###### Useless dictionary elements. ######\n"); for (size_t i = 0; i < Dict.size(); ++i) { // Dictionary units with positive score are treated as useful ones. - if (Scores[i] > 0) continue; + if (Scores[i] > 0) + continue; Printf("\""); PrintASCII(Dict[i].data(), Dict[i].size(), "\""); @@ -587,12 +606,13 @@ Vector ParseSeedInuts(const char *seed_inputs) { // Parse -seed_inputs=file1,file2,... or -seed_inputs=@seed_inputs_file Vector Files; - if (!seed_inputs) return Files; + if (!seed_inputs) + return Files; std::string SeedInputs; if (Flags.seed_inputs[0] == '@') - SeedInputs = FileToString(Flags.seed_inputs + 1); // File contains list. + SeedInputs = FileToString(Flags.seed_inputs + 1); // File contains list. else - SeedInputs = Flags.seed_inputs; // seed_inputs contains the list. + SeedInputs = Flags.seed_inputs; // seed_inputs contains the list. if (SeedInputs.empty()) { Printf("seed_inputs is empty or @file does not exist.\n"); exit(1); @@ -607,9 +627,9 @@ return Files; } -static Vector ReadCorpora( - const Vector &CorpusDirs, - const Vector &ExtraSeedFiles) { +static Vector +ReadCorpora(const Vector &CorpusDirs, + const Vector &ExtraSeedFiles) { Vector SizedFiles; size_t LastNumFiles = 0; for (auto &Dir : CorpusDirs) { @@ -619,7 +639,8 @@ LastNumFiles = SizedFiles.size(); } for (auto &File : ExtraSeedFiles) - if (auto Size = FileSize(File)) SizedFiles.push_back({File, Size}); + if (auto Size = FileSize(File)) + SizedFiles.push_back({File, Size}); return SizedFiles; } @@ -628,7 +649,8 @@ assert(argc && argv && "Argument pointers cannot be nullptr"); std::string Argv0((*argv)[0]); EF = new ExternalFunctions(); - if (EF->LLVMFuzzerInitialize) EF->LLVMFuzzerInitialize(argc, argv); + if (EF->LLVMFuzzerInitialize) + EF->LLVMFuzzerInitialize(argc, argv); if (EF->__msan_scoped_disable_interceptor_checks) EF->__msan_scoped_disable_interceptor_checks(); const Vector Args(*argv, *argv + *argc); @@ -644,12 +666,15 @@ return 0; } - if (Flags.close_fd_mask & 2) DupAndCloseStderr(); - if (Flags.close_fd_mask & 1) CloseStdout(); + if (Flags.close_fd_mask & 2) + DupAndCloseStderr(); + if (Flags.close_fd_mask & 1) + CloseStdout(); if (Flags.jobs > 0 && Flags.workers == 0) { Flags.workers = std::min(NumberOfCpuCores() / 2, Flags.jobs); - if (Flags.workers > 1) Printf("Running %u workers\n", Flags.workers); + if (Flags.workers > 1) + Printf("Running %u workers\n", Flags.workers); } if (Flags.workers > 0 && Flags.jobs > 0) @@ -686,8 +711,10 @@ Options.TraceMalloc = Flags.trace_malloc; Options.RssLimitMb = Flags.rss_limit_mb; Options.MallocLimitMb = Flags.malloc_limit_mb; - if (!Options.MallocLimitMb) Options.MallocLimitMb = Options.RssLimitMb; - if (Flags.runs >= 0) Options.MaxNumberOfRuns = Flags.runs; + if (!Options.MallocLimitMb) + Options.MallocLimitMb = Options.RssLimitMb; + if (Flags.runs >= 0) + Options.MaxNumberOfRuns = Flags.runs; if (!Inputs->empty() && !Flags.minimize_crash_internal_step) { // Ensure output corpus assumed to be the first arbitrary argument input // is not a path to an existing file. @@ -717,7 +744,8 @@ } Vector Dictionary; if (Flags.dict) - if (!ParseDictionaryFile(FileToString(Flags.dict), &Dictionary)) return 1; + if (!ParseDictionaryFile(FileToString(Flags.dict), &Dictionary)) + return 1; if (Flags.verbosity > 0 && !Dictionary.empty()) Printf("Dictionary: %zd entries\n", Dictionary.size()); bool RunIndividualFiles = AllInputsAreFiles(); @@ -729,10 +757,14 @@ Options.PrintCorpusStats = Flags.print_corpus_stats; Options.PrintCoverage = Flags.print_coverage; Options.PrintFullCoverage = Flags.print_full_coverage; - if (Flags.exit_on_src_pos) Options.ExitOnSrcPos = Flags.exit_on_src_pos; - if (Flags.exit_on_item) Options.ExitOnItem = Flags.exit_on_item; - if (Flags.focus_function) Options.FocusFunction = Flags.focus_function; - if (Flags.data_flow_trace) Options.DataFlowTrace = Flags.data_flow_trace; + if (Flags.exit_on_src_pos) + Options.ExitOnSrcPos = Flags.exit_on_src_pos; + if (Flags.exit_on_item) + Options.ExitOnItem = Flags.exit_on_item; + if (Flags.focus_function) + Options.FocusFunction = Flags.focus_function; + if (Flags.data_flow_trace) + Options.DataFlowTrace = Flags.data_flow_trace; if (Flags.features_dir) { Options.FeaturesDir = Flags.features_dir; ValidateDirectoryExists(Options.FeaturesDir, Flags.create_missing_dirs); @@ -741,7 +773,8 @@ Options.MutationGraphFile = Flags.mutation_graph_file; if (Flags.collect_data_flow) Options.CollectDataFlow = Flags.collect_data_flow; - if (Flags.stop_file) Options.StopFile = Flags.stop_file; + if (Flags.stop_file) + Options.StopFile = Flags.stop_file; Options.Entropic = Flags.entropic; Options.EntropicFeatureFrequencyThreshold = (size_t)Flags.entropic_feature_frequency_threshold; @@ -749,7 +782,7 @@ (size_t)Flags.entropic_number_of_rarest_features; Options.EntropicScalePerExecTime = Flags.entropic_scale_per_exec_time; if (!Options.FocusFunction.empty()) - Options.Entropic = false; // FocusFunction overrides entropic scheduling. + Options.Entropic = false; // FocusFunction overrides entropic scheduling. if (Options.Entropic) Printf("INFO: Running with entropic power schedule (0x%X, %d).\n", Options.EntropicFeatureFrequencyThreshold, @@ -766,7 +799,8 @@ if (Seed == 0) Seed = static_cast( std::chrono::system_clock::now().time_since_epoch().count() + GetPid()); - if (Flags.verbosity) Printf("INFO: Seed: %u\n", Seed); + if (Flags.verbosity) + Printf("INFO: Seed: %u\n", Seed); if (Flags.collect_data_flow && !Flags.fork && !Flags.merge) { if (RunIndividualFiles) @@ -790,7 +824,7 @@ // for now. #if !LIBFUZZER_EMSCRIPTEN StartRssThread(F, Flags.rss_limit_mb); -#endif // LIBFUZZER_EMSCRIPTEN +#endif // LIBFUZZER_EMSCRIPTEN Options.HandleAbrt = Flags.handle_abrt; Options.HandleAlrm = !Flags.minimize_crash; @@ -809,12 +843,14 @@ std::atexit(Fuzzer::StaticExitCallback); - if (Flags.minimize_crash) return MinimizeCrashInput(Args, Options); + if (Flags.minimize_crash) + return MinimizeCrashInput(Args, Options); if (Flags.minimize_crash_internal_step) return MinimizeCrashInputInternalStep(F, Corpus); - if (Flags.cleanse_crash) return CleanseCrashInput(Args, Options); + if (Flags.cleanse_crash) + return CleanseCrashInput(Args, Options); if (RunIndividualFiles) { Options.SaveArtifacts = false; @@ -830,11 +866,10 @@ auto MS = duration_cast(StopTime - StartTime).count(); Printf("Executed %s in %zd ms\n", Path.c_str(), (long)MS); } - Printf( - "***\n" - "*** NOTE: fuzzing was not performed, you have only\n" - "*** executed the target code on a fixed set of inputs.\n" - "***\n"); + Printf("***\n" + "*** NOTE: fuzzing was not performed, you have only\n" + "*** executed the target code on a fixed set of inputs.\n" + "***\n"); F->PrintFinalStats(); exit(0); } @@ -843,18 +878,20 @@ FuzzWithFork(F->GetMD().GetRand(), Options, Args, *Inputs, Flags.fork, Flags.NumCorpuses); - if (Flags.merge) Merge(F, Options, Args, *Inputs, Flags.merge_control_file); + if (Flags.merge) + Merge(F, Options, Args, *Inputs, Flags.merge_control_file); if (Flags.merge_inner) { const size_t kDefaultMaxMergeLen = 1 << 20; - if (Options.MaxLen == 0) F->SetMaxInputLen(kDefaultMaxMergeLen); + if (Options.MaxLen == 0) + F->SetMaxInputLen(kDefaultMaxMergeLen); assert(Flags.merge_control_file); F->CrashResistantMergeInternalStep(Flags.merge_control_file); exit(0); } if (Flags.analyze_dict) { - size_t MaxLen = INT_MAX; // Large max length. + size_t MaxLen = INT_MAX; // Large max length. UnitVector InitialCorpus; for (auto &Inp : *Inputs) { Printf("Loading corpus dir: %s\n", Inp.c_str()); @@ -882,15 +919,16 @@ F->secondsSinceProcessStartUp()); F->PrintFinalStats(); - exit(0); // Don't let F destroy itself. + exit(0); // Don't let F destroy itself. } -extern "C" ATTRIBUTE_INTERFACE int LLVMFuzzerRunDriver( - int *argc, char ***argv, int (*UserCb)(const uint8_t *Data, size_t Size)) { +extern "C" ATTRIBUTE_INTERFACE int +LLVMFuzzerRunDriver(int *argc, char ***argv, + int (*UserCb)(const uint8_t *Data, size_t Size)) { return FuzzerDriver(argc, argv, UserCb); } // Storage for global ExternalFunctions object. ExternalFunctions *EF = nullptr; -} // namespace fuzzer +} // namespace fuzzer Index: compiler-rt/lib/fuzzer/FuzzerFlags.def =================================================================== --- compiler-rt/lib/fuzzer/FuzzerFlags.def +++ compiler-rt/lib/fuzzer/FuzzerFlags.def @@ -73,6 +73,7 @@ "If positive, indicates the maximal total " "time in seconds to run the fuzzer.") FUZZER_FLAG_INT(help, 0, "Print help.") + FUZZER_FLAG_INT( NumCorpuses, 1, "FOR fork mode. Divide the main corpus into N parts according to size.") @@ -147,10 +148,9 @@ FUZZER_FLAG_INT(only_ascii, 0, "If 1, generate only ASCII (isprint+isspace) inputs.") FUZZER_FLAG_STRING(dict, "Experimental. Use the dictionary file.") -FUZZER_FLAG_STRING(artifact_prefix, - "Write fuzzing artifacts (crash, " - "timeout, or slow inputs) as " - "$(artifact_prefix)file") +FUZZER_FLAG_STRING(artifact_prefix, "Write fuzzing artifacts (crash, " + "timeout, or slow inputs) as " + "$(artifact_prefix)file") FUZZER_FLAG_STRING(exact_artifact_path, "Write the single artifact on failure (crash, timeout) " "as $(exact_artifact_path). This overrides -artifact_prefix " @@ -213,10 +213,9 @@ "Exit if a newly found PC originates" " from the given source location. Example: -exit_on_src_pos=foo.cc:123. " "Used primarily for testing libFuzzer itself.") -FUZZER_FLAG_STRING(exit_on_item, - "Exit if an item with a given sha1 sum" - " was added to the corpus. " - "Used primarily for testing libFuzzer itself.") +FUZZER_FLAG_STRING(exit_on_item, "Exit if an item with a given sha1 sum" + " was added to the corpus. " + "Used primarily for testing libFuzzer itself.") FUZZER_FLAG_INT(ignore_remaining_args, 0, "If 1, ignore all arguments passed " "after this one. Useful for fuzzers that need to do their own " Index: compiler-rt/lib/fuzzer/FuzzerFork.h =================================================================== --- compiler-rt/lib/fuzzer/FuzzerFork.h +++ compiler-rt/lib/fuzzer/FuzzerFork.h @@ -9,17 +9,17 @@ #ifndef LLVM_FUZZER_FORK_H #define LLVM_FUZZER_FORK_H -#include - #include "FuzzerDefs.h" #include "FuzzerOptions.h" #include "FuzzerRandom.h" +#include + namespace fuzzer { void FuzzWithFork(Random &Rand, const FuzzingOptions &Options, const Vector &Args, const Vector &CorpusDirs, int NumJobs, int NumCorpuses); -} // namespace fuzzer +} // namespace fuzzer -#endif // LLVM_FUZZER_FORK_H +#endif // LLVM_FUZZER_FORK_H Index: compiler-rt/lib/fuzzer/FuzzerFork.cpp =================================================================== --- compiler-rt/lib/fuzzer/FuzzerFork.cpp +++ compiler-rt/lib/fuzzer/FuzzerFork.cpp @@ -9,6 +9,13 @@ //===----------------------------------------------------------------------===// #include "FuzzerFork.h" +#include "FuzzerCommand.h" +#include "FuzzerIO.h" +#include "FuzzerInternal.h" +#include "FuzzerMerge.h" +#include "FuzzerSHA1.h" +#include "FuzzerTracePC.h" +#include "FuzzerUtil.h" #include #include @@ -20,14 +27,6 @@ #include #include -#include "FuzzerCommand.h" -#include "FuzzerIO.h" -#include "FuzzerInternal.h" -#include "FuzzerMerge.h" -#include "FuzzerSHA1.h" -#include "FuzzerTracePC.h" -#include "FuzzerUtil.h" - namespace fuzzer { struct Stats { @@ -50,13 +49,15 @@ {nullptr, nullptr}, }; while (std::getline(In, Line, '\n')) { - if (Line.find("stat::") != 0) continue; + if (Line.find("stat::") != 0) + continue; std::istringstream ISS(Line); std::string Name; size_t Val; ISS >> Name >> Val; for (size_t i = 0; NameVarPairs[i].Name; i++) - if (Name == NameVarPairs[i].Name) *NameVarPairs[i].Var = Val; + if (Name == NameVarPairs[i].Name) + *NameVarPairs[i].Var = Val; } return Res; } @@ -95,7 +96,7 @@ Set Features, Cov; Set FilesWithDFT; Vector Files; - // This variable is used to store the size of the seed. + // Declare a variable to store the seed size. Vector FilesSizes; Random *Rand; std::chrono::system_clock::time_point ProcessStartTime; @@ -120,16 +121,17 @@ Cmd.removeFlag("fork"); Cmd.removeFlag("runs"); Cmd.removeFlag("collect_data_flow"); - for (auto &C : CorpusDirs) // Remove all corpora from the args. + for (auto &C : CorpusDirs) // Remove all corpora from the args. Cmd.removeArgument(C); - Cmd.addFlag("reload", "0"); // working in an isolated dir, no reload. + Cmd.addFlag("reload", "0"); // working in an isolated dir, no reload. Cmd.addFlag("print_final_stats", "1"); - Cmd.addFlag("print_funcs", "0"); // no need to spend time symbolizing. + Cmd.addFlag("print_funcs", "0"); // no need to spend time symbolizing. Cmd.addFlag("max_total_time", std::to_string(std::min((size_t)300, JobId))); Cmd.addFlag("stop_file", StopFile()); if (!DataFlowBinary.empty()) { Cmd.addFlag("data_flow_trace", DFTDir); - if (!Cmd.hasFlag("focus_function")) Cmd.addFlag("focus_function", "auto"); + if (!Cmd.hasFlag("focus_function")) + Cmd.addFlag("focus_function", "auto"); } auto Job = new FuzzJob; std::string Seeds; @@ -138,10 +140,11 @@ size_t AverageSize = Files.size() / NumCorpuses + 1; auto Time1 = std::chrono::system_clock::now(); size_t StartIndex = ((JobId - 1) % NumCorpuses) * AverageSize; - // At this time, the seeds in the File variable are sorted according to - // the seed size, so by generating a uniformly distributed random - // number, the seeds are selected in a certain group. for (size_t i = 0; i < CorpusSubsetSize; i++) { + // size_t j = Rand->SkewTowardsLast(AverageSize); + // At this time, the seeds in the File variable are sorted according to + // the seed size, so by generating a uniformly distributed random + // number, the seeds are selected in a certain group std::random_device rd; std::mt19937 randomseed(rd()); std::uniform_int_distribution<> rand(0, AverageSize); @@ -218,14 +221,14 @@ } } // if (!FilesToAdd.empty() || Job->ExitCode != 0) - Printf( - "#%zd: cov: %zd ft: %zd corp: %zd exec/s %zd " - "oom/timeout/crash: %zd/%zd/%zd time: %zds job: %zd dft_time: %d\n", - NumRuns, Cov.size(), Features.size(), Files.size(), - Stats.average_exec_per_sec, NumOOMs, NumTimeouts, NumCrashes, - secondsSinceProcessStartUp(), Job->JobId, Job->DftTimeInSeconds); + Printf("#%zd: cov: %zd ft: %zd corp: %zd exec/s %zd " + "oom/timeout/crash: %zd/%zd/%zd time: %zds job: %zd dft_time: %d\n", + NumRuns, Cov.size(), Features.size(), Files.size(), + Stats.average_exec_per_sec, NumOOMs, NumTimeouts, NumCrashes, + secondsSinceProcessStartUp(), Job->JobId, Job->DftTimeInSeconds); - if (MergeCandidates.empty()) return; + if (MergeCandidates.empty()) + return; Vector FilesToAdd; Set NewFeatures, NewCov; @@ -252,14 +255,16 @@ } void CollectDFT(const std::string &InputPath) { - if (DataFlowBinary.empty()) return; - if (!FilesWithDFT.insert(InputPath).second) return; + if (DataFlowBinary.empty()) + return; + if (!FilesWithDFT.insert(InputPath).second) + return; Command Cmd(Args); Cmd.removeFlag("fork"); Cmd.removeFlag("runs"); Cmd.addFlag("data_flow_trace", DFTDir); Cmd.addArgument(InputPath); - for (auto &C : CorpusDirs) // Remove all corpora from the args. + for (auto &C : CorpusDirs) // Remove all corpora from the args. Cmd.removeArgument(C); Cmd.setOutputFile(DirPlusFile(TempDir, "dft.log")); Cmd.combineOutAndErr(); @@ -315,11 +320,12 @@ Env.DataFlowBinary = Options.CollectDataFlow; Vector SeedFiles; - for (auto &Dir : CorpusDirs) GetSizedFilesFromDir(Dir, &SeedFiles); + for (auto &Dir : CorpusDirs) + GetSizedFilesFromDir(Dir, &SeedFiles); std::sort(SeedFiles.begin(), SeedFiles.end()); Env.TempDir = TempPath("FuzzWithFork", ".dir"); Env.DFTDir = DirPlusFile(Env.TempDir, "DFT"); - RmDirRecursive(Env.TempDir); // in case there is a leftover from old runs. + RmDirRecursive(Env.TempDir); // in case there is a leftover from old runs. MkDir(Env.TempDir); MkDir(Env.DFTDir); @@ -355,7 +361,8 @@ JobQueue FuzzQ, MergeQ; auto StopJobs = [&]() { - for (int i = 0; i < NumJobs; i++) FuzzQ.Push(nullptr); + for (int i = 0; i < NumJobs; i++) + FuzzQ.Push(nullptr); MergeQ.Push(nullptr); WriteToFile(Unit({1}), Env.StopFile()); }; @@ -369,7 +376,8 @@ while (true) { std::unique_ptr Job(MergeQ.Pop()); - if (!Job) break; + if (!Job) + break; ExitCode = Job->ExitCode; if (ExitCode == Options.InterruptExitCode) { Printf("==%lu== libFuzzer: a child was interrupted; exiting\n", GetPid()); @@ -423,18 +431,27 @@ // Since the number of corpus seeds will gradually increase, in order to // control the number in each group to be about three times the number of // seeds selected each time, the number of groups is dynamically adjusted. - if (Env.Files.size() >= 1 && Env.Files.size() < 1600) NumCorpuses = 16; - if (Env.Files.size() >= 1600 && Env.Files.size() < 3600) NumCorpuses = 20; - if (Env.Files.size() >= 3600 && Env.Files.size() < 6400) NumCorpuses = 24; - if (Env.Files.size() >= 6400 && Env.Files.size() < 8100) NumCorpuses = 32; - if (Env.Files.size() >= 8100 && Env.Files.size() < 12000) NumCorpuses = 36; - if (Env.Files.size() >= 12000 && Env.Files.size() < 16000) NumCorpuses = 40; - if (Env.Files.size() >= 16000 && Env.Files.size() < 30000) NumCorpuses = 60; - if (Env.Files.size() >= 30000) NumCorpuses = 80; + if (Env.Files.size() >= 1 && Env.Files.size() < 1600) + NumCorpuses = 16; + if (Env.Files.size() >= 1600 && Env.Files.size() < 3600) + NumCorpuses = 20; + if (Env.Files.size() >= 3600 && Env.Files.size() < 6400) + NumCorpuses = 24; + if (Env.Files.size() >= 6400 && Env.Files.size() < 8100) + NumCorpuses = 32; + if (Env.Files.size() >= 8100 && Env.Files.size() < 12000) + NumCorpuses = 36; + if (Env.Files.size() >= 12000 && Env.Files.size() < 16000) + NumCorpuses = 40; + if (Env.Files.size() >= 16000 && Env.Files.size() < 30000) + NumCorpuses = 60; + if (Env.Files.size() >= 30000) + NumCorpuses = 80; FuzzQ.Push(Env.CreateNewJob(JobId++, NumCorpuses)); } - for (auto &T : Threads) T.join(); + for (auto &T : Threads) + T.join(); // The workers have terminated. Don't try to remove the directory before they // terminate to avoid a race condition preventing cleanup on Windows. @@ -446,4 +463,4 @@ exit(ExitCode); } -} // namespace fuzzer +} // namespace fuzzer