[llvm] r257713 - [libFuzzer] make CurrentUnit a POD object instead of vector to avoid extra allocations

Kostya Serebryany via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 13 15:46:01 PST 2016


Author: kcc
Date: Wed Jan 13 17:46:01 2016
New Revision: 257713

URL: http://llvm.org/viewvc/llvm-project?rev=257713&view=rev
Log:
[libFuzzer] make CurrentUnit a POD object instead of vector to avoid extra allocations

Modified:
    llvm/trunk/lib/Fuzzer/FuzzerInternal.h
    llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp
    llvm/trunk/lib/Fuzzer/FuzzerTraceState.cpp
    llvm/trunk/lib/Fuzzer/FuzzerUtil.cpp

Modified: llvm/trunk/lib/Fuzzer/FuzzerInternal.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerInternal.h?rev=257713&r1=257712&r2=257713&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerInternal.h (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerInternal.h Wed Jan 13 17:46:01 2016
@@ -37,7 +37,9 @@ std::string DirPlusFile(const std::strin
                         const std::string &FileName);
 
 void Printf(const char *Fmt, ...);
-void Print(const Unit &U, const char *PrintAfter = "");
+void PrintHexArray(const Unit &U, const char *PrintAfter = "");
+void PrintHexArray(const uint8_t *Data, size_t Size,
+                   const char *PrintAfter = "");
 void PrintASCII(const uint8_t *Data, size_t Size, const char *PrintAfter = "");
 void PrintASCII(const Unit &U, const char *PrintAfter = "");
 std::string Hash(const Unit &U);
@@ -140,7 +142,6 @@ class Fuzzer {
   void WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix);
   void PrintStats(const char *Where, const char *End = "\n");
   void PrintStatusForNewUnit(const Unit &U);
-  void PrintUnitInASCII(const Unit &U, const char *PrintAfter = "");
 
   void SyncCorpus();
 
@@ -162,7 +163,9 @@ class Fuzzer {
   void SetDeathCallback();
   static void StaticDeathCallback();
   void DeathCallback();
-  Unit CurrentUnit;
+
+  uint8_t *CurrentUnitData;
+  size_t CurrentUnitSize;
 
   size_t TotalNumberOfRuns = 0;
   size_t TotalNumberOfExecutedTraceBasedMutations = 0;

Modified: llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp?rev=257713&r1=257712&r2=257713&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp Wed Jan 13 17:46:01 2016
@@ -68,10 +68,6 @@ void Fuzzer::SetDeathCallback() {
   __sanitizer_set_death_callback(StaticDeathCallback);
 }
 
-void Fuzzer::PrintUnitInASCII(const Unit &U, const char *PrintAfter) {
-  PrintASCII(U, PrintAfter);
-}
-
 void Fuzzer::StaticDeathCallback() {
   assert(F);
   F->DeathCallback();
@@ -79,11 +75,12 @@ void Fuzzer::StaticDeathCallback() {
 
 void Fuzzer::DeathCallback() {
   Printf("DEATH:\n");
-  if (CurrentUnit.size() <= kMaxUnitSizeToPrint) {
-    Print(CurrentUnit, "\n");
-    PrintUnitInASCII(CurrentUnit, "\n");
+  if (CurrentUnitSize <= kMaxUnitSizeToPrint) {
+    PrintHexArray(CurrentUnitData, CurrentUnitSize, "\n");
+    PrintASCII(CurrentUnitData, CurrentUnitSize, "\n");
   }
-  WriteUnitToFileWithPrefix(CurrentUnit, "crash-");
+  WriteUnitToFileWithPrefix(
+      {CurrentUnitData, CurrentUnitData + CurrentUnitSize}, "crash-");
 }
 
 void Fuzzer::StaticAlarmCallback() {
@@ -102,11 +99,12 @@ void Fuzzer::AlarmCallback() {
     Printf("ALARM: working on the last Unit for %zd seconds\n", Seconds);
     Printf("       and the timeout value is %d (use -timeout=N to change)\n",
            Options.UnitTimeoutSec);
-    if (CurrentUnit.size() <= kMaxUnitSizeToPrint) {
-      Print(CurrentUnit, "\n");
-      PrintUnitInASCII(CurrentUnit, "\n");
+    if (CurrentUnitSize <= kMaxUnitSizeToPrint) {
+      PrintHexArray(CurrentUnitData, CurrentUnitSize, "\n");
+      PrintASCII(CurrentUnitData, CurrentUnitSize, "\n");
     }
-    WriteUnitToFileWithPrefix(CurrentUnit, "timeout-");
+    WriteUnitToFileWithPrefix(
+        {CurrentUnitData, CurrentUnitData + CurrentUnitSize}, "timeout-");
     Printf("==%d== ERROR: libFuzzer: timeout after %d seconds\n", GetPid(),
            Seconds);
     if (__sanitizer_print_stack_trace)
@@ -163,9 +161,7 @@ void Fuzzer::RereadOutputCorpus() {
     if (X.size() > (size_t)Options.MaxLen)
       X.resize(Options.MaxLen);
     if (UnitHashesAddedToCorpus.insert(Hash(X)).second) {
-      CurrentUnit.clear();
-      CurrentUnit.insert(CurrentUnit.begin(), X.begin(), X.end());
-      if (RunOne(CurrentUnit)) {
+      if (RunOne(X)) {
         Corpus.push_back(X);
         PrintStats("RELOAD");
       }
@@ -188,7 +184,7 @@ void Fuzzer::ShuffleAndMinimize() {
           Corpus.begin(), Corpus.end(),
           [](const Unit &A, const Unit &B) { return A.size() < B.size(); });
   }
-  Unit &U = CurrentUnit;
+  Unit U;
   for (const auto &C : Corpus) {
     for (size_t First = 0; First < 1; First++) {
       U.clear();
@@ -247,9 +243,13 @@ void Fuzzer::ExecuteCallback(const Unit
   std::unique_ptr<uint8_t[]> Data(new uint8_t[U.size()]);
   memcpy(Data.get(), U.data(), U.size());
   AssignTaintLabels(Data.get(), U.size());
+  CurrentUnitData = Data.get();
+  CurrentUnitSize = U.size();
   int Res = USF.TargetFunction(Data.get(), U.size());
   (void)Res;
   assert(Res == 0);
+  CurrentUnitData = nullptr;
+  CurrentUnitSize = 0;
 }
 
 size_t Fuzzer::RecordBlockCoverage() {
@@ -387,10 +387,9 @@ void Fuzzer::Merge(const std::vector<std
 }
 
 void Fuzzer::MutateAndTestOne() {
-  auto &U = CurrentUnit;
   USF.StartMutationSequence();
 
-  U = ChooseUnitToMutate();
+  auto U = ChooseUnitToMutate();
 
   for (int i = 0; i < Options.MutateDepth; i++) {
     size_t Size = U.size();
@@ -458,15 +457,12 @@ void Fuzzer::Drill() {
 
   PrintStats("REINIT");
   SavedOutputCorpusPath.swap(Options.OutputCorpus);
-  for (auto &U : SavedCorpus) {
-    CurrentUnit = U;
+  for (auto &U : SavedCorpus)
     RunOne(U);
-  }
   PrintStats("MERGE ");
   Options.PrintNEW = true;
   size_t NumMerged = 0;
   for (auto &U : Corpus) {
-    CurrentUnit = U;
     if (RunOne(U)) {
       PrintStatusForNewUnit(U);
       NumMerged++;

Modified: llvm/trunk/lib/Fuzzer/FuzzerTraceState.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerTraceState.cpp?rev=257713&r1=257712&r2=257713&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerTraceState.cpp (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerTraceState.cpp Wed Jan 13 17:46:01 2016
@@ -41,8 +41,8 @@
 //     __dfsw_HOOK(a, b, label(a), label(b)) so that __dfsw_HOOK
 //     gets all the taint labels for the arguments.
 //   * At the Fuzzer startup we assign a unique DFSan label
-//     to every byte of the input string (Fuzzer::CurrentUnit) so that for any
-//     chunk of data we know which input bytes it has derived from.
+//     to every byte of the input string (Fuzzer::CurrentUnitData) so that
+//     for any chunk of data we know which input bytes it has derived from.
 //   * The __dfsw_* functions (implemented in this file) record the
 //     parameters (i.e. the application data and the corresponding taint labels)
 //     in a global state.
@@ -174,13 +174,14 @@ const size_t TraceBasedMutation::kMaxSiz
 
 class TraceState {
  public:
-  TraceState(UserSuppliedFuzzer &USF,
-             const Fuzzer::FuzzingOptions &Options, const Unit &CurrentUnit)
-       : USF(USF), Options(Options), CurrentUnit(CurrentUnit) {
-    // Current trace collection is not thread-friendly and it probably
-    // does not have to be such, but at least we should not crash in presence
-    // of threads. So, just ignore all traces coming from all threads but one.
-    IsMyThread = true;
+   TraceState(UserSuppliedFuzzer &USF, const Fuzzer::FuzzingOptions &Options,
+              uint8_t **CurrentUnitData, size_t *CurrentUnitSize)
+       : USF(USF), Options(Options), CurrentUnitData(CurrentUnitData),
+         CurrentUnitSize(CurrentUnitSize) {
+     // Current trace collection is not thread-friendly and it probably
+     // does not have to be such, but at least we should not crash in presence
+     // of threads. So, just ignore all traces coming from all threads but one.
+     IsMyThread = true;
   }
 
   LabelRange GetLabelRange(dfsan_label L);
@@ -266,7 +267,8 @@ class TraceState {
   LabelRange LabelRanges[1 << (sizeof(dfsan_label) * 8)];
   UserSuppliedFuzzer &USF;
   const Fuzzer::FuzzingOptions &Options;
-  const Unit &CurrentUnit;
+  uint8_t **CurrentUnitData;
+  size_t *CurrentUnitSize;
   std::map<Unit, size_t> AutoDictUnitCounts;
   size_t AutoDictAdds = 0;
   static thread_local bool IsMyThread;
@@ -363,14 +365,14 @@ void TraceState::DFSanSwitchCallback(uin
 int TraceState::TryToAddDesiredData(uint64_t PresentData, uint64_t DesiredData,
                                     size_t DataSize) {
   int Res = 0;
-  const uint8_t *Beg = CurrentUnit.data();
-  const uint8_t *End = Beg + CurrentUnit.size();
+  const uint8_t *Beg = *CurrentUnitData;
+  const uint8_t *End = Beg + *CurrentUnitSize;
   for (const uint8_t *Cur = Beg; Cur < End; Cur++) {
     Cur = (uint8_t *)memmem(Cur, End - Cur, &PresentData, DataSize);
     if (!Cur)
       break;
     size_t Pos = Cur - Beg;
-    assert(Pos < CurrentUnit.size());
+    assert(Pos < *CurrentUnitSize);
     AddMutation(Pos, DataSize, DesiredData);
     AddMutation(Pos, DataSize, DesiredData + 1);
     AddMutation(Pos, DataSize, DesiredData - 1);
@@ -383,14 +385,14 @@ int TraceState::TryToAddDesiredData(cons
                                     const uint8_t *DesiredData,
                                     size_t DataSize) {
   int Res = 0;
-  const uint8_t *Beg = CurrentUnit.data();
-  const uint8_t *End = Beg + CurrentUnit.size();
+  const uint8_t *Beg = *CurrentUnitData;
+  const uint8_t *End = Beg + *CurrentUnitSize;
   for (const uint8_t *Cur = Beg; Cur < End; Cur++) {
     Cur = (uint8_t *)memmem(Cur, End - Cur, PresentData, DataSize);
     if (!Cur)
       break;
     size_t Pos = Cur - Beg;
-    assert(Pos < CurrentUnit.size());
+    assert(Pos < *CurrentUnitSize);
     AddMutation(Pos, DataSize, DesiredData);
     Res++;
   }
@@ -468,7 +470,7 @@ void Fuzzer::AssignTaintLabels(uint8_t *
 
 void Fuzzer::InitializeTraceState() {
   if (!Options.UseTraces) return;
-  TS = new TraceState(USF, Options, CurrentUnit);
+  TS = new TraceState(USF, Options, &CurrentUnitData, &CurrentUnitSize);
   if (ReallyHaveDFSan()) {
     for (size_t i = 0; i < static_cast<size_t>(Options.MaxLen); i++) {
       dfsan_label L = dfsan_create_label("input", (void *)(i + 1));

Modified: llvm/trunk/lib/Fuzzer/FuzzerUtil.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerUtil.cpp?rev=257713&r1=257712&r2=257713&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerUtil.cpp (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerUtil.cpp Wed Jan 13 17:46:01 2016
@@ -21,12 +21,17 @@
 
 namespace fuzzer {
 
-void Print(const Unit &v, const char *PrintAfter) {
-  for (auto x : v)
-    Printf("0x%x,", (unsigned) x);
+void PrintHexArray(const uint8_t *Data, size_t Size,
+                   const char *PrintAfter) {
+  for (size_t i = 0; i < Size; i++)
+    Printf("0x%x,", (unsigned)Data[i]);
   Printf("%s", PrintAfter);
 }
 
+void Print(const Unit &v, const char *PrintAfter) {
+  PrintHexArray(v.data(), v.size(), PrintAfter);
+}
+
 void PrintASCIIByte(uint8_t Byte) {
   if (Byte == '\\')
     Printf("\\\\");




More information about the llvm-commits mailing list