[compiler-rt] e2e38fc - Entropic: Boosting LibFuzzer Performance
Richard Smith via llvm-commits
llvm-commits at lists.llvm.org
Wed May 20 18:42:53 PDT 2020
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/20200520/42efe89b/attachment.html>
More information about the llvm-commits
mailing list