[compiler-rt] e2e38fc - Entropic: Boosting LibFuzzer Performance
Matt Morehouse via llvm-commits
llvm-commits at lists.llvm.org
Thu May 21 10:45:51 PDT 2020
Fix in 353e5aa42dfee3f119fd1790509ea35a280295f7
On Wed, May 20, 2020 at 6:43 PM Richard Smith <richard at metafoo.co.uk> wrote:
> On Tue, 19 May 2020 at 10:31, Matt Morehouse via llvm-commits <
> llvm-commits at lists.llvm.org> wrote:
>
>>
>> Author: Matt Morehouse
>> Date: 2020-05-19T10:28:57-07:00
>> New Revision: e2e38fca64e49d684de0b100437fe2f227f8fcdd
>>
>> URL:
>> https://github.com/llvm/llvm-project/commit/e2e38fca64e49d684de0b100437fe2f227f8fcdd
>> DIFF:
>> https://github.com/llvm/llvm-project/commit/e2e38fca64e49d684de0b100437fe2f227f8fcdd.diff
>>
>> LOG: Entropic: Boosting LibFuzzer Performance
>>
>> Summary:
>> This is collaboration between Marcel Boehme @ Monash, Australia and
>> Valentin Manès plus Sang Kil Cha @ KAIST, South Korea.
>>
>> We have made a few modifications to boost LibFuzzer performance by
>> changing how weights are assigned to the seeds in the corpus. Essentially,
>> seeds that reveal more "information" about globally rare features are
>> assigned a higher weight. Our results on the Fuzzer Test Suite seem quite
>> promising. In terms of bug finding, our Entropic patch usually finds the
>> same errors much faster and in more runs. In terms of coverage, our version
>> Entropic achieves the same coverage in less than half the time for the
>> majority of subjects. For the lack of space, we shared more detailed
>> performance results directly with @kcc. We'll publish the preprint with all
>> the technical details as soon as it is accepted. Happy to share if you drop
>> us an email.
>>
>> There should be plenty of opportunities to optimise further. For
>> instance, while Entropic achieves the same coverage in less than half the
>> time, Entropic has a much lower #execs per second. We ran the perf-tool and
>> found a few performance bottlenecks.
>>
>> Thanks for open-sourcing LibFuzzer (and the entire LLVM Compiler
>> Infrastructure)! This has been such a tremendous help to my research.
>>
>> Patch By: Marcel Boehme
>>
>> Reviewers: kcc, metzman, morehouse, Dor1s, vitalybuka
>>
>> Reviewed By: kcc
>>
>> Subscribers: dgg5503, Valentin, llvm-commits, kcc
>>
>> Tags: #llvm
>>
>> Differential Revision: https://reviews.llvm.org/D73776
>>
>> Added:
>>
>>
>> Modified:
>> compiler-rt/lib/fuzzer/FuzzerCorpus.h
>> compiler-rt/lib/fuzzer/FuzzerDriver.cpp
>> compiler-rt/lib/fuzzer/FuzzerFlags.def
>> compiler-rt/lib/fuzzer/FuzzerLoop.cpp
>> compiler-rt/lib/fuzzer/FuzzerOptions.h
>> compiler-rt/lib/fuzzer/tests/FuzzerUnittest.cpp
>>
>> Removed:
>>
>>
>>
>>
>> ################################################################################
>> diff --git a/compiler-rt/lib/fuzzer/FuzzerCorpus.h
>> b/compiler-rt/lib/fuzzer/FuzzerCorpus.h
>> index 6a95ef3a8e64..54d1e09ec6df 100644
>> --- a/compiler-rt/lib/fuzzer/FuzzerCorpus.h
>> +++ b/compiler-rt/lib/fuzzer/FuzzerCorpus.h
>> @@ -38,12 +38,102 @@ struct InputInfo {
>> bool HasFocusFunction = false;
>> Vector<uint32_t> UniqFeatureSet;
>> Vector<uint8_t> DataFlowTraceForFocusFunction;
>> + // Power schedule.
>> + bool NeedsEnergyUpdate = false;
>> + double Energy = 0.0;
>> + size_t SumIncidence = 0;
>> + Vector<std::pair<uint32_t, uint16_t>> FeatureFreqs;
>> +
>> + // Delete feature Idx and its frequency from FeatureFreqs.
>> + bool DeleteFeatureFreq(uint32_t Idx) {
>> + if (FeatureFreqs.empty())
>> + return false;
>> +
>> + // Binary search over local feature frequencies sorted by index.
>> + auto Lower = std::lower_bound(FeatureFreqs.begin(),
>> FeatureFreqs.end(),
>> + std::pair<uint32_t, uint16_t>(Idx, 0));
>> +
>> + if (Lower != FeatureFreqs.end() && Lower->first == Idx) {
>> + FeatureFreqs.erase(Lower);
>> + return true;
>> + }
>> + return false;
>> + }
>> +
>> + // Assign more energy to a high-entropy seed, i.e., that reveals more
>> + // information about the globally rare features in the neighborhood
>> + // of the seed. Since we do not know the entropy of a seed that has
>> + // never been executed we assign fresh seeds maximum entropy and
>> + // let II->Energy approach the true entropy from above.
>> + void UpdateEnergy(size_t GlobalNumberOfFeatures) {
>> + Energy = 0.0;
>> + SumIncidence = 0;
>> +
>> + // Apply add-one smoothing to locally discovered features.
>> + for (auto F : FeatureFreqs) {
>> + size_t LocalIncidence = F.second + 1;
>> + Energy -= LocalIncidence * logl(LocalIncidence);
>> + SumIncidence += LocalIncidence;
>> + }
>> +
>> + // Apply add-one smoothing to locally undiscovered features.
>> + // PreciseEnergy -= 0; // since logl(1.0) == 0)
>> + SumIncidence += (GlobalNumberOfFeatures - FeatureFreqs.size());
>> +
>> + // Add a single locally abundant feature apply add-one smoothing.
>> + size_t AbdIncidence = NumExecutedMutations + 1;
>> + Energy -= AbdIncidence * logl(AbdIncidence);
>> + SumIncidence += AbdIncidence;
>> +
>> + // Normalize.
>> + if (SumIncidence != 0)
>> + Energy = (Energy / SumIncidence) + logl(SumIncidence);
>> + }
>> +
>> + // Increment the frequency of the feature Idx.
>> + void UpdateFeatureFrequency(uint32_t Idx) {
>> + NeedsEnergyUpdate = true;
>> +
>> + // The local feature frequencies is an ordered vector of pairs.
>> + // If there are no local feature frequencies, push_back preserves
>> order.
>> + // Set the feature frequency for feature Idx32 to 1.
>> + if (FeatureFreqs.empty()) {
>> + FeatureFreqs.push_back(std::pair<uint32_t, uint16_t>(Idx, 1));
>> + return;
>> + }
>> +
>> + // Binary search over local feature frequencies sorted by index.
>> + auto Lower = std::lower_bound(FeatureFreqs.begin(),
>> FeatureFreqs.end(),
>> + std::pair<uint32_t, uint16_t>(Idx, 0));
>> +
>> + // If feature Idx32 already exists, increment its frequency.
>> + // Otherwise, insert a new pair right after the next lower index.
>> + if (Lower != FeatureFreqs.end() && Lower->first == Idx) {
>> + Lower->second++;
>> + } else {
>> + FeatureFreqs.insert(Lower, std::pair<uint32_t, uint16_t>(Idx, 1));
>> + }
>> + }
>> +};
>> +
>> +struct EntropicOptions {
>> + bool Enabled;
>> + size_t NumberOfRarestFeatures;
>> + size_t FeatureFrequencyThreshold;
>> };
>>
>> class InputCorpus {
>> - static const size_t kFeatureSetSize = 1 << 21;
>> - public:
>> - InputCorpus(const std::string &OutputCorpus) :
>> OutputCorpus(OutputCorpus) {
>> + static const uint32_t kFeatureSetSize = 1 << 21;
>> + static const uint8_t kMaxMutationFactor = 20;
>> + static const size_t kSparseEnergyUpdates = 100;
>> +
>> + size_t NumExecutedMutations = 0;
>> +
>> + EntropicOptions Entropic;
>> +
>> +public:
>> + InputCorpus(const std::string &OutputCorpus, EntropicOptions Entropic)
>> + : Entropic(Entropic), OutputCorpus(OutputCorpus) {
>> memset(InputSizesPerFeature, 0, sizeof(InputSizesPerFeature));
>> memset(SmallestElementPerFeature, 0,
>> sizeof(SmallestElementPerFeature));
>> }
>> @@ -70,6 +160,7 @@ class InputCorpus {
>> Res = std::max(Res, II->U.size());
>> return Res;
>> }
>> + void IncrementNumExecutedMutations() { NumExecutedMutations++; }
>>
>> size_t NumInputsThatTouchFocusFunction() {
>> return std::count_if(Inputs.begin(), Inputs.end(), [](const
>> InputInfo *II) {
>> @@ -99,6 +190,10 @@ class InputCorpus {
>> II.MayDeleteFile = MayDeleteFile;
>> II.UniqFeatureSet = FeatureSet;
>> II.HasFocusFunction = HasFocusFunction;
>> + // Assign maximal energy to the new seed.
>> + II.Energy = RareFeatures.empty() ? 1.0 : log(RareFeatures.size());
>> + II.SumIncidence = RareFeatures.size();
>> + II.NeedsEnergyUpdate = false;
>> std::sort(II.UniqFeatureSet.begin(), II.UniqFeatureSet.end());
>> ComputeSHA1(U.data(), U.size(), II.Sha1);
>> auto Sha1Str = Sha1ToString(II.Sha1);
>> @@ -111,7 +206,7 @@ class InputCorpus {
>> // But if we don't, we'll use the DFT of its base input.
>> if (II.DataFlowTraceForFocusFunction.empty() && BaseII)
>> II.DataFlowTraceForFocusFunction =
>> BaseII->DataFlowTraceForFocusFunction;
>> - UpdateCorpusDistribution();
>> + DistributionNeedsUpdate = true;
>> PrintCorpus();
>> // ValidateFeatureSet();
>> return &II;
>> @@ -162,7 +257,7 @@ class InputCorpus {
>> Hashes.insert(Sha1ToString(II->Sha1));
>> II->U = U;
>> II->Reduced = true;
>> - UpdateCorpusDistribution();
>> + DistributionNeedsUpdate = true;
>> }
>>
>> bool HasUnit(const Unit &U) { return Hashes.count(Hash(U)); }
>> @@ -175,6 +270,7 @@ class InputCorpus {
>>
>> // Returns an index of random unit from the corpus to mutate.
>> size_t ChooseUnitIdxToMutate(Random &Rand) {
>> + UpdateCorpusDistribution(Rand);
>> size_t Idx = static_cast<size_t>(CorpusDistribution(Rand));
>> assert(Idx < Inputs.size());
>> return Idx;
>> @@ -210,10 +306,65 @@ class InputCorpus {
>> InputInfo &II = *Inputs[Idx];
>> DeleteFile(II);
>> Unit().swap(II.U);
>> + II.Energy = 0.0;
>> + II.NeedsEnergyUpdate = false;
>> + DistributionNeedsUpdate = true;
>> if (FeatureDebug)
>> Printf("EVICTED %zd\n", Idx);
>> }
>>
>> + void AddRareFeature(uint32_t Idx) {
>> + // Maintain *at least* TopXRarestFeatures many rare features
>> + // and all features with a frequency below ConsideredRare.
>> + // Remove all other features.
>> + while (RareFeatures.size() > Entropic.NumberOfRarestFeatures &&
>> + FreqOfMostAbundantRareFeature >
>> Entropic.FeatureFrequencyThreshold) {
>> +
>> + // Find most and second most abbundant feature.
>> + uint32_t MostAbundantRareFeatureIndices[2] = {RareFeatures[0],
>> + RareFeatures[0]};
>> + size_t Delete = 0;
>> + for (size_t i = 0; i < RareFeatures.size(); i++) {
>> + uint32_t Idx2 = RareFeatures[i];
>> + if (GlobalFeatureFreqs[Idx2] >=
>> + GlobalFeatureFreqs[MostAbundantRareFeatureIndices[0]]) {
>> + MostAbundantRareFeatureIndices[1] =
>> MostAbundantRareFeatureIndices[0];
>> + MostAbundantRareFeatureIndices[0] = Idx2;
>> + Delete = i;
>> + }
>> + }
>> +
>> + // Remove most abundant rare feature.
>> + RareFeatures[Delete] = RareFeatures.back();
>> + RareFeatures.pop_back();
>> +
>> + for (auto II : Inputs) {
>> + if (II->DeleteFeatureFreq(MostAbundantRareFeatureIndices[0]))
>> + II->NeedsEnergyUpdate = true;
>> + }
>> +
>> + // Set 2nd most abundant as the new most abundant feature count.
>> + FreqOfMostAbundantRareFeature =
>> + GlobalFeatureFreqs[MostAbundantRareFeatureIndices[1]];
>> + }
>> +
>> + // Add rare feature, handle collisions, and update energy.
>> + RareFeatures.push_back(Idx);
>> + GlobalFeatureFreqs[Idx] = 0;
>> + for (auto II : Inputs) {
>> + II->DeleteFeatureFreq(Idx);
>> +
>> + // Apply add-one smoothing to this locally undiscovered feature.
>> + // Zero energy seeds will never be fuzzed and remain zero energy.
>> + if (II->Energy > 0.0) {
>> + II->SumIncidence += 1;
>> + II->Energy += logl(II->SumIncidence) / II->SumIncidence;
>> + }
>> + }
>> +
>> + DistributionNeedsUpdate = true;
>> + }
>> +
>> bool AddFeature(size_t Idx, uint32_t NewSize, bool Shrink) {
>> assert(NewSize);
>> Idx = Idx % kFeatureSetSize;
>> @@ -228,6 +379,8 @@ class InputCorpus {
>> DeleteInput(OldIdx);
>> } else {
>> NumAddedFeatures++;
>> + if (Entropic.Enabled)
>> + AddRareFeature((uint32_t)Idx);
>> }
>> NumUpdatedFeatures++;
>> if (FeatureDebug)
>> @@ -239,6 +392,30 @@ class InputCorpus {
>> return false;
>> }
>>
>> + // Increment frequency of feature Idx globally and locally.
>> + void UpdateFeatureFrequency(InputInfo *II, size_t Idx) {
>> + uint32_t Idx32 = Idx % kFeatureSetSize;
>> +
>> + // Saturated increment.
>> + if (GlobalFeatureFreqs[Idx32] == 0xFFFF)
>> + return;
>> + uint16_t Freq = GlobalFeatureFreqs[Idx32]++;
>> +
>> + // Skip if abundant.
>> + if (Freq > FreqOfMostAbundantRareFeature ||
>> + std::find(RareFeatures.begin(), RareFeatures.end(), Idx32) ==
>> + RareFeatures.end())
>> + return;
>> +
>> + // Update global frequencies.
>> + if (Freq == FreqOfMostAbundantRareFeature)
>> + FreqOfMostAbundantRareFeature++;
>> +
>> + // Update local frequencies.
>> + if (II)
>> + II->UpdateFeatureFrequency(Idx32);
>> + }
>> +
>> size_t NumFeatures() const { return NumAddedFeatures; }
>> size_t NumFeatureUpdates() const { return NumUpdatedFeatures; }
>>
>> @@ -265,19 +442,60 @@ class InputCorpus {
>> // Updates the probability distribution for the units in the corpus.
>> // Must be called whenever the corpus or unit weights are changed.
>> //
>> - // Hypothesis: units added to the corpus last are more interesting.
>> - //
>> - // Hypothesis: inputs with infrequent features are more interesting.
>> - void UpdateCorpusDistribution() {
>> + // Hypothesis: inputs that maximize information about globally rare
>> features
>> + // are interesting.
>> + void UpdateCorpusDistribution(Random &Rand) {
>> + // Skip update if no seeds or rare features were added/deleted.
>> + // Sparse updates for local change of feature frequencies,
>> + // i.e., randomly do not skip.
>> + if (!DistributionNeedsUpdate &&
>> + (!Entropic.Enabled || Rand(kSparseEnergyUpdates)))
>> + return;
>> +
>> + DistributionNeedsUpdate = false;
>> +
>> size_t N = Inputs.size();
>> assert(N);
>> Intervals.resize(N + 1);
>> Weights.resize(N);
>> std::iota(Intervals.begin(), Intervals.end(), 0);
>> - for (size_t i = 0; i < N; i++)
>> - Weights[i] = Inputs[i]->NumFeatures
>> - ? (i + 1) * (Inputs[i]->HasFocusFunction ? 1000 :
>> 1)
>> - : 0.;
>> +
>> + bool VanillaSchedule = true;
>> + if (Entropic.Enabled) {
>> + for (auto II : Inputs) {
>> + if (II->NeedsEnergyUpdate && II->Energy != 0.0) {
>> + II->NeedsEnergyUpdate = false;
>> + II->UpdateEnergy(RareFeatures.size());
>> + }
>> + }
>> +
>> + for (size_t i = 0; i < N; i++) {
>> +
>> + if (Inputs[i]->NumFeatures == 0) {
>> + // If the seed doesn't represent any features, assign zero
>> energy.
>> + Weights[i] = 0.;
>> + } else if (Inputs[i]->NumExecutedMutations / kMaxMutationFactor >
>> + NumExecutedMutations / Inputs.size()) {
>> + // If the seed was fuzzed a lot more than average, assign zero
>> energy.
>> + Weights[i] = 0.;
>> + } else {
>> + // Otherwise, simply assign the computed energy.
>> + Weights[i] = Inputs[i]->Energy;
>> + }
>> +
>> + // If energy for all seeds is zero, fall back to vanilla
>> schedule.
>> + if (Weights[i] > 0.0)
>> + VanillaSchedule = false;
>> + }
>> + }
>> +
>> + if (VanillaSchedule) {
>> + for (size_t i = 0; i < N; i++)
>> + Weights[i] = Inputs[i]->NumFeatures
>> + ? (i + 1) * (Inputs[i]->HasFocusFunction ? 1000
>> : 1)
>> + : 0.;
>> + }
>> +
>> if (FeatureDebug) {
>> for (size_t i = 0; i < N; i++)
>> Printf("%zd ", Inputs[i]->NumFeatures);
>> @@ -302,6 +520,11 @@ class InputCorpus {
>> uint32_t InputSizesPerFeature[kFeatureSetSize];
>> uint32_t SmallestElementPerFeature[kFeatureSetSize];
>>
>> + bool DistributionNeedsUpdate = true;
>> + uint16_t FreqOfMostAbundantRareFeature = 0;
>> + uint16_t GlobalFeatureFreqs[kFeatureSetSize] = {};
>> + Vector<uint32_t> RareFeatures;
>> +
>> std::string OutputCorpus;
>> };
>>
>>
>> diff --git a/compiler-rt/lib/fuzzer/FuzzerDriver.cpp
>> b/compiler-rt/lib/fuzzer/FuzzerDriver.cpp
>> index 0d4e468a674b..1a0b2580c5b7 100644
>> --- a/compiler-rt/lib/fuzzer/FuzzerDriver.cpp
>> +++ b/compiler-rt/lib/fuzzer/FuzzerDriver.cpp
>> @@ -708,6 +708,26 @@ int FuzzerDriver(int *argc, char ***argv,
>> UserCallback Callback) {
>> Options.CollectDataFlow = Flags.collect_data_flow;
>> if (Flags.stop_file)
>> Options.StopFile = Flags.stop_file;
>> + Options.Entropic = Flags.entropic;
>> + Options.EntropicFeatureFrequencyThreshold =
>> + (size_t)Flags.entropic_feature_frequency_threshold;
>> + Options.EntropicNumberOfRarestFeatures =
>> + (size_t)Flags.entropic_number_of_rarest_features;
>> + if (Options.Entropic) {
>> + if (!Options.FocusFunction.empty()) {
>> + Printf("ERROR: The parameters `--entropic` and `--focus_function`
>> cannot "
>> + "be used together.\n");
>> + exit(1);
>> + }
>> + Printf("INFO: Running with entropic power schedule (0x%X, %d).\n",
>> + Options.EntropicFeatureFrequencyThreshold,
>> + Options.EntropicNumberOfRarestFeatures);
>> + }
>> + struct EntropicOptions Entropic;
>> + Entropic.Enabled = Options.Entropic;
>> + Entropic.FeatureFrequencyThreshold =
>> + Options.EntropicFeatureFrequencyThreshold;
>> + Entropic.NumberOfRarestFeatures =
>> Options.EntropicNumberOfRarestFeatures;
>>
>> unsigned Seed = Flags.seed;
>> // Initialize Seed.
>> @@ -728,7 +748,7 @@ int FuzzerDriver(int *argc, char ***argv,
>> UserCallback Callback) {
>>
>> Random Rand(Seed);
>> auto *MD = new MutationDispatcher(Rand, Options);
>> - auto *Corpus = new InputCorpus(Options.OutputCorpus);
>> + auto *Corpus = new InputCorpus(Options.OutputCorpus, Entropic);
>> auto *F = new Fuzzer(Callback, *Corpus, *MD, Options);
>>
>> for (auto &U: Dictionary)
>>
>> diff --git a/compiler-rt/lib/fuzzer/FuzzerFlags.def
>> b/compiler-rt/lib/fuzzer/FuzzerFlags.def
>> index d2aaf24587d2..832224a705d2 100644
>> --- a/compiler-rt/lib/fuzzer/FuzzerFlags.def
>> +++ b/compiler-rt/lib/fuzzer/FuzzerFlags.def
>> @@ -153,6 +153,14 @@ FUZZER_FLAG_STRING(focus_function, "Experimental. "
>> "Fuzzing will focus on inputs that trigger calls to this function. "
>> "If -focus_function=auto and -data_flow_trace is used, libFuzzer "
>> "will choose the focus functions automatically.")
>> +FUZZER_FLAG_INT(entropic, 0, "Experimental. Enables entropic power
>> schedule.")
>> +FUZZER_FLAG_INT(entropic_feature_frequency_threshold, 0xFF,
>> "Experimental. If "
>> + "entropic is enabled, all features which are observed less often
>> than "
>> + "the specified value are considered as rare.")
>> +FUZZER_FLAG_INT(entropic_number_of_rarest_features, 100, "Experimental.
>> If "
>> + "entropic is enabled, we keep track of the frequencies only for the
>> "
>> + "Top-X least abundant features (union features that are considered
>> as "
>> + "rare).")
>>
>> FUZZER_FLAG_INT(analyze_dict, 0, "Experimental")
>> FUZZER_DEPRECATED_FLAG(use_clang_coverage)
>>
>> diff --git a/compiler-rt/lib/fuzzer/FuzzerLoop.cpp
>> b/compiler-rt/lib/fuzzer/FuzzerLoop.cpp
>> index 273c62919e89..7c3288fc5750 100644
>> --- a/compiler-rt/lib/fuzzer/FuzzerLoop.cpp
>> +++ b/compiler-rt/lib/fuzzer/FuzzerLoop.cpp
>> @@ -475,6 +475,8 @@ bool Fuzzer::RunOne(const uint8_t *Data, size_t Size,
>> bool MayDeleteFile,
>> TPC.CollectFeatures([&](size_t Feature) {
>> if (Corpus.AddFeature(Feature, Size, Options.Shrink))
>> UniqFeatureSetTmp.push_back(Feature);
>> + if (Options.Entropic)
>> + Corpus.UpdateFeatureFrequency(II, Feature);
>> if (Options.ReduceInputs && II)
>> if (std::binary_search(II->UniqFeatureSet.begin(),
>> II->UniqFeatureSet.end(), Feature))
>> @@ -693,6 +695,7 @@ void Fuzzer::MutateAndTestOne() {
>> assert(NewSize <= CurrentMaxMutationLen && "Mutator return oversized
>> unit");
>> Size = NewSize;
>> II.NumExecutedMutations++;
>> + Corpus.IncrementNumExecutedMutations();
>>
>> bool FoundUniqFeatures = false;
>> bool NewCov = RunOne(CurrentUnitData, Size, /*MayDeleteFile=*/true,
>> &II,
>> @@ -706,6 +709,8 @@ void Fuzzer::MutateAndTestOne() {
>> if (Options.ReduceDepth && !FoundUniqFeatures)
>> break;
>> }
>> +
>> + II.NeedsEnergyUpdate = true;
>> }
>>
>> void Fuzzer::PurgeAllocator() {
>>
>> diff --git a/compiler-rt/lib/fuzzer/FuzzerOptions.h
>> b/compiler-rt/lib/fuzzer/FuzzerOptions.h
>> index beecc980380b..9d975bd61fe7 100644
>> --- a/compiler-rt/lib/fuzzer/FuzzerOptions.h
>> +++ b/compiler-rt/lib/fuzzer/FuzzerOptions.h
>> @@ -44,6 +44,9 @@ struct FuzzingOptions {
>> size_t MaxNumberOfRuns = -1L;
>> int ReportSlowUnits = 10;
>> bool OnlyASCII = false;
>> + bool Entropic = false;
>> + size_t EntropicFeatureFrequencyThreshold = 0xFF;
>> + size_t EntropicNumberOfRarestFeatures = 100;
>> std::string OutputCorpus;
>> std::string ArtifactPrefix = "./";
>> std::string ExactArtifactPath;
>>
>> diff --git a/compiler-rt/lib/fuzzer/tests/FuzzerUnittest.cpp
>> b/compiler-rt/lib/fuzzer/tests/FuzzerUnittest.cpp
>> index 7fc4b9a55b08..b480e9f0fff5 100644
>> --- a/compiler-rt/lib/fuzzer/tests/FuzzerUnittest.cpp
>> +++ b/compiler-rt/lib/fuzzer/tests/FuzzerUnittest.cpp
>> @@ -592,7 +592,8 @@ TEST(FuzzerUtil, Base64) {
>> TEST(Corpus, Distribution) {
>> DataFlowTrace DFT;
>> Random Rand(0);
>> - std::unique_ptr<InputCorpus> C(new InputCorpus(""));
>> + struct EntropicOptions Entropic = {false, 0xFF, 100};
>> + std::unique_ptr<InputCorpus> C(new InputCorpus("", Entropic));
>> size_t N = 10;
>> size_t TriesPerUnit = 1<<16;
>> for (size_t i = 0; i < N; i++)
>> @@ -1050,6 +1051,68 @@ TEST(FuzzerCommand, SetOutput) {
>> EXPECT_EQ(CmdLine, makeCmdLine("", ">thud 2>&1"));
>> }
>>
>> +TEST(Entropic, UpdateFrequency) {
>> + const size_t One = 1, Two = 2;
>> + const size_t FeatIdx1 = 0, FeatIdx2 = 42, FeatIdx3 = 12, FeatIdx4 = 26;
>> + size_t Index;
>> + // Create input corpus with default entropic configuration
>> + struct EntropicOptions Entropic = {true, 0xFF, 100};
>> + std::unique_ptr<InputCorpus> C(new InputCorpus("", Entropic));
>> + InputInfo *II = new InputInfo();
>>
>
> This is leaked.
>
>
>> +
>> + C->AddRareFeature(FeatIdx1);
>> + C->UpdateFeatureFrequency(II, FeatIdx1);
>> + EXPECT_EQ(II->FeatureFreqs.size(), One);
>> + C->AddRareFeature(FeatIdx2);
>> + C->UpdateFeatureFrequency(II, FeatIdx1);
>> + C->UpdateFeatureFrequency(II, FeatIdx2);
>> + EXPECT_EQ(II->FeatureFreqs.size(), Two);
>> + EXPECT_EQ(II->FeatureFreqs[0].second, 2);
>> + EXPECT_EQ(II->FeatureFreqs[1].second, 1);
>> +
>> + C->AddRareFeature(FeatIdx3);
>> + C->AddRareFeature(FeatIdx4);
>> + C->UpdateFeatureFrequency(II, FeatIdx3);
>> + C->UpdateFeatureFrequency(II, FeatIdx3);
>> + C->UpdateFeatureFrequency(II, FeatIdx3);
>> + C->UpdateFeatureFrequency(II, FeatIdx4);
>> +
>> + for (Index = 1; Index < II->FeatureFreqs.size(); Index++)
>> + EXPECT_LT(II->FeatureFreqs[Index - 1].first,
>> II->FeatureFreqs[Index].first);
>> +
>> + II->DeleteFeatureFreq(FeatIdx3);
>> + for (Index = 1; Index < II->FeatureFreqs.size(); Index++)
>> + EXPECT_LT(II->FeatureFreqs[Index - 1].first,
>> II->FeatureFreqs[Index].first);
>> +}
>> +
>> +double SubAndSquare(double X, double Y) {
>> + double R = X - Y;
>> + R = R * R;
>> + return R;
>> +}
>> +
>> +TEST(Entropic, ComputeEnergy) {
>> + const double Precision = 0.01;
>> + struct EntropicOptions Entropic = {true, 0xFF, 100};
>> + std::unique_ptr<InputCorpus> C(new InputCorpus("", Entropic));
>> + InputInfo *II = new InputInfo();
>>
>
> As is this. Please can you fix or revert?
>
>
>> + Vector<std::pair<uint32_t, uint16_t>> FeatureFreqs = {{1, 3}, {2, 3},
>> {3, 3}};
>> + II->FeatureFreqs = FeatureFreqs;
>> + II->NumExecutedMutations = 0;
>> + II->UpdateEnergy(4);
>> + EXPECT_LT(SubAndSquare(II->Energy, 1.450805), Precision);
>> +
>> + II->NumExecutedMutations = 9;
>> + II->UpdateEnergy(5);
>> + EXPECT_LT(SubAndSquare(II->Energy, 1.525496), Precision);
>> +
>> + II->FeatureFreqs[0].second++;
>> + II->FeatureFreqs.push_back(std::pair<uint32_t, uint16_t>(42, 6));
>> + II->NumExecutedMutations = 20;
>> + II->UpdateEnergy(10);
>> + EXPECT_LT(SubAndSquare(II->Energy, 1.792831), Precision);
>> +}
>> +
>> int main(int argc, char **argv) {
>> testing::InitGoogleTest(&argc, argv);
>> return RUN_ALL_TESTS();
>>
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at lists.llvm.org
>> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200521/9b919ff3/attachment.html>
More information about the llvm-commits
mailing list