[compiler-rt] 6708186 - [crt][fuzzer] Fix up various numeric conversions

Marco Vanotti via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 11 16:01:37 PST 2021


Author: Aaron Green
Date: 2021-03-11T16:01:28-08:00
New Revision: 6708186c91dd7c5463b83091ade40e721c0e62ab

URL: https://github.com/llvm/llvm-project/commit/6708186c91dd7c5463b83091ade40e721c0e62ab
DIFF: https://github.com/llvm/llvm-project/commit/6708186c91dd7c5463b83091ade40e721c0e62ab.diff

LOG: [crt][fuzzer] Fix up various numeric conversions

Attempting to build a standalone libFuzzer in Fuchsia's default toolchain for the purpose of cross-compiling the unit tests  revealed a number of not-quite-proper type conversions. Fuchsia's toolchain include `-std=c++17` and `-Werror`, among others, leading to many errors like `-Wshorten-64-to-32`, `-Wimplicit-float-conversion`, etc.

Most of these have been addressed by simply making the conversion explicit with a `static_cast`. These typically fell into one of two categories: 1) conversions between types where high precision isn't critical, e.g. the "energy" calculations for `InputInfo`, and 2) conversions where the values will never reach the bits being truncated, e.g. `DftTimeInSeconds` is not going to exceed 136 years.

The major exception to this is the number of features: there are several places that treat features as `size_t`, and others as `uint32_t`. This change makes the decision to cap the features at 32 bits. The maximum value of a feature as produced by `TracePC::CollectFeatures` is roughly:
  (NumPCsInPCTables + ValueBitMap::kMapSizeInBits + ExtraCountersBegin() - ExtraCountersEnd() + log2(SIZE_MAX)) * 8

It's conceivable for extremely large targets and/or extra counters that this limit could be reached. This shouldn't break fuzzing, but it will cause certain features to collide and lower the fuzzers overall precision. To address this, this change adds a warning to TracePC::PrintModuleInfo about excessive feature size if it is detected, and recommends refactoring the fuzzer into several smaller ones.

Reviewed By: morehouse

Differential Revision: https://reviews.llvm.org/D97992

Added: 
    

Modified: 
    compiler-rt/lib/fuzzer/FuzzerBuiltins.h
    compiler-rt/lib/fuzzer/FuzzerBuiltinsMsvc.h
    compiler-rt/lib/fuzzer/FuzzerCorpus.h
    compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.cpp
    compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.h
    compiler-rt/lib/fuzzer/FuzzerDictionary.h
    compiler-rt/lib/fuzzer/FuzzerDriver.cpp
    compiler-rt/lib/fuzzer/FuzzerFork.cpp
    compiler-rt/lib/fuzzer/FuzzerLoop.cpp
    compiler-rt/lib/fuzzer/FuzzerMerge.cpp
    compiler-rt/lib/fuzzer/FuzzerMutate.cpp
    compiler-rt/lib/fuzzer/FuzzerRandom.h
    compiler-rt/lib/fuzzer/FuzzerSHA1.cpp
    compiler-rt/lib/fuzzer/FuzzerTracePC.cpp
    compiler-rt/lib/fuzzer/FuzzerTracePC.h
    compiler-rt/lib/fuzzer/FuzzerUtil.cpp
    compiler-rt/lib/fuzzer/FuzzerUtil.h
    compiler-rt/lib/fuzzer/FuzzerUtilFuchsia.cpp

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/fuzzer/FuzzerBuiltins.h b/compiler-rt/lib/fuzzer/FuzzerBuiltins.h
index 4c0ada82662d..ce0bd5cb47f4 100644
--- a/compiler-rt/lib/fuzzer/FuzzerBuiltins.h
+++ b/compiler-rt/lib/fuzzer/FuzzerBuiltins.h
@@ -26,7 +26,6 @@ inline uint32_t Bswap(uint32_t x) { return __builtin_bswap32(x); }
 inline uint64_t Bswap(uint64_t x) { return __builtin_bswap64(x); }
 
 inline uint32_t Clzll(unsigned long long X) { return __builtin_clzll(X); }
-inline uint32_t Clz(unsigned long long X) { return __builtin_clz(X); }
 inline int Popcountll(unsigned long long X) { return __builtin_popcountll(X); }
 
 }  // namespace fuzzer

diff  --git a/compiler-rt/lib/fuzzer/FuzzerBuiltinsMsvc.h b/compiler-rt/lib/fuzzer/FuzzerBuiltinsMsvc.h
index c5bec9787d8e..ab191b60ef6e 100644
--- a/compiler-rt/lib/fuzzer/FuzzerBuiltinsMsvc.h
+++ b/compiler-rt/lib/fuzzer/FuzzerBuiltinsMsvc.h
@@ -52,12 +52,6 @@ inline uint32_t Clzll(uint64_t X) {
   return 64;
 }
 
-inline uint32_t Clz(uint32_t X) {
-  unsigned long LeadZeroIdx = 0;
-  if (_BitScanReverse(&LeadZeroIdx, X)) return 31 - LeadZeroIdx;
-  return 32;
-}
-
 inline int Popcountll(unsigned long long X) {
 #if !defined(_M_ARM) && !defined(_M_X64)
   return __popcnt(X) + __popcnt(X >> 32);

diff  --git a/compiler-rt/lib/fuzzer/FuzzerCorpus.h b/compiler-rt/lib/fuzzer/FuzzerCorpus.h
index daea4f5213b1..f8c126072c96 100644
--- a/compiler-rt/lib/fuzzer/FuzzerCorpus.h
+++ b/compiler-rt/lib/fuzzer/FuzzerCorpus.h
@@ -44,7 +44,7 @@ struct InputInfo {
   // Power schedule.
   bool NeedsEnergyUpdate = false;
   double Energy = 0.0;
-  size_t SumIncidence = 0;
+  double SumIncidence = 0.0;
   Vector<std::pair<uint32_t, uint16_t>> FeatureFreqs;
 
   // Delete feature Idx and its frequency from FeatureFreqs.
@@ -74,27 +74,28 @@ struct InputInfo {
   void UpdateEnergy(size_t GlobalNumberOfFeatures, bool ScalePerExecTime,
                     std::chrono::microseconds AverageUnitExecutionTime) {
     Energy = 0.0;
-    SumIncidence = 0;
+    SumIncidence = 0.0;
 
     // Apply add-one smoothing to locally discovered features.
     for (auto F : FeatureFreqs) {
-      size_t LocalIncidence = F.second + 1;
-      Energy -= LocalIncidence * logl(LocalIncidence);
+      double LocalIncidence = F.second + 1;
+      Energy -= LocalIncidence * log(LocalIncidence);
       SumIncidence += LocalIncidence;
     }
 
     // Apply add-one smoothing to locally undiscovered features.
-    //   PreciseEnergy -= 0; // since logl(1.0) == 0)
-    SumIncidence += (GlobalNumberOfFeatures - FeatureFreqs.size());
+    //   PreciseEnergy -= 0; // since log(1.0) == 0)
+    SumIncidence +=
+        static_cast<double>(GlobalNumberOfFeatures - FeatureFreqs.size());
 
     // Add a single locally abundant feature apply add-one smoothing.
-    size_t AbdIncidence = NumExecutedMutations + 1;
-    Energy -= AbdIncidence * logl(AbdIncidence);
+    double AbdIncidence = static_cast<double>(NumExecutedMutations + 1);
+    Energy -= AbdIncidence * log(AbdIncidence);
     SumIncidence += AbdIncidence;
 
     // Normalize.
     if (SumIncidence != 0)
-      Energy = (Energy / SumIncidence) + logl(SumIncidence);
+      Energy = Energy / SumIncidence + log(SumIncidence);
 
     if (ScalePerExecTime) {
       // Scaling to favor inputs with lower execution time.
@@ -213,6 +214,8 @@ class InputCorpus {
     assert(!U.empty());
     if (FeatureDebug)
       Printf("ADD_TO_CORPUS %zd NF %zd\n", Inputs.size(), NumFeatures);
+    // Inputs.size() is cast to uint32_t below.
+    assert(Inputs.size() < std::numeric_limits<uint32_t>::max());
     Inputs.push_back(new InputInfo());
     InputInfo &II = *Inputs.back();
     II.U = U;
@@ -224,7 +227,7 @@ class InputCorpus {
     II.HasFocusFunction = HasFocusFunction;
     // Assign maximal energy to the new seed.
     II.Energy = RareFeatures.empty() ? 1.0 : log(RareFeatures.size());
-    II.SumIncidence = RareFeatures.size();
+    II.SumIncidence = static_cast<double>(RareFeatures.size());
     II.NeedsEnergyUpdate = false;
     std::sort(II.UniqFeatureSet.begin(), II.UniqFeatureSet.end());
     ComputeSHA1(U.data(), U.size(), II.Sha1);
@@ -399,7 +402,7 @@ class InputCorpus {
       // 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;
+        II->Energy += log(II->SumIncidence) / II->SumIncidence;
       }
     }
 
@@ -426,7 +429,8 @@ class InputCorpus {
       NumUpdatedFeatures++;
       if (FeatureDebug)
         Printf("ADD FEATURE %zd sz %d\n", Idx, NewSize);
-      SmallestElementPerFeature[Idx] = Inputs.size();
+      // Inputs.size() is guaranteed to be less than UINT32_MAX by AddToCorpus.
+      SmallestElementPerFeature[Idx] = static_cast<uint32_t>(Inputs.size());
       InputSizesPerFeature[Idx] = NewSize;
       return true;
     }
@@ -464,7 +468,7 @@ class InputCorpus {
 
   static const bool FeatureDebug = false;
 
-  size_t GetFeature(size_t Idx) const { return InputSizesPerFeature[Idx]; }
+  uint32_t GetFeature(size_t Idx) const { return InputSizesPerFeature[Idx]; }
 
   void ValidateFeatureSet() {
     if (FeatureDebug)
@@ -539,9 +543,11 @@ class InputCorpus {
 
     if (VanillaSchedule) {
       for (size_t i = 0; i < N; i++)
-        Weights[i] = Inputs[i]->NumFeatures
-                         ? (i + 1) * (Inputs[i]->HasFocusFunction ? 1000 : 1)
-                         : 0.;
+        Weights[i] =
+            Inputs[i]->NumFeatures
+                ? static_cast<double>((i + 1) *
+                                      (Inputs[i]->HasFocusFunction ? 1000 : 1))
+                : 0.;
     }
 
     if (FeatureDebug) {

diff  --git a/compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.cpp b/compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.cpp
index 0e9cdf7e66b1..23d422590d19 100644
--- a/compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.cpp
+++ b/compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.cpp
@@ -60,6 +60,7 @@ bool BlockCoverage::AppendCoverage(std::istream &IN) {
       CoveredBlocks.push_back(BB);
     }
     if (CoveredBlocks.empty()) return false;
+    // Ensures no CoverageVector is longer than UINT32_MAX.
     uint32_t NumBlocks = CoveredBlocks.back();
     CoveredBlocks.pop_back();
     for (auto BB : CoveredBlocks)
@@ -200,7 +201,8 @@ bool DataFlowTrace::Init(const std::string &DirPath, std::string *FocusFunction,
     Printf("INFO: AUTOFOCUS: %zd %s\n", FocusFuncIdx,
            FunctionNames[FocusFuncIdx].c_str());
     for (size_t i = 0; i < NumFunctions; i++) {
-      if (!Weights[i]) continue;
+      if (Weights[i] == 0.0)
+        continue;
       Printf("  [%zd] W %g\tBB-tot %u\tBB-cov %u\tEntryFreq %u:\t%s\n", i,
              Weights[i], Coverage.GetNumberOfBlocks(i),
              Coverage.GetNumberOfCoveredBlocks(i), Coverage.GetCounter(i, 0),

diff  --git a/compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.h b/compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.h
index d6e3de30a4ef..07c03bb25651 100644
--- a/compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.h
+++ b/compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.h
@@ -42,7 +42,8 @@ int CollectDataFlow(const std::string &DFTBinary, const std::string &DirPath,
                     const Vector<SizedFile> &CorporaFiles);
 
 class BlockCoverage {
- public:
+public:
+  // These functions guarantee no CoverageVector is longer than UINT32_MAX.
   bool AppendCoverage(std::istream &IN);
   bool AppendCoverage(const std::string &S);
 
@@ -50,7 +51,8 @@ class BlockCoverage {
 
   uint32_t GetCounter(size_t FunctionId, size_t BasicBlockId) {
     auto It = Functions.find(FunctionId);
-    if (It == Functions.end()) return 0;
+    if (It == Functions.end())
+      return 0;
     const auto &Counters = It->second;
     if (BasicBlockId < Counters.size())
       return Counters[BasicBlockId];
@@ -61,7 +63,7 @@ class BlockCoverage {
     auto It = Functions.find(FunctionId);
     if (It == Functions.end()) return 0;
     const auto &Counters = It->second;
-    return Counters.size();
+    return static_cast<uint32_t>(Counters.size());
   }
 
   uint32_t GetNumberOfCoveredBlocks(size_t FunctionId) {
@@ -78,8 +80,7 @@ class BlockCoverage {
   Vector<double> FunctionWeights(size_t NumFunctions) const;
   void clear() { Functions.clear(); }
 
- private:
-
+private:
   typedef Vector<uint32_t> CoverageVector;
 
   uint32_t NumberOfCoveredBlocks(const CoverageVector &Counters) const {
@@ -91,7 +92,8 @@ class BlockCoverage {
   }
 
   uint32_t NumberOfUncoveredBlocks(const CoverageVector &Counters) const {
-    return Counters.size() - NumberOfCoveredBlocks(Counters);
+    return static_cast<uint32_t>(Counters.size()) -
+           NumberOfCoveredBlocks(Counters);
   }
 
   uint32_t SmallestNonZeroCounter(const CoverageVector &Counters) const {

diff  --git a/compiler-rt/lib/fuzzer/FuzzerDictionary.h b/compiler-rt/lib/fuzzer/FuzzerDictionary.h
index 301c5d9afecf..db55907d9363 100644
--- a/compiler-rt/lib/fuzzer/FuzzerDictionary.h
+++ b/compiler-rt/lib/fuzzer/FuzzerDictionary.h
@@ -23,12 +23,14 @@ template <size_t kMaxSizeT> class FixedWord {
 public:
   static const size_t kMaxSize = kMaxSizeT;
   FixedWord() {}
-  FixedWord(const uint8_t *B, uint8_t S) { Set(B, S); }
+  FixedWord(const uint8_t *B, size_t S) { Set(B, S); }
 
-  void Set(const uint8_t *B, uint8_t S) {
+  void Set(const uint8_t *B, size_t S) {
+    static_assert(kMaxSizeT <= std::numeric_limits<uint8_t>::max(),
+                  "FixedWord::kMaxSizeT cannot fit in a uint8_t.");
     assert(S <= kMaxSize);
     memcpy(Data, B, S);
-    Size = S;
+    Size = static_cast<uint8_t>(S);
   }
 
   bool operator==(const FixedWord<kMaxSize> &w) const {

diff  --git a/compiler-rt/lib/fuzzer/FuzzerDriver.cpp b/compiler-rt/lib/fuzzer/FuzzerDriver.cpp
index 447cafce7fd4..ceaa9070512f 100644
--- a/compiler-rt/lib/fuzzer/FuzzerDriver.cpp
+++ b/compiler-rt/lib/fuzzer/FuzzerDriver.cpp
@@ -159,14 +159,14 @@ static bool ParseOneFlag(const char *Param) {
     const char *Str = FlagValue(Param, Name);
     if (Str)  {
       if (FlagDescriptions[F].IntFlag) {
-        int Val = MyStol(Str);
-        *FlagDescriptions[F].IntFlag = Val;
+        auto Val = MyStol(Str);
+        *FlagDescriptions[F].IntFlag = static_cast<int>(Val);
         if (Flags.verbosity >= 2)
           Printf("Flag: %s %d\n", Name, Val);
         return true;
       } else if (FlagDescriptions[F].UIntFlag) {
-        unsigned int Val = std::stoul(Str);
-        *FlagDescriptions[F].UIntFlag = Val;
+        auto Val = std::stoul(Str);
+        *FlagDescriptions[F].UIntFlag = static_cast<unsigned int>(Val);
         if (Flags.verbosity >= 2)
           Printf("Flag: %s %u\n", Name, Val);
         return true;
@@ -789,8 +789,8 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
   unsigned Seed = Flags.seed;
   // Initialize Seed.
   if (Seed == 0)
-    Seed =
-        std::chrono::system_clock::now().time_since_epoch().count() + GetPid();
+    Seed = static_cast<unsigned>(
+        std::chrono::system_clock::now().time_since_epoch().count() + GetPid());
   if (Flags.verbosity)
     Printf("INFO: Seed: %u\n", Seed);
 

diff  --git a/compiler-rt/lib/fuzzer/FuzzerFork.cpp b/compiler-rt/lib/fuzzer/FuzzerFork.cpp
index 44976b90ce54..5134a5d979e6 100644
--- a/compiler-rt/lib/fuzzer/FuzzerFork.cpp
+++ b/compiler-rt/lib/fuzzer/FuzzerFork.cpp
@@ -142,7 +142,9 @@ struct GlobalEnv {
         CollectDFT(SF);
       }
       auto Time2 = std::chrono::system_clock::now();
-      Job->DftTimeInSeconds = duration_cast<seconds>(Time2 - Time1).count();
+      auto DftTimeInSeconds = duration_cast<seconds>(Time2 - Time1).count();
+      assert(DftTimeInSeconds < std::numeric_limits<int>::max());
+      Job->DftTimeInSeconds = static_cast<int>(DftTimeInSeconds);
     }
     if (!Seeds.empty()) {
       Job->SeedListPath =

diff  --git a/compiler-rt/lib/fuzzer/FuzzerLoop.cpp b/compiler-rt/lib/fuzzer/FuzzerLoop.cpp
index 6e3bf44f8b45..03bf4fc4576f 100644
--- a/compiler-rt/lib/fuzzer/FuzzerLoop.cpp
+++ b/compiler-rt/lib/fuzzer/FuzzerLoop.cpp
@@ -440,8 +440,9 @@ void Fuzzer::PrintPulseAndReportSlowInput(const uint8_t *Data, size_t Size) {
   if (!(TotalNumberOfRuns & (TotalNumberOfRuns - 1)) &&
       secondsSinceProcessStartUp() >= 2)
     PrintStats("pulse ");
-  if (TimeOfUnit > TimeOfLongestUnitInSeconds * 1.1 &&
-      TimeOfUnit >= Options.ReportSlowUnits) {
+  auto Threshhold =
+      static_cast<long>(static_cast<double>(TimeOfLongestUnitInSeconds) * 1.1);
+  if (TimeOfUnit > Threshhold && TimeOfUnit >= Options.ReportSlowUnits) {
     TimeOfLongestUnitInSeconds = TimeOfUnit;
     Printf("Slowest unit: %zd s:\n", TimeOfLongestUnitInSeconds);
     WriteUnitToFileWithPrefix({Data, Data + Size}, "slow-unit-");
@@ -501,6 +502,8 @@ bool Fuzzer::RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile,
                     bool *FoundUniqFeatures) {
   if (!Size)
     return false;
+  // Largest input length should be INT_MAX.
+  assert(Size < std::numeric_limits<uint32_t>::max());
 
   ExecuteCallback(Data, Size);
   auto TimeOfUnit = duration_cast<microseconds>(UnitStopTime - UnitStartTime);
@@ -508,8 +511,8 @@ bool Fuzzer::RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile,
   UniqFeatureSetTmp.clear();
   size_t FoundUniqFeaturesOfII = 0;
   size_t NumUpdatesBefore = Corpus.NumFeatureUpdates();
-  TPC.CollectFeatures([&](size_t Feature) {
-    if (Corpus.AddFeature(Feature, Size, Options.Shrink))
+  TPC.CollectFeatures([&](uint32_t Feature) {
+    if (Corpus.AddFeature(Feature, static_cast<uint32_t>(Size), Options.Shrink))
       UniqFeatureSetTmp.push_back(Feature);
     if (Options.Entropic)
       Corpus.UpdateFeatureFrequency(II, Feature);

diff  --git a/compiler-rt/lib/fuzzer/FuzzerMerge.cpp b/compiler-rt/lib/fuzzer/FuzzerMerge.cpp
index e865f154895c..162453ceae2c 100644
--- a/compiler-rt/lib/fuzzer/FuzzerMerge.cpp
+++ b/compiler-rt/lib/fuzzer/FuzzerMerge.cpp
@@ -82,9 +82,9 @@ bool Merger::Parse(std::istream &IS, bool ParseCoverage) {
   while (std::getline(IS, Line, '\n')) {
     std::istringstream ISS1(Line);
     std::string Marker;
-    size_t N;
-    ISS1 >> Marker;
-    ISS1 >> N;
+    uint32_t N;
+    if (!(ISS1 >> Marker) || !(ISS1 >> N))
+      return false;
     if (Marker == "STARTED") {
       // STARTED FILE_ID FILE_SIZE
       if (ExpectedStartMarker != N)

diff  --git a/compiler-rt/lib/fuzzer/FuzzerMutate.cpp b/compiler-rt/lib/fuzzer/FuzzerMutate.cpp
index cf34a9fe8e2e..5209b86641fb 100644
--- a/compiler-rt/lib/fuzzer/FuzzerMutate.cpp
+++ b/compiler-rt/lib/fuzzer/FuzzerMutate.cpp
@@ -61,14 +61,16 @@ MutationDispatcher::MutationDispatcher(Random &Rand,
 }
 
 static char RandCh(Random &Rand) {
-  if (Rand.RandBool()) return Rand(256);
+  if (Rand.RandBool())
+    return static_cast<char>(Rand(256));
   const char Special[] = "!*'();:@&=+$,/?%#[]012Az-`~.\xff\x00";
   return Special[Rand(sizeof(Special) - 1)];
 }
 
 size_t MutationDispatcher::Mutate_Custom(uint8_t *Data, size_t Size,
                                          size_t MaxSize) {
-  return EF->LLVMFuzzerCustomMutator(Data, Size, MaxSize, Rand.Rand());
+  return EF->LLVMFuzzerCustomMutator(Data, Size, MaxSize,
+                                     Rand.Rand<unsigned int>());
 }
 
 size_t MutationDispatcher::Mutate_CustomCrossOver(uint8_t *Data, size_t Size,
@@ -82,7 +84,8 @@ size_t MutationDispatcher::Mutate_CustomCrossOver(uint8_t *Data, size_t Size,
   CustomCrossOverInPlaceHere.resize(MaxSize);
   auto &U = CustomCrossOverInPlaceHere;
   size_t NewSize = EF->LLVMFuzzerCustomCrossOver(
-      Data, Size, Other.data(), Other.size(), U.data(), U.size(), Rand.Rand());
+      Data, Size, Other.data(), Other.size(), U.data(), U.size(),
+      Rand.Rand<unsigned int>());
   if (!NewSize)
     return 0;
   assert(NewSize <= MaxSize && "CustomCrossOver returned overisized unit");
@@ -135,7 +138,8 @@ size_t MutationDispatcher::Mutate_InsertRepeatedBytes(uint8_t *Data,
   // Insert new values at Data[Idx].
   memmove(Data + Idx + N, Data + Idx, Size - Idx);
   // Give preference to 0x00 and 0xff.
-  uint8_t Byte = Rand.RandBool() ? Rand(256) : (Rand.RandBool() ? 0 : 255);
+  uint8_t Byte = static_cast<uint8_t>(
+      Rand.RandBool() ? Rand(256) : (Rand.RandBool() ? 0 : 255));
   for (size_t i = 0; i < N; i++)
     Data[Idx + i] = Byte;
   return Size + N;
@@ -227,8 +231,8 @@ DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP(
     T Arg1, T Arg2, const uint8_t *Data, size_t Size) {
   if (Rand.RandBool()) Arg1 = Bswap(Arg1);
   if (Rand.RandBool()) Arg2 = Bswap(Arg2);
-  T Arg1Mutation = Arg1 + Rand(-1, 1);
-  T Arg2Mutation = Arg2 + Rand(-1, 1);
+  T Arg1Mutation = static_cast<T>(Arg1 + Rand(-1, 1));
+  T Arg2Mutation = static_cast<T>(Arg2 + Rand(-1, 1));
   return MakeDictionaryEntryFromCMP(&Arg1, &Arg2, &Arg1Mutation, &Arg2Mutation,
                                     sizeof(Arg1), Data, Size);
 }
@@ -245,23 +249,23 @@ size_t MutationDispatcher::Mutate_AddWordFromTORC(
   DictionaryEntry DE;
   switch (Rand(4)) {
   case 0: {
-    auto X = TPC.TORC8.Get(Rand.Rand());
+    auto X = TPC.TORC8.Get(Rand.Rand<size_t>());
     DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size);
   } break;
   case 1: {
-    auto X = TPC.TORC4.Get(Rand.Rand());
+    auto X = TPC.TORC4.Get(Rand.Rand<size_t>());
     if ((X.A >> 16) == 0 && (X.B >> 16) == 0 && Rand.RandBool())
       DE = MakeDictionaryEntryFromCMP((uint16_t)X.A, (uint16_t)X.B, Data, Size);
     else
       DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size);
   } break;
   case 2: {
-    auto X = TPC.TORCW.Get(Rand.Rand());
+    auto X = TPC.TORCW.Get(Rand.Rand<size_t>());
     DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size);
   } break;
   case 3: if (Options.UseMemmem) {
-    auto X = TPC.MMT.Get(Rand.Rand());
-    DE = DictionaryEntry(X);
+      auto X = TPC.MMT.Get(Rand.Rand<size_t>());
+      DE = DictionaryEntry(X);
   } break;
   default:
     assert(0);
@@ -387,12 +391,12 @@ size_t ChangeBinaryInteger(uint8_t *Data, size_t Size, Random &Rand) {
   assert(Off + sizeof(T) <= Size);
   T Val;
   if (Off < 64 && !Rand(4)) {
-    Val = Size;
+    Val = static_cast<T>(Size);
     if (Rand.RandBool())
       Val = Bswap(Val);
   } else {
     memcpy(&Val, Data + Off, sizeof(Val));
-    T Add = Rand(21);
+    T Add = static_cast<T>(Rand(21));
     Add -= 10;
     if (Rand.RandBool())
       Val = Bswap(T(Bswap(Val) + Add)); // Add assuming 
diff erent endiannes.

diff  --git a/compiler-rt/lib/fuzzer/FuzzerRandom.h b/compiler-rt/lib/fuzzer/FuzzerRandom.h
index 659283eee207..ad6c07eb5ef5 100644
--- a/compiler-rt/lib/fuzzer/FuzzerRandom.h
+++ b/compiler-rt/lib/fuzzer/FuzzerRandom.h
@@ -18,18 +18,27 @@ class Random : public std::minstd_rand {
  public:
   Random(unsigned int seed) : std::minstd_rand(seed) {}
   result_type operator()() { return this->std::minstd_rand::operator()(); }
-  size_t Rand() { return this->operator()(); }
-  size_t RandBool() { return Rand() % 2; }
+  template <typename T>
+  typename std::enable_if<std::is_integral<T>::value, T>::type Rand() {
+    return static_cast<T>(this->operator()());
+  }
+  size_t RandBool() { return this->operator()() % 2; }
   size_t SkewTowardsLast(size_t n) {
     size_t T = this->operator()(n * n);
-    size_t Res = sqrt(T);
+    size_t Res = static_cast<size_t>(sqrt(T));
     return Res;
   }
-  size_t operator()(size_t n) { return n ? Rand() % n : 0; }
-  intptr_t operator()(intptr_t From, intptr_t To) {
+  template <typename T>
+  typename std::enable_if<std::is_integral<T>::value, T>::type operator()(T n) {
+    return n ? Rand<T>() % n : 0;
+  }
+  template <typename T>
+  typename std::enable_if<std::is_integral<T>::value, T>::type
+  operator()(T From, T To) {
     assert(From < To);
-    intptr_t RangeSize = To - From + 1;
-    return operator()(RangeSize) + From;
+    auto RangeSize = static_cast<unsigned long long>(To) -
+                     static_cast<unsigned long long>(From) + 1;
+    return static_cast<T>(this->operator()(RangeSize) + From);
   }
 };
 

diff  --git a/compiler-rt/lib/fuzzer/FuzzerSHA1.cpp b/compiler-rt/lib/fuzzer/FuzzerSHA1.cpp
index 2005dc700305..b05655c8ef4d 100644
--- a/compiler-rt/lib/fuzzer/FuzzerSHA1.cpp
+++ b/compiler-rt/lib/fuzzer/FuzzerSHA1.cpp
@@ -134,12 +134,13 @@ void sha1_hashBlock(sha1nfo *s) {
 	s->state[4] += e;
 }
 
-void sha1_addUncounted(sha1nfo *s, uint8_t data) {
-	uint8_t * const b = (uint8_t*) s->buffer;
+// Adds the least significant byte of |data|.
+void sha1_addUncounted(sha1nfo *s, uint32_t data) {
+  uint8_t *const b = (uint8_t *)s->buffer;
 #ifdef SHA_BIG_ENDIAN
-	b[s->bufferOffset] = data;
+  b[s->bufferOffset] = static_cast<uint8_t>(data);
 #else
-	b[s->bufferOffset ^ 3] = data;
+  b[s->bufferOffset ^ 3] = static_cast<uint8_t>(data);
 #endif
 	s->bufferOffset++;
 	if (s->bufferOffset == BLOCK_LENGTH) {

diff  --git a/compiler-rt/lib/fuzzer/FuzzerTracePC.cpp b/compiler-rt/lib/fuzzer/FuzzerTracePC.cpp
index 91e94d824002..d808b9b00fa3 100644
--- a/compiler-rt/lib/fuzzer/FuzzerTracePC.cpp
+++ b/compiler-rt/lib/fuzzer/FuzzerTracePC.cpp
@@ -106,6 +106,15 @@ void TracePC::PrintModuleInfo() {
   }
   if (size_t NumExtraCounters = ExtraCountersEnd() - ExtraCountersBegin())
     Printf("INFO: %zd Extra Counters\n", NumExtraCounters);
+
+  size_t MaxFeatures = CollectFeatures([](uint32_t) {});
+  if (MaxFeatures > std::numeric_limits<uint32_t>::max())
+    Printf("WARNING: The coverage PC tables may produce up to %zu features.\n"
+           "This exceeds the maximum 32-bit value. Some features may be\n"
+           "ignored, and fuzzing may become less precise. If possible,\n"
+           "consider refactoring the fuzzer into several smaller fuzzers\n"
+           "linked against only a portion of the current target.\n",
+           MaxFeatures);
 }
 
 ATTRIBUTE_NO_SANITIZE_ALL
@@ -356,7 +365,7 @@ void TracePC::AddValueForMemcmp(void *caller_pc, const void *s1, const void *s2,
   uint8_t HammingDistance = 0;
   for (; I < Len; I++) {
     if (B1[I] != B2[I] || (StopAtZero && B1[I] == 0)) {
-      HammingDistance = Popcountll(B1[I] ^ B2[I]);
+      HammingDistance = static_cast<uint8_t>(Popcountll(B1[I] ^ B2[I]));
       break;
     }
   }

diff  --git a/compiler-rt/lib/fuzzer/FuzzerTracePC.h b/compiler-rt/lib/fuzzer/FuzzerTracePC.h
index 63b232062651..1fa9ed11c698 100644
--- a/compiler-rt/lib/fuzzer/FuzzerTracePC.h
+++ b/compiler-rt/lib/fuzzer/FuzzerTracePC.h
@@ -79,7 +79,7 @@ class TracePC {
   void SetPrintNewPCs(bool P) { DoPrintNewPCs = P; }
   void SetPrintNewFuncs(size_t P) { NumPrintNewFuncs = P; }
   void UpdateObservedPCs();
-  template <class Callback> void CollectFeatures(Callback CB) const;
+  template <class Callback> size_t CollectFeatures(Callback CB) const;
 
   void ResetMaps() {
     ValueProfileMap.Reset();
@@ -234,16 +234,16 @@ unsigned CounterToFeature(T Counter) {
     return Bit;
 }
 
-template <class Callback>  // void Callback(size_t Feature)
-ATTRIBUTE_NO_SANITIZE_ADDRESS
-ATTRIBUTE_NOINLINE
-void TracePC::CollectFeatures(Callback HandleFeature) const {
+template <class Callback> // void Callback(uint32_t Feature)
+ATTRIBUTE_NO_SANITIZE_ADDRESS ATTRIBUTE_NOINLINE size_t
+TracePC::CollectFeatures(Callback HandleFeature) const {
   auto Handle8bitCounter = [&](size_t FirstFeature,
                                size_t Idx, uint8_t Counter) {
     if (UseCounters)
-      HandleFeature(FirstFeature + Idx * 8 + CounterToFeature(Counter));
+      HandleFeature(static_cast<uint32_t>(FirstFeature + Idx * 8 +
+                                          CounterToFeature(Counter)));
     else
-      HandleFeature(FirstFeature + Idx);
+      HandleFeature(static_cast<uint32_t>(FirstFeature + Idx));
   };
 
   size_t FirstFeature = 0;
@@ -263,16 +263,18 @@ void TracePC::CollectFeatures(Callback HandleFeature) const {
 
   if (UseValueProfileMask) {
     ValueProfileMap.ForEach([&](size_t Idx) {
-      HandleFeature(FirstFeature + Idx);
+      HandleFeature(static_cast<uint32_t>(FirstFeature + Idx));
     });
     FirstFeature += ValueProfileMap.SizeInBits();
   }
 
   // Step function, grows similar to 8 * Log_2(A).
-  auto StackDepthStepFunction = [](uint32_t A) -> uint32_t {
-    if (!A) return A;
-    uint32_t Log2 = Log(A);
-    if (Log2 < 3) return A;
+  auto StackDepthStepFunction = [](size_t A) -> size_t {
+    if (!A)
+      return A;
+    auto Log2 = Log(A);
+    if (Log2 < 3)
+      return A;
     Log2 -= 3;
     return (Log2 + 1) * 8 + ((A >> Log2) & 7);
   };
@@ -280,8 +282,13 @@ void TracePC::CollectFeatures(Callback HandleFeature) const {
   assert(StackDepthStepFunction(1024 * 4) == 80);
   assert(StackDepthStepFunction(1024 * 1024) == 144);
 
-  if (auto MaxStackOffset = GetMaxStackOffset())
-    HandleFeature(FirstFeature + StackDepthStepFunction(MaxStackOffset / 8));
+  if (auto MaxStackOffset = GetMaxStackOffset()) {
+    HandleFeature(static_cast<uint32_t>(
+        FirstFeature + StackDepthStepFunction(MaxStackOffset / 8)));
+    FirstFeature += StackDepthStepFunction(std::numeric_limits<size_t>::max());
+  }
+
+  return FirstFeature;
 }
 
 extern TracePC TPC;

diff  --git a/compiler-rt/lib/fuzzer/FuzzerUtil.cpp b/compiler-rt/lib/fuzzer/FuzzerUtil.cpp
index 7eecb68d0729..4b161c4139a5 100644
--- a/compiler-rt/lib/fuzzer/FuzzerUtil.cpp
+++ b/compiler-rt/lib/fuzzer/FuzzerUtil.cpp
@@ -111,7 +111,7 @@ bool ParseOneDictionaryEntry(const std::string &Str, Unit *U) {
         char Hex[] = "0xAA";
         Hex[2] = Str[Pos + 2];
         Hex[3] = Str[Pos + 3];
-        U->push_back(strtol(Hex, nullptr, 16));
+        U->push_back(static_cast<uint8_t>(strtol(Hex, nullptr, 16)));
         Pos += 3;
         continue;
       }

diff  --git a/compiler-rt/lib/fuzzer/FuzzerUtil.h b/compiler-rt/lib/fuzzer/FuzzerUtil.h
index e90be085008e..2ae58102759c 100644
--- a/compiler-rt/lib/fuzzer/FuzzerUtil.h
+++ b/compiler-rt/lib/fuzzer/FuzzerUtil.h
@@ -90,7 +90,9 @@ std::string SearchRegexCmd(const std::string &Regex);
 
 size_t SimpleFastHash(const uint8_t *Data, size_t Size);
 
-inline uint32_t Log(uint32_t X) { return 32 - Clz(X) - 1; }
+inline size_t Log(size_t X) {
+  return static_cast<size_t>((sizeof(unsigned long long) * 8) - Clzll(X) - 1);
+}
 
 inline size_t PageSize() { return 4096; }
 inline uint8_t *RoundUpByPage(uint8_t *P) {

diff  --git a/compiler-rt/lib/fuzzer/FuzzerUtilFuchsia.cpp b/compiler-rt/lib/fuzzer/FuzzerUtilFuchsia.cpp
index af4394616776..5034b4a28d3f 100644
--- a/compiler-rt/lib/fuzzer/FuzzerUtilFuchsia.cpp
+++ b/compiler-rt/lib/fuzzer/FuzzerUtilFuchsia.cpp
@@ -515,7 +515,7 @@ int ExecuteCommand(const Command &Cmd) {
     return rc;
   }
 
-  return Info.return_code;
+  return static_cast<int>(Info.return_code);
 }
 
 bool ExecuteCommand(const Command &BaseCmd, std::string *CmdOutput) {


        


More information about the llvm-commits mailing list