- U->resize(NewSize);
- RunOneAndUpdateCorpus(*U);
- size_t NumTraceBasedMutations = StopTraceRecording();
- size_t TBMWidth =
- std::min((size_t)Options.TBMWidth, NumTraceBasedMutations);
- size_t TBMDepth =
- std::min((size_t)Options.TBMDepth, NumTraceBasedMutations);
- Unit BackUp = *U;
- for (size_t w = 0; w < TBMWidth; w++) {
- *U = BackUp;
- for (size_t d = 0; d < TBMDepth; d++) {
- TotalNumberOfExecutedTraceBasedMutations++;
- ApplyTraceBasedMutation(USF.GetRand()(NumTraceBasedMutations), U);
- RunOneAndUpdateCorpus(*U);
- }
+ U.resize(NewSize);
+ if (i == 0)
+ StartTraceRecording();
+ RunOneAndUpdateCorpus(U);
+ StopTraceRecording();
+ }
+}
+
+// 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::ChooseUnitIdxToMutate() {
+ size_t N = Corpus.size();
+ size_t Total = (N + 1) * N / 2;
+ size_t R = USF.GetRand()(Total);
+ size_t IdxBeg = 0, IdxEnd = N;
+ // Binary search.
+ while (IdxEnd - IdxBeg >= 2) {
+ size_t Idx = IdxBeg + (IdxEnd - IdxBeg) / 2;
+ if (R > (Idx + 1) * Idx / 2)
+ IdxBeg = Idx;
+ else
+ IdxEnd = Idx;
+ }
+ assert(IdxBeg < N);
+ return IdxBeg;
+}
+
+// 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) {
+ CurrentUnit = U;
+ RunOne(U);
+ }
+ PrintStats("MERGE ");
+ Options.PrintNEW = true;
+ size_t NumMerged = 0;
+ for (auto &U : Corpus) {
+ CurrentUnit = U;
+ if (RunOne(U)) {
+ PrintStatusForNewUnit(U);
+ NumMerged++;
+ WriteToOutputCorpus(U);