[libFuzzer] fix use-after-free in libFuzzer found by ... fuzzing.
authorKostya Serebryany <kcc@google.com>
Sat, 8 Oct 2016 21:57:48 +0000 (21:57 +0000)
committerKostya Serebryany <kcc@google.com>
Sat, 8 Oct 2016 21:57:48 +0000 (21:57 +0000)
llvm-svn: 283675

llvm/lib/Fuzzer/FuzzerCorpus.h

index 382980b..5899c67 100644 (file)
@@ -36,25 +36,28 @@ class InputCorpus {
  public:
   static const size_t kFeatureSetSize = 1 << 16;
   InputCorpus() {
-    Inputs.reserve(1 << 14);  // Avoid too many resizes.
     memset(InputSizesPerFeature, 0, sizeof(InputSizesPerFeature));
     memset(SmallestElementPerFeature, 0, sizeof(SmallestElementPerFeature));
   }
+  ~InputCorpus() {
+    for (auto II : Inputs)
+      delete II;
+  }
   size_t size() const { return Inputs.size(); }
   size_t SizeInBytes() const {
     size_t Res = 0;
-    for (auto &II : Inputs)
-      Res += II.U.size();
+    for (auto II : Inputs)
+      Res += II->U.size();
     return Res;
   }
   size_t NumActiveUnits() const {
     size_t Res = 0;
-    for (auto &II : Inputs)
-      Res += !II.U.empty();
+    for (auto II : Inputs)
+      Res += !II->U.empty();
     return Res;
   }
   bool empty() const { return Inputs.empty(); }
-  const Unit &operator[] (size_t Idx) const { return Inputs[Idx].U; }
+  const Unit &operator[] (size_t Idx) const { return Inputs[Idx]->U; }
   void AddToCorpus(const Unit &U, size_t NumFeatures) {
     assert(!U.empty());
     uint8_t Hash[kSHA1NumBytes];
@@ -62,8 +65,8 @@ class InputCorpus {
       Printf("ADD_TO_CORPUS %zd NF %zd\n", Inputs.size(), NumFeatures);
     ComputeSHA1(U.data(), U.size(), Hash);
     Hashes.insert(Sha1ToString(Hash));
-    Inputs.push_back(InputInfo());
-    InputInfo &II = Inputs.back();
+    Inputs.push_back(new InputInfo());
+    InputInfo &II = *Inputs.back();
     II.U = U;
     II.NumFeatures = NumFeatures;
     memcpy(II.Sha1, Hash, kSHA1NumBytes);
@@ -71,14 +74,10 @@ class InputCorpus {
     ValidateFeatureSet();
   }
 
-  typedef const std::vector<InputInfo>::const_iterator ConstIter;
-  ConstIter begin() const { return Inputs.begin(); }
-  ConstIter end() const { return Inputs.end(); }
-
   bool HasUnit(const Unit &U) { return Hashes.count(Hash(U)); }
   bool HasUnit(const std::string &H) { return Hashes.count(H); }
   InputInfo &ChooseUnitToMutate(Random &Rand) {
-    InputInfo &II = Inputs[ChooseUnitIdxToMutate(Rand)];
+    InputInfo &II = *Inputs[ChooseUnitIdxToMutate(Rand)];
     assert(!II.U.empty());
     return II;
   };
@@ -94,7 +93,7 @@ class InputCorpus {
 
   void PrintStats() {
     for (size_t i = 0; i < Inputs.size(); i++) {
-      const auto &II = Inputs[i];
+      const auto &II = *Inputs[i];
       Printf("  [%zd %s]\tsz: %zd\truns: %zd\tsucc: %zd\n", i,
              Sha1ToString(II.Sha1).c_str(), II.U.size(),
              II.NumExecutedMutations, II.NumSuccessfullMutations);
@@ -108,7 +107,7 @@ class InputCorpus {
     }
     Printf("\n\t");
     for (size_t i = 0; i < Inputs.size(); i++)
-      if (size_t N = Inputs[i].NumFeatures)
+      if (size_t N = Inputs[i]->NumFeatures)
         Printf(" %zd=>%zd ", i, N);
     Printf("\n");
   }
@@ -119,7 +118,7 @@ class InputCorpus {
     uint32_t OldSize = GetFeature(Idx);
     if (OldSize == 0 || (Shrink && OldSize > NewSize)) {
       if (OldSize > 0) {
-        InputInfo &II = Inputs[SmallestElementPerFeature[Idx]];
+        InputInfo &II = *Inputs[SmallestElementPerFeature[Idx]];
         assert(II.NumFeatures > 0);
         II.NumFeatures--;
         if (II.NumFeatures == 0) {
@@ -157,12 +156,12 @@ private:
       PrintFeatureSet();
     for (size_t Idx = 0; Idx < kFeatureSetSize; Idx++)
       if (GetFeature(Idx))
-        Inputs[SmallestElementPerFeature[Idx]].Tmp++;
-    for (auto &II: Inputs) {
-      if (II.Tmp != II.NumFeatures)
-        Printf("ZZZ %zd %zd\n", II.Tmp, II.NumFeatures);
-      assert(II.Tmp == II.NumFeatures);
-      II.Tmp = 0;
+        Inputs[SmallestElementPerFeature[Idx]]->Tmp++;
+    for (auto II: Inputs) {
+      if (II->Tmp != II->NumFeatures)
+        Printf("ZZZ %zd %zd\n", II->Tmp, II->NumFeatures);
+      assert(II->Tmp == II->NumFeatures);
+      II->Tmp = 0;
     }
   }
 
@@ -175,7 +174,7 @@ private:
     std::iota(Intervals.begin(), Intervals.end(), 0);
     if (CountingFeatures)
       for (size_t i = 0; i < N; i++)
-        Weights[i] = Inputs[i].NumFeatures * (i + 1);
+        Weights[i] = Inputs[i]->NumFeatures * (i + 1);
     else
       std::iota(Weights.begin(), Weights.end(), 1);
     CorpusDistribution = std::piecewise_constant_distribution<double>(
@@ -187,7 +186,7 @@ private:
   std::vector<double> Weights;
 
   std::unordered_set<std::string> Hashes;
-  std::vector<InputInfo> Inputs;
+  std::vector<InputInfo*> Inputs;
 
   bool CountingFeatures = false;
   uint32_t InputSizesPerFeature[kFeatureSetSize];