void Fuzzer::RereadOutputCorpus(size_t MaxSize) { if (Options.OutputCorpus.empty()) 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 (RunOne(X)) { Corpus.push_back(X); UpdateCorpusDistribution(); PrintStats("RELOAD"); } } } }
void Fuzzer::ReportNewCoverage(const Unit &U) { Corpus.push_back(U); UpdateCorpusDistribution(); UnitHashesAddedToCorpus.insert(Hash(U)); MD.RecordSuccessfulMutationSequence(); PrintStatusForNewUnit(U); WriteToOutputCorpus(U); NumberOfNewUnitsAdded++; }
void Fuzzer::ShuffleAndMinimize() { PrintStats("READ "); std::vector<Unit> NewCorpus; if (Options.ShuffleAtStartUp) ShuffleCorpus(&Corpus); for (const auto &U : Corpus) { if (RunOne(U)) { NewCorpus.push_back(U); if (Options.Verbosity >= 2) Printf("NEW0: %zd L %zd\n", MaxCoverage.BlockCoverage, U.size()); } } Corpus = NewCorpus; UpdateCorpusDistribution(); for (auto &X : Corpus) UnitHashesAddedToCorpus.insert(Hash(X)); PrintStats("INITED"); CheckForMemoryLeaks(); }
// 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(); CHECK_WEAK_API_FUNCTION(__sanitizer_reset_coverage); __sanitizer_reset_coverage(); 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(); __sanitizer_reset_coverage(); 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::ShuffleAndMinimize() { bool PreferSmall = (Options.PreferSmallDuringInitialShuffle == 1 || (Options.PreferSmallDuringInitialShuffle == -1 && MD.GetRand().RandBool())); if (Options.Verbosity) Printf("PreferSmall: %d\n", PreferSmall); PrintStats("READ "); std::vector<Unit> NewCorpus; if (Options.ShuffleAtStartUp) { std::random_shuffle(Corpus.begin(), Corpus.end(), MD.GetRand()); if (PreferSmall) std::stable_sort( Corpus.begin(), Corpus.end(), [](const Unit &A, const Unit &B) { return A.size() < B.size(); }); } Unit U; for (const auto &C : Corpus) { for (size_t First = 0; First < 1; First++) { U.clear(); size_t Last = std::min(First + Options.MaxLen, C.size()); U.insert(U.begin(), C.begin() + First, C.begin() + Last); if (Options.OnlyASCII) ToASCII(U.data(), U.size()); if (RunOne(U)) { NewCorpus.push_back(U); if (Options.Verbosity >= 2) Printf("NEW0: %zd L %zd\n", LastRecordedBlockCoverage, U.size()); } } } Corpus = NewCorpus; UpdateCorpusDistribution(); for (auto &X : Corpus) UnitHashesAddedToCorpus.insert(Hash(X)); PrintStats("INITED"); }