[libFuzzer] make the fork mode less verbose

llvm-svn: 353794
This commit is contained in:
Kostya Serebryany 2019-02-12 03:12:40 +00:00
parent 9e624d5410
commit 2b9a8f37a4
5 changed files with 52 additions and 28 deletions

View File

@ -484,11 +484,12 @@ void FuzzWithFork(Fuzzer *F, const FuzzingOptions &Options,
GetSizedFilesFromDir(Dir, &Corpus); GetSizedFilesFromDir(Dir, &Corpus);
std::sort(Corpus.begin(), Corpus.end()); std::sort(Corpus.begin(), Corpus.end());
auto CFPath = TempPath(".fork"); auto CFPath = TempPath(".fork");
auto LogPath = TempPath(".log");
Vector<std::string> Files; Vector<std::string> Files;
Set<uint32_t> Features; Set<uint32_t> Features;
if (!Corpus.empty()) { if (!Corpus.empty()) {
CrashResistantMerge(Args, {}, Corpus, &Files, {}, &Features, CFPath); CrashResistantMerge(Args, {}, Corpus, &Files, {}, &Features, CFPath, false);
RemoveFile(CFPath); RemoveFile(CFPath);
} }
auto TempDir = TempPath("Dir"); auto TempDir = TempPath("Dir");
@ -500,8 +501,8 @@ void FuzzWithFork(Fuzzer *F, const FuzzingOptions &Options,
BaseCmd.removeFlag("fork"); BaseCmd.removeFlag("fork");
for (auto &C : Corpora) // Remove all corpora from the args. for (auto &C : Corpora) // Remove all corpora from the args.
BaseCmd.removeArgument(C); BaseCmd.removeArgument(C);
BaseCmd.addFlag("runs", "1000000"); if (!BaseCmd.hasFlag("max_total_time"))
BaseCmd.addFlag("max_total_time", "30"); BaseCmd.addFlag("max_total_time", "60");
BaseCmd.addArgument(TempDir); BaseCmd.addArgument(TempDir);
int ExitCode = 0; int ExitCode = 0;
for (size_t i = 0; i < 1000000; i++) { for (size_t i = 0; i < 1000000; i++) {
@ -511,10 +512,11 @@ void FuzzWithFork(Fuzzer *F, const FuzzingOptions &Options,
Cmd.addFlag("seed_inputs", Cmd.addFlag("seed_inputs",
Files[Rand.SkewTowardsLast(Files.size())] + "," + Files[Rand.SkewTowardsLast(Files.size())] + "," +
Files[Rand.SkewTowardsLast(Files.size())]); Files[Rand.SkewTowardsLast(Files.size())]);
Printf("RUN %s\n", Cmd.toString().c_str()); Cmd.setOutputFile(LogPath);
Cmd.combineOutAndErr();
RmFilesInDir(TempDir); RmFilesInDir(TempDir);
ExitCode = ExecuteCommand(Cmd); ExitCode = ExecuteCommand(Cmd);
Printf("Exit code: %d\n", ExitCode); // Printf("done [%d] %s\n", ExitCode, Cmd.toString().c_str());
if (ExitCode == Options.InterruptExitCode) if (ExitCode == Options.InterruptExitCode)
break; break;
Vector<SizedFile> TempFiles; Vector<SizedFile> TempFiles;
@ -522,7 +524,7 @@ void FuzzWithFork(Fuzzer *F, const FuzzingOptions &Options,
Set<uint32_t> NewFeatures; Set<uint32_t> NewFeatures;
GetSizedFilesFromDir(TempDir, &TempFiles); GetSizedFilesFromDir(TempDir, &TempFiles);
CrashResistantMerge(Args, {}, TempFiles, &FilesToAdd, Features, CrashResistantMerge(Args, {}, TempFiles, &FilesToAdd, Features,
&NewFeatures, CFPath); &NewFeatures, CFPath, false);
RemoveFile(CFPath); RemoveFile(CFPath);
for (auto &Path : FilesToAdd) { for (auto &Path : FilesToAdd) {
auto NewPath = F->WriteToOutputCorpus(FileToVector(Path, Options.MaxLen)); auto NewPath = F->WriteToOutputCorpus(FileToVector(Path, Options.MaxLen));
@ -539,7 +541,11 @@ void FuzzWithFork(Fuzzer *F, const FuzzingOptions &Options,
if (Options.IgnoreOOMs && ExitCode == Options.OOMExitCode) if (Options.IgnoreOOMs && ExitCode == Options.OOMExitCode)
continue; continue;
// And exit if we don't ignore this crash. // And exit if we don't ignore this crash.
if (ExitCode != 0) break; if (ExitCode != 0) {
Printf("INFO: log from the inner process:\n%s",
FileToString(LogPath).c_str());
break;
}
} }
RmFilesInDir(TempDir); RmFilesInDir(TempDir);
@ -568,7 +574,7 @@ void Merge(Fuzzer *F, FuzzingOptions &Options, const Vector<std::string> &Args,
Vector<std::string> NewFiles; Vector<std::string> NewFiles;
Set<uint32_t> NewFeatures; Set<uint32_t> NewFeatures;
CrashResistantMerge(Args, OldCorpus, NewCorpus, &NewFiles, {}, &NewFeatures, CrashResistantMerge(Args, OldCorpus, NewCorpus, &NewFiles, {}, &NewFeatures,
CFPath); CFPath, true);
for (auto &Path : NewFiles) for (auto &Path : NewFiles)
F->WriteToOutputCorpus(FileToVector(Path, Options.MaxLen)); F->WriteToOutputCorpus(FileToVector(Path, Options.MaxLen));
// We are done, delete the control file if it was a temporary one. // We are done, delete the control file if it was a temporary one.

View File

@ -125,6 +125,15 @@ void Printf(const char *Fmt, ...) {
fflush(OutputFile); fflush(OutputFile);
} }
void VPrintf(bool Verbose, const char *Fmt, ...) {
if (!Verbose) return;
va_list ap;
va_start(ap, Fmt);
vfprintf(OutputFile, Fmt, ap);
va_end(ap);
fflush(OutputFile);
}
void RmFilesInDir(const std::string &Path) { void RmFilesInDir(const std::string &Path) {
Vector<std::string> Files; Vector<std::string> Files;
ListFilesInDirRecursive(Path, 0, &Files, /*TopDir*/true); ListFilesInDirRecursive(Path, 0, &Files, /*TopDir*/true);

View File

@ -46,6 +46,7 @@ void DupAndCloseStderr();
void CloseStdout(); void CloseStdout();
void Printf(const char *Fmt, ...); void Printf(const char *Fmt, ...);
void VPrintf(bool Verbose, const char *Fmt, ...);
// Print using raw syscalls, useful when printing at early init stages. // Print using raw syscalls, useful when printing at early init stages.
void RawPrint(const char *Str); void RawPrint(const char *Str);

View File

@ -255,42 +255,43 @@ static void WriteNewControlFile(const std::string &CFPath,
// Outer process. Does not call the target code and thus should not fail. // Outer process. Does not call the target code and thus should not fail.
void CrashResistantMerge(const Vector<std::string> &Args, void CrashResistantMerge(const Vector<std::string> &Args,
const Vector<SizedFile> &OldCorpus, const Vector<SizedFile> &OldCorpus,
const Vector<SizedFile> &NewCorpus, const Vector<SizedFile> &NewCorpus,
Vector<std::string> *NewFiles, Vector<std::string> *NewFiles,
const Set<uint32_t> &InitialFeatures, const Set<uint32_t> &InitialFeatures,
Set<uint32_t> *NewFeatures, Set<uint32_t> *NewFeatures, const std::string &CFPath,
const std::string &CFPath) { bool V /*Verbose*/) {
size_t NumAttempts = 0; size_t NumAttempts = 0;
if (FileSize(CFPath)) { if (FileSize(CFPath)) {
Printf("MERGE-OUTER: non-empty control file provided: '%s'\n", VPrintf(V, "MERGE-OUTER: non-empty control file provided: '%s'\n",
CFPath.c_str()); CFPath.c_str());
Merger M; Merger M;
std::ifstream IF(CFPath); std::ifstream IF(CFPath);
if (M.Parse(IF, /*ParseCoverage=*/false)) { if (M.Parse(IF, /*ParseCoverage=*/false)) {
Printf("MERGE-OUTER: control file ok, %zd files total," VPrintf(V, "MERGE-OUTER: control file ok, %zd files total,"
" first not processed file %zd\n", " first not processed file %zd\n",
M.Files.size(), M.FirstNotProcessedFile); M.Files.size(), M.FirstNotProcessedFile);
if (!M.LastFailure.empty()) if (!M.LastFailure.empty())
Printf("MERGE-OUTER: '%s' will be skipped as unlucky " VPrintf(V, "MERGE-OUTER: '%s' will be skipped as unlucky "
"(merge has stumbled on it the last time)\n", "(merge has stumbled on it the last time)\n",
M.LastFailure.c_str()); M.LastFailure.c_str());
if (M.FirstNotProcessedFile >= M.Files.size()) { if (M.FirstNotProcessedFile >= M.Files.size()) {
Printf("MERGE-OUTER: nothing to do, merge has been completed before\n"); VPrintf(
V, "MERGE-OUTER: nothing to do, merge has been completed before\n");
exit(0); exit(0);
} }
NumAttempts = M.Files.size() - M.FirstNotProcessedFile; NumAttempts = M.Files.size() - M.FirstNotProcessedFile;
} else { } else {
Printf("MERGE-OUTER: bad control file, will overwrite it\n"); VPrintf(V, "MERGE-OUTER: bad control file, will overwrite it\n");
} }
} }
if (!NumAttempts) { if (!NumAttempts) {
// The supplied control file is empty or bad, create a fresh one. // The supplied control file is empty or bad, create a fresh one.
NumAttempts = OldCorpus.size() + NewCorpus.size(); NumAttempts = OldCorpus.size() + NewCorpus.size();
Printf("MERGE-OUTER: %zd files, %zd in the initial corpus\n", NumAttempts, VPrintf(V, "MERGE-OUTER: %zd files, %zd in the initial corpus\n",
OldCorpus.size()); NumAttempts, OldCorpus.size());
WriteNewControlFile(CFPath, OldCorpus, NewCorpus); WriteNewControlFile(CFPath, OldCorpus, NewCorpus);
} }
@ -301,13 +302,17 @@ void CrashResistantMerge(const Vector<std::string> &Args,
BaseCmd.removeFlag("fork"); BaseCmd.removeFlag("fork");
for (size_t Attempt = 1; Attempt <= NumAttempts; Attempt++) { for (size_t Attempt = 1; Attempt <= NumAttempts; Attempt++) {
Fuzzer::MaybeExitGracefully(); Fuzzer::MaybeExitGracefully();
Printf("MERGE-OUTER: attempt %zd\n", Attempt); VPrintf(V, "MERGE-OUTER: attempt %zd\n", Attempt);
Command Cmd(BaseCmd); Command Cmd(BaseCmd);
Cmd.addFlag("merge_control_file", CFPath); Cmd.addFlag("merge_control_file", CFPath);
Cmd.addFlag("merge_inner", "1"); Cmd.addFlag("merge_inner", "1");
if (!V) {
Cmd.setOutputFile("/dev/null"); // TODO: need to handle this on Windows?
Cmd.combineOutAndErr();
}
auto ExitCode = ExecuteCommand(Cmd); auto ExitCode = ExecuteCommand(Cmd);
if (!ExitCode) { if (!ExitCode) {
Printf("MERGE-OUTER: succesfull in %zd attempt(s)\n", Attempt); VPrintf(V, "MERGE-OUTER: succesfull in %zd attempt(s)\n", Attempt);
break; break;
} }
} }
@ -315,14 +320,16 @@ void CrashResistantMerge(const Vector<std::string> &Args,
Merger M; Merger M;
std::ifstream IF(CFPath); std::ifstream IF(CFPath);
IF.seekg(0, IF.end); IF.seekg(0, IF.end);
Printf("MERGE-OUTER: the control file has %zd bytes\n", (size_t)IF.tellg()); VPrintf(V, "MERGE-OUTER: the control file has %zd bytes\n",
(size_t)IF.tellg());
IF.seekg(0, IF.beg); IF.seekg(0, IF.beg);
M.ParseOrExit(IF, true); M.ParseOrExit(IF, true);
IF.close(); IF.close();
Printf("MERGE-OUTER: consumed %zdMb (%zdMb rss) to parse the control file\n", VPrintf(V,
M.ApproximateMemoryConsumption() >> 20, GetPeakRSSMb()); "MERGE-OUTER: consumed %zdMb (%zdMb rss) to parse the control file\n",
M.ApproximateMemoryConsumption() >> 20, GetPeakRSSMb());
size_t NumNewFeatures = M.Merge(InitialFeatures, NewFeatures, NewFiles); size_t NumNewFeatures = M.Merge(InitialFeatures, NewFeatures, NewFiles);
Printf("MERGE-OUTER: %zd new files with %zd new features added\n", VPrintf(V, "MERGE-OUTER: %zd new files with %zd new features added\n",
NewFiles->size(), NumNewFeatures); NewFiles->size(), NumNewFeatures);
} }

View File

@ -76,7 +76,8 @@ void CrashResistantMerge(const Vector<std::string> &Args,
Vector<std::string> *NewFiles, Vector<std::string> *NewFiles,
const Set<uint32_t> &InitialFeatures, const Set<uint32_t> &InitialFeatures,
Set<uint32_t> *NewFeatures, Set<uint32_t> *NewFeatures,
const std::string &CFPath); const std::string &CFPath,
bool Verbose);
} // namespace fuzzer } // namespace fuzzer