// libFuzzer can be linked w/o the sanitizers and sanitizer-coveragte
// (in which case it will complain at start-up time).
__attribute__((weak)) void __sanitizer_print_stack_trace();
+__attribute__((weak)) void __sanitizer_reset_coverage();
__attribute__((weak)) size_t __sanitizer_get_total_unique_caller_callee_pairs();
__attribute__((weak)) size_t __sanitizer_get_total_unique_coverage();
__attribute__((weak))
Options.OutputCorpus.c_str());
}
-void Fuzzer::ReportNewCoverage(const Unit &U) {
- Corpus.push_back(U);
- UnitHashesAddedToCorpus.insert(Hash(U));
+void Fuzzer::PrintStatusForNewUnit(const Unit &U) {
+ if (!Options.PrintNEW)
+ return;
PrintStats("NEW ", "");
if (Options.Verbosity) {
Printf(" L: %zd", U.size());
}
Printf("\n");
}
+}
+
+void Fuzzer::ReportNewCoverage(const Unit &U) {
+ Corpus.push_back(U);
+ UnitHashesAddedToCorpus.insert(Hash(U));
+ PrintStatusForNewUnit(U);
WriteToOutputCorpus(U);
if (Options.ExitOnFirst)
exit(0);
// Returns an index of random unit from the corpus to mutate.
// Hypothesis: units added to the corpus last are more likely to be interesting.
// This function gives more wieght to the more recent units.
-size_t Fuzzer::ChooseUnitToMutate() {
+size_t Fuzzer::ChooseUnitIdxToMutate() {
size_t N = Corpus.size();
size_t Total = (N + 1) * N / 2;
size_t R = USF.GetRand()(Total);
return IdxBeg;
}
-void Fuzzer::Loop() {
- for (auto &U: Options.Dictionary)
- USF.GetMD().AddWordToDictionary(U.data(), U.size());
+// 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);
+ 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::Loop() {
while (true) {
- size_t J1 = ChooseUnitToMutate();;
+ size_t J1 = ChooseUnitIdxToMutate();;
SyncCorpus();
RereadOutputCorpus();
if (TotalNumberOfRuns >= Options.MaxNumberOfRuns)
CurrentUnit = Corpus[J1];
// Optionally, cross with another unit.
if (Options.DoCrossOver && USF.GetRand().RandBool()) {
- size_t J2 = ChooseUnitToMutate();
+ size_t J2 = ChooseUnitIdxToMutate();
if (!Corpus[J1].empty() && !Corpus[J2].empty()) {
assert(!Corpus[J2].empty());
CurrentUnit.resize(Options.MaxLen);