forked from OSchip/llvm-project
[libFuzzer] Evenly select inputs to cross over with from the corpus regardless of the input's coverage.
This patch adds an option "cross_over_uniform_dist", which, if 1, considers all inputs in the corpus for the crossover input selection. More specifically, this patch uses a uniform distribution of all inputs in the corpus for the CrossOver input selection. Note that input selection for mutation is still fully determined by the scheduling policy (i.e., vanilla or Entropic); the uniform distribution only applies to the secondary input selection, only for the crossover mutation of the base input chosen by the scheduling policy. This way the corpus inputs that have useful fragments in them, even though they are deprioritized by the scheduling policy, have chances of getting mixed with other inputs that are prioritized and selected as base input for mutation. Differential Revision: https://reviews.llvm.org/D86954
This commit is contained in:
parent
a09eef113f
commit
b53243e194
|
@ -270,6 +270,15 @@ public:
|
|||
return II;
|
||||
}
|
||||
|
||||
InputInfo &ChooseUnitToCrossOverWith(Random &Rand, bool UniformDist) {
|
||||
if (!UniformDist) {
|
||||
return ChooseUnitToMutate(Rand);
|
||||
}
|
||||
InputInfo &II = *Inputs[Rand(Inputs.size())];
|
||||
assert(!II.U.empty());
|
||||
return II;
|
||||
}
|
||||
|
||||
// Returns an index of random unit from the corpus to mutate.
|
||||
size_t ChooseUnitIdxToMutate(Random &Rand) {
|
||||
UpdateCorpusDistribution(Rand);
|
||||
|
|
|
@ -680,6 +680,7 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
|
|||
Options.IgnoreCrashes = Flags.ignore_crashes;
|
||||
Options.MaxTotalTimeSec = Flags.max_total_time;
|
||||
Options.DoCrossOver = Flags.cross_over;
|
||||
Options.CrossOverUniformDist = Flags.cross_over_uniform_dist;
|
||||
Options.MutateDepth = Flags.mutate_depth;
|
||||
Options.ReduceDepth = Flags.reduce_depth;
|
||||
Options.UseCounters = Flags.use_counters;
|
||||
|
|
|
@ -28,6 +28,16 @@ FUZZER_FLAG_INT(keep_seed, 0, "If 1, keep seed inputs in the corpus even if "
|
|||
"seed inputs will never be reduced. This option can be useful when seeds are"
|
||||
"not properly formed for the fuzz target but still have useful snippets.")
|
||||
FUZZER_FLAG_INT(cross_over, 1, "If 1, cross over inputs.")
|
||||
FUZZER_FLAG_INT(cross_over_uniform_dist, 0, "Experimental. If 1, use a "
|
||||
"uniform probability distribution when choosing inputs to cross over with. "
|
||||
"Some of the inputs in the corpus may never get chosen for mutation "
|
||||
"depending on the input mutation scheduling policy. With this flag, all "
|
||||
"inputs, regardless of the input mutation scheduling policy, can be chosen "
|
||||
"as an input to cross over with. This can be particularly useful with "
|
||||
"|keep_seed==1|; all the initial seed inputs, even though they do not "
|
||||
"increase coverage because they are not properly formed, will still be "
|
||||
"chosen as an input to cross over with.")
|
||||
|
||||
FUZZER_FLAG_INT(mutate_depth, 5,
|
||||
"Apply this number of consecutive mutations to each input.")
|
||||
FUZZER_FLAG_INT(reduce_depth, 0, "Experimental/internal. "
|
||||
|
|
|
@ -666,8 +666,11 @@ void Fuzzer::MutateAndTestOne() {
|
|||
MD.StartMutationSequence();
|
||||
|
||||
auto &II = Corpus.ChooseUnitToMutate(MD.GetRand());
|
||||
if (Options.DoCrossOver)
|
||||
MD.SetCrossOverWith(&Corpus.ChooseUnitToMutate(MD.GetRand()).U);
|
||||
if (Options.DoCrossOver) {
|
||||
auto &CrossOverII = Corpus.ChooseUnitToCrossOverWith(
|
||||
MD.GetRand(), Options.CrossOverUniformDist);
|
||||
MD.SetCrossOverWith(&CrossOverII.U);
|
||||
}
|
||||
const auto &U = II.U;
|
||||
memcpy(BaseSha1, II.Sha1, sizeof(BaseSha1));
|
||||
assert(CurrentUnitData);
|
||||
|
|
|
@ -31,6 +31,7 @@ struct FuzzingOptions {
|
|||
int RssLimitMb = 0;
|
||||
int MallocLimitMb = 0;
|
||||
bool DoCrossOver = true;
|
||||
bool CrossOverUniformDist = false;
|
||||
int MutateDepth = 5;
|
||||
bool ReduceDepth = false;
|
||||
bool UseCounters = false;
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
REQUIRES: linux, x86_64
|
||||
RUN: %cpp_compiler %S/KeepSeedTest.cpp -o %t-CrossOverUniformDistTest
|
||||
|
||||
RUN: rm -rf %t-corpus
|
||||
RUN: mkdir %t-corpus
|
||||
RUN: echo -n "@SELECT" > %t-corpus/A
|
||||
RUN: echo -n "@FROM WHERE" > %t-corpus/B
|
||||
|
||||
RUN: not %run %t-CrossOverUniformDistTest -keep_seed=1 -cross_over_uniform_dist=1 -seed=1 -runs=2000000 %t-corpus 2>&1 | FileCheck %s
|
||||
CHECK: BINGO
|
||||
|
||||
RUN: rm -rf %t-corpus
|
||||
RUN: mkdir %t-corpus
|
||||
RUN: echo -n "@SELECT" > %t-corpus/A
|
||||
RUN: echo -n "@FROM WHERE" > %t-corpus/B
|
||||
RUN: %run %t-CrossOverUniformDistTest -keep_seed=1 -seed=1 -runs=2000000 %t-corpus 2>&1
|
Loading…
Reference in New Issue