[libFuzzer] when choosing the next unit to mutate, give some preference to the most recent units (they are more likely to be interesting)

llvm-svn: 252097
This commit is contained in:
Kostya Serebryany 2015-11-04 23:22:25 +00:00
parent 58a7e659d9
commit e692621a9d
2 changed files with 46 additions and 26 deletions

View File

@ -99,6 +99,7 @@ class Fuzzer {
};
Fuzzer(UserSuppliedFuzzer &USF, FuzzingOptions Options);
void AddToCorpus(const Unit &U) { Corpus.push_back(U); }
size_t ChooseUnitToMutate();
void Loop();
void ShuffleAndMinimize();
void InitializeTraceState();

View File

@ -346,12 +346,32 @@ void Fuzzer::MutateAndTestOne(Unit *U) {
}
}
// 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 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;
}
void Fuzzer::Loop() {
for (auto &U: Options.Dictionary)
USF.GetMD().AddWordToDictionary(U.data(), U.size());
while (true) {
for (size_t J1 = 0; J1 < Corpus.size(); J1++) {
size_t J1 = ChooseUnitToMutate();;
SyncCorpus();
RereadOutputCorpus();
if (TotalNumberOfRuns >= Options.MaxNumberOfRuns)
@ -363,7 +383,7 @@ void Fuzzer::Loop() {
CurrentUnit = Corpus[J1];
// Optionally, cross with another unit.
if (Options.DoCrossOver && USF.GetRand().RandBool()) {
size_t J2 = USF.GetRand()(Corpus.size());
size_t J2 = ChooseUnitToMutate();
if (!Corpus[J1].empty() && !Corpus[J2].empty()) {
assert(!Corpus[J2].empty());
CurrentUnit.resize(Options.MaxLen);
@ -379,7 +399,6 @@ void Fuzzer::Loop() {
// Perform several mutations and runs.
MutateAndTestOne(&CurrentUnit);
}
}
}
void Fuzzer::SyncCorpus() {