From 05ef67b6b9f1efe216cb4c1bbe0e75b178b5fba2 Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Mon, 18 May 2015 21:34:20 +0000 Subject: [PATCH] [lib/Fuzzer] when -sync_command= is given, periodically execute 'CMD CORPUS' to synchronize with other processes git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@237617 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Fuzzer/FuzzerDriver.cpp | 3 +++ lib/Fuzzer/FuzzerFlags.def | 4 ++++ lib/Fuzzer/FuzzerIO.cpp | 2 +- lib/Fuzzer/FuzzerInternal.h | 6 ++++++ lib/Fuzzer/FuzzerLoop.cpp | 11 +++++++++++ lib/Fuzzer/FuzzerUtil.cpp | 4 ++++ 6 files changed, 29 insertions(+), 1 deletion(-) diff --git a/lib/Fuzzer/FuzzerDriver.cpp b/lib/Fuzzer/FuzzerDriver.cpp index d1f6953a748..6b8a4b220ef 100644 --- a/lib/Fuzzer/FuzzerDriver.cpp +++ b/lib/Fuzzer/FuzzerDriver.cpp @@ -230,6 +230,9 @@ int FuzzerDriver(int argc, char **argv, UserCallback Callback) { Options.MaxNumberOfRuns = Flags.runs; if (!inputs.empty()) Options.OutputCorpus = inputs[0]; + if (Flags.sync_command) + Options.SyncCommand = Flags.sync_command; + Options.SyncTimeout = Flags.sync_timeout; Fuzzer F(Callback, Options); unsigned seed = Flags.seed; diff --git a/lib/Fuzzer/FuzzerFlags.def b/lib/Fuzzer/FuzzerFlags.def index 942bd59cb79..9d1b54524e9 100644 --- a/lib/Fuzzer/FuzzerFlags.def +++ b/lib/Fuzzer/FuzzerFlags.def @@ -53,3 +53,7 @@ FUZZER_FLAG_STRING(tokens, "Use the file with tokens (one token per line) to" " fuzz a token based input language.") FUZZER_FLAG_STRING(apply_tokens, "Read the given input file, substitute bytes " " with tokens and write the result to stdout.") +FUZZER_FLAG_STRING(sync_command, "Execute an external command " + "\" \" " + "to synchronize the test corpus.") +FUZZER_FLAG_INT(sync_timeout, 600, "Minimal timeout between syncs.") diff --git a/lib/Fuzzer/FuzzerIO.cpp b/lib/Fuzzer/FuzzerIO.cpp index 7136d38fb77..c6636c86818 100644 --- a/lib/Fuzzer/FuzzerIO.cpp +++ b/lib/Fuzzer/FuzzerIO.cpp @@ -83,7 +83,7 @@ std::string DirPlusFile(const std::string &DirPath, void PrintFileAsBase64(const std::string &Path) { std::string Cmd = "base64 -w 0 < " + Path + "; echo"; - system(Cmd.c_str()); + ExecuteCommand(Cmd); } } // namespace fuzzer diff --git a/lib/Fuzzer/FuzzerInternal.h b/lib/Fuzzer/FuzzerInternal.h index 89261895579..8d6193e9a22 100644 --- a/lib/Fuzzer/FuzzerInternal.h +++ b/lib/Fuzzer/FuzzerInternal.h @@ -43,6 +43,7 @@ void PrintASCII(const Unit &U, const char *PrintAfter = ""); std::string Hash(const Unit &U); void SetTimer(int Seconds); void PrintFileAsBase64(const std::string &Path); +void ExecuteCommand(const std::string &Command); // Private copy of SHA1 implementation. static const int kSHA1NumBytes = 20; @@ -66,7 +67,9 @@ class Fuzzer { bool Reload = true; int PreferSmallDuringInitialShuffle = -1; size_t MaxNumberOfRuns = ULONG_MAX; + int SyncTimeout = 600; std::string OutputCorpus; + std::string SyncCommand; std::vector Tokens; }; Fuzzer(UserCallback Callback, FuzzingOptions Options); @@ -108,6 +111,8 @@ class Fuzzer { void PrintStats(const char *Where, size_t Cov, const char *End = "\n"); void PrintUnitInASCIIOrTokens(const Unit &U, const char *PrintAfter = ""); + void SyncCorpus(); + // Trace-based fuzzing: we run a unit with some kind of tracing // enabled and record potentially useful mutations. Then // We apply these mutations one by one to the unit and run it again. @@ -142,6 +147,7 @@ class Fuzzer { UserCallback Callback; FuzzingOptions Options; system_clock::time_point ProcessStartTime = system_clock::now(); + system_clock::time_point LastExternalSync = system_clock::now(); system_clock::time_point UnitStartTime; long TimeOfLongestUnitInSeconds = 0; long EpochOfLastReadOfOutputCorpus = 0; diff --git a/lib/Fuzzer/FuzzerLoop.cpp b/lib/Fuzzer/FuzzerLoop.cpp index 9200f6293fd..3a80d0d7e23 100644 --- a/lib/Fuzzer/FuzzerLoop.cpp +++ b/lib/Fuzzer/FuzzerLoop.cpp @@ -324,6 +324,7 @@ void Fuzzer::MutateAndTestOne(Unit *U) { void Fuzzer::Loop(size_t NumIterations) { for (size_t i = 1; i <= NumIterations; i++) { for (size_t J1 = 0; J1 < Corpus.size(); J1++) { + SyncCorpus(); RereadOutputCorpus(); if (TotalNumberOfRuns >= Options.MaxNumberOfRuns) return; @@ -342,4 +343,14 @@ void Fuzzer::Loop(size_t NumIterations) { } } +void Fuzzer::SyncCorpus() { + if (Options.SyncCommand.empty() || Options.OutputCorpus.empty()) return; + auto Now = system_clock::now(); + if (duration_cast(Now - LastExternalSync).count() < + Options.SyncTimeout) + return; + LastExternalSync = Now; + ExecuteCommand(Options.SyncCommand + " " + Options.OutputCorpus); +} + } // namespace fuzzer diff --git a/lib/Fuzzer/FuzzerUtil.cpp b/lib/Fuzzer/FuzzerUtil.cpp index c4b0afa55d5..06852081f52 100644 --- a/lib/Fuzzer/FuzzerUtil.cpp +++ b/lib/Fuzzer/FuzzerUtil.cpp @@ -70,4 +70,8 @@ int NumberOfCpuCores() { return N; } +void ExecuteCommand(const std::string &Command) { + system(Command.c_str()); +} + } // namespace fuzzer