Index: llvm/trunk/lib/Fuzzer/FuzzerInterface.h =================================================================== --- llvm/trunk/lib/Fuzzer/FuzzerInterface.h +++ llvm/trunk/lib/Fuzzer/FuzzerInterface.h @@ -66,18 +66,6 @@ // Return a random number in range [0,n). size_t operator()(size_t n) { return n ? Rand() % n : 0; } bool RandBool() { return Rand() % 2; } - - // The methods below is to satisfy UniformRandomNumberGenerator: - // http://en.cppreference.com/w/cpp/concept/UniformRandomNumberGenerator\ - - // Returns a random number between 0 and RAND_MAX inclusive. - double operator()() { return operator()(RAND_MAX); } - - // Returns the smallest value that operator() may return. - double min() { return 0; } - - // Returns the largest value that operator() may return. - double max() { return RAND_MAX; } }; // Using libc's stand/rand. Index: llvm/trunk/lib/Fuzzer/FuzzerInternal.h =================================================================== --- llvm/trunk/lib/Fuzzer/FuzzerInternal.h +++ llvm/trunk/lib/Fuzzer/FuzzerInternal.h @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -201,7 +200,7 @@ bool PrintNewCovPcs = false; }; Fuzzer(UserSuppliedFuzzer &USF, FuzzingOptions Options); - void AddToCorpus(const Unit &U) { Corpus.push_back(U); UpdateCorpusDistribution(); } + void AddToCorpus(const Unit &U) { Corpus.push_back(U); } size_t ChooseUnitIdxToMutate(); const Unit &ChooseUnitToMutate() { return Corpus[ChooseUnitIdxToMutate()]; }; void Loop(); @@ -242,9 +241,6 @@ void WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix); void PrintStats(const char *Where, const char *End = "\n"); void PrintStatusForNewUnit(const Unit &U); - // Updates the probability distribution for the units in the corpus. - // Must be called whenever the corpus or unit weights are changed. - void UpdateCorpusDistribution(); void SyncCorpus(); @@ -284,7 +280,6 @@ return Res; } - std::piecewise_constant_distribution CorpusDistribution; UserSuppliedFuzzer &USF; FuzzingOptions Options; system_clock::time_point ProcessStartTime = system_clock::now(); Index: llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp =================================================================== --- llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp +++ llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp @@ -163,7 +163,6 @@ if (UnitHashesAddedToCorpus.insert(Hash(X)).second) { if (RunOne(X)) { Corpus.push_back(X); - UpdateCorpusDistribution(); PrintStats("RELOAD"); } } @@ -201,7 +200,6 @@ } } Corpus = NewCorpus; - UpdateCorpusDistribution(); for (auto &X : Corpus) UnitHashesAddedToCorpus.insert(Hash(X)); PrintStats("INITED"); @@ -349,7 +347,6 @@ void Fuzzer::ReportNewCoverage(const Unit &U) { Corpus.push_back(U); - UpdateCorpusDistribution(); UnitHashesAddedToCorpus.insert(Hash(U)); USF.GetMD().RecordSuccessfulMutationSequence(); PrintStatusForNewUnit(U); @@ -412,11 +409,22 @@ // 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 weight to the more recent units. +// This function gives more wieght to the more recent units. size_t Fuzzer::ChooseUnitIdxToMutate() { - size_t Idx = static_cast(CorpusDistribution(USF.GetRand())); - assert(Idx < Corpus.size()); - return Idx; + 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. @@ -439,7 +447,6 @@ std::vector SavedCorpus; SavedCorpus.swap(Corpus); Corpus.push_back(U); - UpdateCorpusDistribution(); assert(Corpus.size() == 1); RunOne(U); PrintStats("DRILL "); @@ -503,14 +510,4 @@ ExecuteCommand(Options.SyncCommand + " " + Options.OutputCorpus); } -void Fuzzer::UpdateCorpusDistribution() { - size_t N = Corpus.size(); - std::vector Intervals(N+1); - std::vector Weights(N); - std::iota(Intervals.begin(), Intervals.end(), 0); - std::iota(Weights.begin(), Weights.end(), 1); - CorpusDistribution = std::piecewise_constant_distribution( - Intervals.begin(), Intervals.end(), Weights.begin()); -} - } // namespace fuzzer Index: llvm/trunk/lib/Fuzzer/test/FuzzerUnittest.cpp =================================================================== --- llvm/trunk/lib/Fuzzer/test/FuzzerUnittest.cpp +++ llvm/trunk/lib/Fuzzer/test/FuzzerUnittest.cpp @@ -6,7 +6,7 @@ // For now, have LLVMFuzzerTestOneInput just to make it link. // Later we may want to make unittests that actually call LLVMFuzzerTestOneInput. -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { +extern "C" void LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { abort(); } @@ -400,23 +400,3 @@ EXPECT_EQ("YWJjeHk=", Base64({'a', 'b', 'c', 'x', 'y'})); EXPECT_EQ("YWJjeHl6", Base64({'a', 'b', 'c', 'x', 'y', 'z'})); } - -TEST(Corpus, Distribution) { - FuzzerRandomLibc Rand(0); - SimpleUserSuppliedFuzzer USF(&Rand, LLVMFuzzerTestOneInput); - Fuzzer::FuzzingOptions Options; - Fuzzer Fuzz(USF, Options); - size_t N = 10; - size_t TriesPerUnit = 1<<20; - for (size_t i = 0; i < N; i++) { - Fuzz.AddToCorpus(Unit{ static_cast(i) }); - } - std::vector Hist(N); - for (size_t i = 0; i < N * TriesPerUnit; i++) { - Hist[Fuzz.ChooseUnitIdxToMutate()]++; - } - for (size_t i = 0; i < N; i++) { - // A weak sanity check that every unit gets invoked. - EXPECT_GT(Hist[i], TriesPerUnit / N / 3); - } -}