[compiler-rt] r337696 - [libFuzzer] Handle unstable edges by using minimum hit counts

Max Moroz via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 23 07:20:52 PDT 2018


Author: dor1s
Date: Mon Jul 23 07:20:52 2018
New Revision: 337696

URL: http://llvm.org/viewvc/llvm-project?rev=337696&view=rev
Log:
[libFuzzer] Handle unstable edges by using minimum hit counts

Summary:
Created unstable_handle flag that takes 1 or 2, depending on the handling type.
Modified RunOne to accommodate the following heuristic:
    Use the first CollectFeatures to count how many features there are.
    If no new features, CollectFeatures like before.
    If there is new feature, we run CB 2 more times,
        Check which edges are unstable per input and we store the least amount of hit counts for each edge.
        Apply these hit counts back to inline8bitcounters so that CollectFeatures can work as intended.
Modified UnstableCounters to 8int_t and created a bitset UnstableSet to tell which edges are unstable.

Patch by Kyungtak Woo (@kevinwkt).

Reviewers: Dor1s, metzman, morehouse

Reviewed By: Dor1s, morehouse

Subscribers: delcypher, #sanitizers, llvm-commits, kcc

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

Added:
    compiler-rt/trunk/test/fuzzer/handle_unstable_minunstable.test
Modified:
    compiler-rt/trunk/lib/fuzzer/FuzzerCorpus.h
    compiler-rt/trunk/lib/fuzzer/FuzzerDriver.cpp
    compiler-rt/trunk/lib/fuzzer/FuzzerFlags.def
    compiler-rt/trunk/lib/fuzzer/FuzzerLoop.cpp
    compiler-rt/trunk/lib/fuzzer/FuzzerOptions.h
    compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.cpp
    compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.h

Modified: compiler-rt/trunk/lib/fuzzer/FuzzerCorpus.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerCorpus.h?rev=337696&r1=337695&r2=337696&view=diff
==============================================================================
--- compiler-rt/trunk/lib/fuzzer/FuzzerCorpus.h (original)
+++ compiler-rt/trunk/lib/fuzzer/FuzzerCorpus.h Mon Jul 23 07:20:52 2018
@@ -238,6 +238,12 @@ class InputCorpus {
     return false;
   }
 
+  bool IsFeatureNew(size_t Idx, uint32_t NewSize, bool Shrink) {
+    assert(NewSize);
+    uint32_t OldSize = GetFeature(Idx % kFeatureSetSize);
+    return OldSize == 0 || (Shrink && OldSize > NewSize);
+  }
+
   size_t NumFeatures() const { return NumAddedFeatures; }
   size_t NumFeatureUpdates() const { return NumUpdatedFeatures; }
 

Modified: compiler-rt/trunk/lib/fuzzer/FuzzerDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerDriver.cpp?rev=337696&r1=337695&r2=337696&view=diff
==============================================================================
--- compiler-rt/trunk/lib/fuzzer/FuzzerDriver.cpp (original)
+++ compiler-rt/trunk/lib/fuzzer/FuzzerDriver.cpp Mon Jul 23 07:20:52 2018
@@ -619,6 +619,8 @@ int FuzzerDriver(int *argc, char ***argv
   Options.PrintCorpusStats = Flags.print_corpus_stats;
   Options.PrintCoverage = Flags.print_coverage;
   Options.PrintUnstableStats = Flags.print_unstable_stats;
+  if (Flags.handle_unstable)
+    Options.HandleUnstable = Flags.handle_unstable;
   Options.DumpCoverage = Flags.dump_coverage;
   if (Flags.exit_on_src_pos)
     Options.ExitOnSrcPos = Flags.exit_on_src_pos;

Modified: compiler-rt/trunk/lib/fuzzer/FuzzerFlags.def
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerFlags.def?rev=337696&r1=337695&r2=337696&view=diff
==============================================================================
--- compiler-rt/trunk/lib/fuzzer/FuzzerFlags.def (original)
+++ compiler-rt/trunk/lib/fuzzer/FuzzerFlags.def Mon Jul 23 07:20:52 2018
@@ -110,6 +110,11 @@ FUZZER_FLAG_INT(print_coverage, 0, "If 1
 FUZZER_FLAG_INT(dump_coverage, 0, "Deprecated."
                                   " If 1, dump coverage information as a"
                                   " .sancov file at exit.")
+FUZZER_FLAG_INT(handle_unstable, 0, "Experimental."
+                   " Executes every input 3 times in total if a unique feature"
+                   " is found during the first execution."
+                   " If 1, we only use the minimum hit count from the 3 runs"
+                   " to determine whether an input is interesting.")
 FUZZER_FLAG_INT(print_unstable_stats, 0, "Experimental."
 				  " If 1, print unstable statistics at exit.")
 FUZZER_FLAG_INT(handle_segv, 1, "If 1, try to intercept SIGSEGV.")

Modified: compiler-rt/trunk/lib/fuzzer/FuzzerLoop.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerLoop.cpp?rev=337696&r1=337695&r2=337696&view=diff
==============================================================================
--- compiler-rt/trunk/lib/fuzzer/FuzzerLoop.cpp (original)
+++ compiler-rt/trunk/lib/fuzzer/FuzzerLoop.cpp Mon Jul 23 07:20:52 2018
@@ -465,11 +465,15 @@ void Fuzzer::CheckForUnstableCounters(co
 
   // First Rerun
   CBSetupAndRun();
-  TPC.UpdateUnstableCounters();
+  TPC.UpdateUnstableCounters(Options.HandleUnstable);
 
   // Second Rerun
   CBSetupAndRun();
-  TPC.UpdateUnstableCounters();
+  TPC.UpdateUnstableCounters(Options.HandleUnstable);
+
+  // Move minimum hit counts back to ModuleInline8bitCounters
+  if (Options.HandleUnstable)
+    TPC.ApplyUnstableCounters();
 }
 
 bool Fuzzer::RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile,
@@ -482,6 +486,17 @@ bool Fuzzer::RunOne(const uint8_t *Data,
   UniqFeatureSetTmp.clear();
   size_t FoundUniqFeaturesOfII = 0;
   size_t NumUpdatesBefore = Corpus.NumFeatureUpdates();
+  bool NewFeaturesUnstable = false;
+
+  if (Options.HandleUnstable || Options.PrintUnstableStats) {
+    TPC.CollectFeatures([&](size_t Feature) {
+      if (Corpus.IsFeatureNew(Feature, Size, Options.Shrink))
+        NewFeaturesUnstable = true;
+    });
+    if (NewFeaturesUnstable)
+      CheckForUnstableCounters(Data, Size);
+  }
+
   TPC.CollectFeatures([&](size_t Feature) {
     if (Corpus.AddFeature(Feature, Size, Options.Shrink))
       UniqFeatureSetTmp.push_back(Feature);
@@ -490,16 +505,12 @@ bool Fuzzer::RunOne(const uint8_t *Data,
                              II->UniqFeatureSet.end(), Feature))
         FoundUniqFeaturesOfII++;
   });
+
   if (FoundUniqFeatures)
     *FoundUniqFeatures = FoundUniqFeaturesOfII;
   PrintPulseAndReportSlowInput(Data, Size);
   size_t NumNewFeatures = Corpus.NumFeatureUpdates() - NumUpdatesBefore;
 
-  // If print_unstable_stats, execute the same input two more times to detect
-  // unstable edges.
-  if (NumNewFeatures && Options.PrintUnstableStats)
-    CheckForUnstableCounters(Data, Size);
-
   if (NumNewFeatures) {
     TPC.UpdateObservedPCs();
     Corpus.AddToCorpus({Data, Data + Size}, NumNewFeatures, MayDeleteFile,

Modified: compiler-rt/trunk/lib/fuzzer/FuzzerOptions.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerOptions.h?rev=337696&r1=337695&r2=337696&view=diff
==============================================================================
--- compiler-rt/trunk/lib/fuzzer/FuzzerOptions.h (original)
+++ compiler-rt/trunk/lib/fuzzer/FuzzerOptions.h Mon Jul 23 07:20:52 2018
@@ -56,6 +56,7 @@ struct FuzzingOptions {
   bool PrintCorpusStats = false;
   bool PrintCoverage = false;
   bool PrintUnstableStats = false;
+  int HandleUnstable = 0;
   bool DumpCoverage = false;
   bool DetectLeaks = true;
   int PurgeAllocatorIntervalSec = 1;

Modified: compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.cpp?rev=337696&r1=337695&r2=337696&view=diff
==============================================================================
--- compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.cpp (original)
+++ compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.cpp Mon Jul 23 07:20:52 2018
@@ -75,17 +75,26 @@ void TracePC::IterateInline8bitCounters(
 // counters.
 void TracePC::InitializeUnstableCounters() {
   IterateInline8bitCounters([&](int i, int j, int UnstableIdx) {
-    if (UnstableCounters[UnstableIdx] != kUnstableCounter)
-      UnstableCounters[UnstableIdx] = ModuleCounters[i].Start[j];
+    UnstableCounters[UnstableIdx].Counter = ModuleCounters[i].Start[j];
   });
 }
 
 // Compares the current counters with counters from previous runs
 // and records differences as unstable edges.
-void TracePC::UpdateUnstableCounters() {
+void TracePC::UpdateUnstableCounters(int UnstableMode) {
   IterateInline8bitCounters([&](int i, int j, int UnstableIdx) {
-    if (ModuleCounters[i].Start[j] != UnstableCounters[UnstableIdx])
-      UnstableCounters[UnstableIdx] = kUnstableCounter;
+    if (ModuleCounters[i].Start[j] != UnstableCounters[UnstableIdx].Counter)
+      UnstableCounters[UnstableIdx].IsUnstable = true;
+    if (UnstableMode &&
+        ModuleCounters[i].Start[j] < UnstableCounters[UnstableIdx].Counter)
+      UnstableCounters[UnstableIdx].Counter = ModuleCounters[i].Start[j];
+  });
+}
+
+// Moves the minimum hit counts to ModuleCounters.
+void TracePC::ApplyUnstableCounters() {
+  IterateInline8bitCounters([&](int i, int j, int UnstableIdx) {
+    ModuleCounters[i].Start[j] = UnstableCounters[UnstableIdx].Counter;
   });
 }
 
@@ -340,7 +349,7 @@ void TracePC::DumpCoverage() {
 void TracePC::PrintUnstableStats() {
   size_t count = 0;
   for (size_t i = 0; i < NumInline8bitCounters; i++)
-    if (UnstableCounters[i] == kUnstableCounter)
+    if (UnstableCounters[i].IsUnstable)
       count++;
   Printf("stat::stability_rate: %.2f\n",
          100 - static_cast<float>(count * 100) / NumInline8bitCounters);

Modified: compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.h?rev=337696&r1=337695&r2=337696&view=diff
==============================================================================
--- compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.h (original)
+++ compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.h Mon Jul 23 07:20:52 2018
@@ -138,15 +138,16 @@ class TracePC {
   bool ObservedFocusFunction();
 
   void InitializeUnstableCounters();
-  void UpdateUnstableCounters();
+  void UpdateUnstableCounters(int UnstableMode);
+  void ApplyUnstableCounters();
 
 private:
-  // Value used to represent unstable edge.
-  static constexpr int16_t kUnstableCounter = -1;
+  struct UnstableEdge {
+    uint8_t Counter;
+    bool IsUnstable;
+  };
 
-  // Uses 16-bit signed type to be able to accommodate any possible value from
-  // uint8_t counter and -1 constant as well.
-  int16_t UnstableCounters[kNumPCs];
+  UnstableEdge UnstableCounters[kNumPCs];
 
   bool UseCounters = false;
   uint32_t UseValueProfileMask = false;

Added: compiler-rt/trunk/test/fuzzer/handle_unstable_minunstable.test
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/fuzzer/handle_unstable_minunstable.test?rev=337696&view=auto
==============================================================================
--- compiler-rt/trunk/test/fuzzer/handle_unstable_minunstable.test (added)
+++ compiler-rt/trunk/test/fuzzer/handle_unstable_minunstable.test Mon Jul 23 07:20:52 2018
@@ -0,0 +1,12 @@
+RUN: %cpp_compiler %S/PrintUnstableStatsTest.cpp -o %t-HandleUnstableMinUnstableTest
+RUN: %run %t-HandleUnstableMinUnstableTest -print_coverage=1 -handle_unstable=1 -runs=100000 2>&1 | FileCheck %s --check-prefix=UNSTABLE
+UNSTABLE-NOT: ini0()
+UNSTABLE-NOT: ini1()
+UNSTABLE-NOT: ini2()
+
+RUN: %run %t-HandleUnstableMinUnstableTest -print_coverage=1 -runs=100000 2>&1 | FileCheck %s --check-prefix=NORMAL
+NORMAL-DAG: ini0()
+NORMAL-DAG: ini1()
+NORMAL-DAG: ini2()
+
+




More information about the llvm-commits mailing list