[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