diff options
author | Kostya Serebryany <kcc@google.com> | 2016-09-21 01:04:43 +0000 |
---|---|---|
committer | Kostya Serebryany <kcc@google.com> | 2016-09-21 01:04:43 +0000 |
commit | 09aa01a6f86e348800d76d7e7008eba9b2d5803f (patch) | |
tree | 849d0a42ee7c70ace285c1ea56b5c92f02066970 /llvm/lib/Fuzzer/FuzzerLoop.cpp | |
parent | 3eb83b4a0df13cd5d7f3ae4a04253c909163eb03 (diff) | |
download | bcm5719-llvm-09aa01a6f86e348800d76d7e7008eba9b2d5803f.tar.gz bcm5719-llvm-09aa01a6f86e348800d76d7e7008eba9b2d5803f.zip |
[libFuzzer] refactoring: move the Corpus into a separate class; delete two unused experimental features
llvm-svn: 282042
Diffstat (limited to 'llvm/lib/Fuzzer/FuzzerLoop.cpp')
-rw-r--r-- | llvm/lib/Fuzzer/FuzzerLoop.cpp | 134 |
1 files changed, 21 insertions, 113 deletions
diff --git a/llvm/lib/Fuzzer/FuzzerLoop.cpp b/llvm/lib/Fuzzer/FuzzerLoop.cpp index 3ef7c5f68ae..2dcf11eb36d 100644 --- a/llvm/lib/Fuzzer/FuzzerLoop.cpp +++ b/llvm/lib/Fuzzer/FuzzerLoop.cpp @@ -172,6 +172,8 @@ Fuzzer::Fuzzer(UserCallback CB, MutationDispatcher &MD, FuzzingOptions Options) } if (Options.Verbosity) TPC.PrintModuleInfo(); + if (!Options.OutputCorpus.empty() && Options.Reload) + EpochOfLastReadOfOutputCorpus = GetEpoch(Options.OutputCorpus); } Fuzzer::~Fuzzer() { } @@ -340,13 +342,6 @@ void Fuzzer::PrintFinalStats() { Printf("stat::peak_rss_mb: %zd\n", GetPeakRSSMb()); } -size_t Fuzzer::MaxUnitSizeInCorpus() const { - size_t Res = 0; - for (auto &X : Corpus) - Res = std::max(Res, X.size()); - return Res; -} - void Fuzzer::SetMaxLen(size_t MaxLen) { assert(Options.MaxLen == 0); // Can only reset MaxLen from 0 to non-0. assert(MaxLen); @@ -354,25 +349,25 @@ void Fuzzer::SetMaxLen(size_t MaxLen) { Printf("INFO: -max_len is not provided, using %zd\n", Options.MaxLen); } +void Fuzzer::ReadDir(const std::string &Path, long *Epoch, size_t MaxSize) { + Printf("Loading corpus: %s\n", Path.c_str()); + std::vector<Unit> V; + ReadDirToVectorOfUnits(Path.c_str(), &V, Epoch, MaxSize); + for (auto &U : V) + Corpus.push_back(U); +} void Fuzzer::RereadOutputCorpus(size_t MaxSize) { - if (Options.OutputCorpus.empty()) - return; + if (Options.OutputCorpus.empty() || !Options.Reload) return; std::vector<Unit> AdditionalCorpus; ReadDirToVectorOfUnits(Options.OutputCorpus.c_str(), &AdditionalCorpus, &EpochOfLastReadOfOutputCorpus, MaxSize); - if (Corpus.empty()) { - Corpus = AdditionalCorpus; - return; - } - if (!Options.Reload) - return; if (Options.Verbosity >= 2) Printf("Reload: read %zd new units.\n", AdditionalCorpus.size()); for (auto &X : AdditionalCorpus) { if (X.size() > MaxSize) X.resize(MaxSize); - if (UnitHashesAddedToCorpus.insert(Hash(X)).second) { + if (!Corpus.HasUnit(X)) { if (RunOne(X)) { Corpus.push_back(X); UpdateCorpusDistribution(); @@ -390,51 +385,22 @@ void Fuzzer::ShuffleCorpus(UnitVector *V) { }); } -// Tries random prefixes of corpus items. -void Fuzzer::TruncateUnits(std::vector<Unit> *NewCorpus) { - std::vector<double> Fractions = {0.25, 0.5, 0.75, 1.0}; - - size_t TruncInputs = 0; - for (double Fraction : Fractions) { - for (const auto &U : Corpus) { - uint64_t S = MD.GetRand()(U.size() * Fraction); - if (!S || !RunOne(U.data(), S)) - continue; - TruncInputs++; - Unit U1(U.begin(), U.begin() + S); - NewCorpus->push_back(U1); - } - } - if (TruncInputs) - Printf("\tINFO TRUNC %zd units added to in-memory corpus\n", TruncInputs); -} - -void Fuzzer::ShuffleAndMinimize() { - PrintStats("READ "); - std::vector<Unit> NewCorpus; +void Fuzzer::ShuffleAndMinimize(UnitVector *InitialCorpus) { + Printf("#0\tREAD units: %zd\n", InitialCorpus->size()); if (Options.ShuffleAtStartUp) - ShuffleCorpus(&Corpus); - - if (Options.TruncateUnits) { - ResetCoverage(); - TruncateUnits(&NewCorpus); - ResetCoverage(); - } + ShuffleCorpus(InitialCorpus); - for (const auto &U : Corpus) { + for (const auto &U : *InitialCorpus) { bool NewCoverage = RunOne(U); if (!Options.PruneCorpus || NewCoverage) { - NewCorpus.push_back(U); + Corpus.push_back(U); if (Options.Verbosity >= 2) Printf("NEW0: %zd L %zd\n", MaxCoverage.BlockCoverage, U.size()); } TryDetectingAMemoryLeak(U.data(), U.size(), /*DuringInitialCorpusExecution*/ true); } - Corpus = NewCorpus; UpdateCorpusDistribution(); - for (auto &X : Corpus) - UnitHashesAddedToCorpus.insert(Hash(X)); PrintStats("INITED"); if (Corpus.empty()) { Printf("ERROR: no interesting inputs were found. " @@ -540,16 +506,6 @@ void Fuzzer::WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix) { Printf("Base64: %s\n", Base64(U).c_str()); } -void Fuzzer::SaveCorpus() { - if (Options.OutputCorpus.empty()) - return; - for (const auto &U : Corpus) - WriteToFile(U, DirPlusFile(Options.OutputCorpus, Hash(U))); - if (Options.Verbosity) - Printf("Written corpus of %zd files to %s\n", Corpus.size(), - Options.OutputCorpus.c_str()); -} - void Fuzzer::PrintStatusForNewUnit(const Unit &U) { if (!Options.PrintNEW) return; @@ -584,7 +540,6 @@ void Fuzzer::PrintNewPCs() { void Fuzzer::ReportNewCoverage(const Unit &U) { Corpus.push_back(U); UpdateCorpusDistribution(); - UnitHashesAddedToCorpus.insert(Hash(U)); MD.RecordSuccessfulMutationSequence(); PrintStatusForNewUnit(U); WriteToOutputCorpus(U); @@ -599,6 +554,7 @@ void Fuzzer::ReportNewCoverage(const Unit &U) { UnitVector Fuzzer::FindExtraUnits(const UnitVector &Initial, const UnitVector &Extra) { UnitVector Res = Extra; + UnitVector Tmp; size_t OldSize = Res.size(); for (int Iter = 0; Iter < 10; Iter++) { ShuffleCorpus(&Res); @@ -607,18 +563,18 @@ UnitVector Fuzzer::FindExtraUnits(const UnitVector &Initial, for (auto &U : Initial) RunOne(U); - Corpus.clear(); + Tmp.clear(); for (auto &U : Res) if (RunOne(U)) - Corpus.push_back(U); + Tmp.push_back(U); char Stat[7] = "MIN "; Stat[3] = '0' + Iter; PrintStats(Stat); - size_t NewSize = Corpus.size(); + size_t NewSize = Tmp.size(); assert(NewSize <= OldSize); - Res.swap(Corpus); + Res.swap(Tmp); if (NewSize + 5 >= OldSize) break; @@ -736,54 +692,6 @@ void Fuzzer::ResetCoverage() { PrepareCounters(&MaxCoverage); } -// Experimental search heuristic: drilling. -// - Read, shuffle, execute and minimize the corpus. -// - Choose one random unit. -// - Reset the coverage. -// - Start fuzzing as if the chosen unit was the only element of the corpus. -// - When done, reset the coverage again. -// - Merge the newly created corpus into the original one. -void Fuzzer::Drill() { - // The corpus is already read, shuffled, and minimized. - assert(!Corpus.empty()); - Options.PrintNEW = false; // Don't print NEW status lines when drilling. - - Unit U = ChooseUnitToMutate(); - - ResetCoverage(); - - std::vector<Unit> SavedCorpus; - SavedCorpus.swap(Corpus); - Corpus.push_back(U); - UpdateCorpusDistribution(); - assert(Corpus.size() == 1); - RunOne(U); - PrintStats("DRILL "); - std::string SavedOutputCorpusPath; // Don't write new units while drilling. - SavedOutputCorpusPath.swap(Options.OutputCorpus); - Loop(); - - ResetCoverage(); - - PrintStats("REINIT"); - SavedOutputCorpusPath.swap(Options.OutputCorpus); - for (auto &U : SavedCorpus) - RunOne(U); - PrintStats("MERGE "); - Options.PrintNEW = true; - size_t NumMerged = 0; - for (auto &U : Corpus) { - if (RunOne(U)) { - PrintStatusForNewUnit(U); - NumMerged++; - WriteToOutputCorpus(U); - } - } - PrintStats("MERGED"); - if (NumMerged && Options.Verbosity) - Printf("Drilling discovered %zd new units\n", NumMerged); -} - void Fuzzer::Loop() { system_clock::time_point LastCorpusReload = system_clock::now(); if (Options.DoCrossOver) |