]> granicus.if.org Git - llvm/commitdiff
[lib/Fuzzer] rename FuzzerDFSan.cpp to FuzzerTraceState.cpp; update comments. NFC...
authorKostya Serebryany <kcc@google.com>
Mon, 11 May 2015 21:16:27 +0000 (21:16 +0000)
committerKostya Serebryany <kcc@google.com>
Mon, 11 May 2015 21:16:27 +0000 (21:16 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@237050 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Fuzzer/CMakeLists.txt
lib/Fuzzer/FuzzerInternal.h
lib/Fuzzer/FuzzerLoop.cpp
lib/Fuzzer/FuzzerTraceState.cpp [moved from lib/Fuzzer/FuzzerDFSan.cpp with 82% similarity]

index bfd87ecc8ec9fb416a7830de417e17c17a9a592d..736950dd39619bdc813c2a21760c54216cb489df 100644 (file)
@@ -4,7 +4,7 @@ set(CMAKE_CXX_FLAGS_RELEASE "${LIBFUZZER_FLAGS_BASE} -O2 -fno-sanitize=all")
 if( LLVM_USE_SANITIZE_COVERAGE )
   add_library(LLVMFuzzerNoMain OBJECT
     FuzzerCrossOver.cpp
-    FuzzerDFSan.cpp
+    FuzzerTraceState.cpp
     FuzzerDriver.cpp
     FuzzerIO.cpp
     FuzzerLoop.cpp
index f085f94d612e9d60d9298e8a908a7e75dc79693f..f83ea96fe0fe9744600f23f62885e0bec9c04d80 100644 (file)
@@ -67,7 +67,7 @@ class Fuzzer {
   void AddToCorpus(const Unit &U) { Corpus.push_back(U); }
   void Loop(size_t NumIterations);
   void ShuffleAndMinimize();
-  void InitializeDFSan();
+  void InitializeTraceState();
   size_t CorpusSize() const { return Corpus.size(); }
   void ReadDir(const std::string &Path, long *Epoch) {
     ReadDirToVectorOfUnits(Path.c_str(), &Corpus, Epoch);
index 9f9d92e2c0c5a74cf368781b5fba0d8c13a16d17..a8ea46b4b4d8f0184d2fd159108c1da5b6a96fa6 100644 (file)
@@ -22,7 +22,7 @@ static Fuzzer *F;
 Fuzzer::Fuzzer(UserCallback Callback, FuzzingOptions Options)
     : Callback(Callback), Options(Options) {
   SetDeathCallback();
-  InitializeDFSan();
+  InitializeTraceState();
   assert(!F);
   F = this;
 }
similarity index 82%
rename from lib/Fuzzer/FuzzerDFSan.cpp
rename to lib/Fuzzer/FuzzerTraceState.cpp
index 217124d211037a2532d08ba9d98b8eff2872ecfa..c04084903809b82439d4817508fb71323d0c9494 100644 (file)
@@ -1,4 +1,4 @@
-//===- FuzzerDFSan.cpp - DFSan-based fuzzer mutator -----------------------===//
+//===- FuzzerTraceState.cpp - Trace-based fuzzer mutator ------------------===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -6,25 +6,37 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
+// This file implements a mutation algorithm based on instruction traces and
+// on taint analysis feedback from DFSan.
+//
+// Instruction traces are special hooks inserted by the compiler around
+// interesting instructions. Currently supported traces:
+//   * __sanitizer_cov_trace_cmp -- inserted before every ICMP instruction,
+//    receives the type, size and arguments of ICMP.
+//
+// Every time a traced event is intercepted we analyse the data involved
+// in the event and suggest a mutation for future executions.
+// For example if 4 bytes of data that derive from input bytes {4,5,6,7}
+// are compared with a constant 12345,
+// we try to insert 12345, 12344, 12346 into bytes
+// {4,5,6,7} of the next fuzzed inputs.
+//
+// The fuzzer can work only with the traces, or with both traces and DFSan.
+//
 // DataFlowSanitizer (DFSan) is a tool for
 // generalised dynamic data flow (taint) analysis:
 // http://clang.llvm.org/docs/DataFlowSanitizer.html .
 //
-// This file implements a mutation algorithm based on taint
-// analysis feedback from DFSan.
-//
-// The approach has some similarity to "Taint-based Directed Whitebox Fuzzing"
+// The approach with DFSan-based fuzzing has some similarity to
+// "Taint-based Directed Whitebox Fuzzing"
 // by Vijay Ganesh & Tim Leek & Martin Rinard:
 // http://dspace.mit.edu/openaccess-disseminate/1721.1/59320,
 // but it uses a full blown LLVM IR taint analysis and separate instrumentation
 // to analyze all of the "attack points" at once.
 //
-// Workflow:
+// Workflow with DFSan:
 //   * lib/Fuzzer/Fuzzer*.cpp is compiled w/o any instrumentation.
-//   * The code under test is compiled with DFSan *and* with special extra hooks
-//     that are inserted before dfsan. Currently supported hooks:
-//     - __sanitizer_cov_trace_cmp: inserted before every ICMP instruction,
-//       receives the type, size and arguments of ICMP.
+//   * The code under test is compiled with DFSan *and* with instruction traces.
 //   * Every call to HOOK(a,b) is replaced by DFSan with
 //     __dfsw_HOOK(a, b, label(a), label(b)) so that __dfsw_HOOK
 //     gets all the taint labels for the arguments.
 //   * The __dfsw_* functions (implemented in this file) record the
 //     parameters (i.e. the application data and the corresponding taint labels)
 //     in a global state.
-//   * Fuzzer::MutateWithDFSan() tries to use the data recorded by __dfsw_*
-//     hooks to guide the fuzzing towards new application states.
-//     For example if 4 bytes of data that derive from input bytes {4,5,6,7}
-//     are compared with a constant 12345 and the comparison always yields
-//     the same result, we try to insert 12345, 12344, 12346 into bytes
-//     {4,5,6,7} of the next fuzzed inputs.
+//   * Fuzzer::ApplyTraceBasedMutation() tries to use the data recorded
+//     by __dfsw_* hooks to guide the fuzzing towards new application states.
 //
-// This code does not function when DFSan is not linked in.
+// Parts of this code will not function when DFSan is not linked in.
 // Instead of using ifdefs and thus requiring a separate build of lib/Fuzzer
 // we redeclare the dfsan_* interface functions as weak and check if they
 // are nullptr before calling.
@@ -53,7 +61,7 @@
 // like test/dfsan/DFSanSimpleCmpTest.cpp.
 //===----------------------------------------------------------------------===//
 
-/* Example of manual usage:
+/* Example of manual usage (-fsanitize=dataflow is optional):
 (
   cd $LLVM/lib/Fuzzer/
   clang  -fPIC -c -g -O2 -std=c++11 Fuzzer*.cpp
@@ -168,9 +176,9 @@ struct TraceBasedMutation {
   uint64_t Data;
 };
 
-class DFSanState {
+class TraceState {
  public:
-   DFSanState(const Fuzzer::FuzzingOptions &Options, const Unit &CurrentUnit)
+   TraceState(const Fuzzer::FuzzingOptions &Options, const Unit &CurrentUnit)
        : Options(Options), CurrentUnit(CurrentUnit) {}
 
   LabelRange GetLabelRange(dfsan_label L);
@@ -208,7 +216,7 @@ class DFSanState {
   const Unit &CurrentUnit;
 };
 
-LabelRange DFSanState::GetLabelRange(dfsan_label L) {
+LabelRange TraceState::GetLabelRange(dfsan_label L) {
   LabelRange &LR = LabelRanges[L];
   if (LR.Beg < LR.End || L == 0)
     return LR;
@@ -218,7 +226,7 @@ LabelRange DFSanState::GetLabelRange(dfsan_label L) {
   return LR = LabelRange::Singleton(LI);
 }
 
-void DFSanState::ApplyTraceBasedMutation(size_t Idx, fuzzer::Unit *U) {
+void TraceState::ApplyTraceBasedMutation(size_t Idx, fuzzer::Unit *U) {
   assert(Idx < Mutations.size());
   auto &M = Mutations[Idx];
   if (Options.Verbosity >= 3)
@@ -227,7 +235,7 @@ void DFSanState::ApplyTraceBasedMutation(size_t Idx, fuzzer::Unit *U) {
   memcpy(U->data() + M.Pos, &M.Data, M.Size);
 }
 
-void DFSanState::DFSanCmpCallback(uintptr_t PC, size_t CmpSize, size_t CmpType,
+void TraceState::DFSanCmpCallback(uintptr_t PC, size_t CmpSize, size_t CmpType,
                                   uint64_t Arg1, uint64_t Arg2, dfsan_label L1,
                                   dfsan_label L2) {
   assert(ReallyHaveDFSan());
@@ -263,7 +271,7 @@ void DFSanState::DFSanCmpCallback(uintptr_t PC, size_t CmpSize, size_t CmpType,
               << "\n";
 }
 
-int DFSanState::TryToAddDesiredData(uint64_t PresentData, uint64_t DesiredData,
+int TraceState::TryToAddDesiredData(uint64_t PresentData, uint64_t DesiredData,
                                     size_t DataSize) {
   int Res = 0;
   const uint8_t *Beg = CurrentUnit.data();
@@ -284,7 +292,7 @@ int DFSanState::TryToAddDesiredData(uint64_t PresentData, uint64_t DesiredData,
   return Res;
 }
 
-void DFSanState::TraceCmpCallback(size_t CmpSize, size_t CmpType, uint64_t Arg1,
+void TraceState::TraceCmpCallback(size_t CmpSize, size_t CmpType, uint64_t Arg1,
                         uint64_t Arg2) {
   if (!Options.UseTraces) return;
   int Added = 0;
@@ -298,29 +306,29 @@ void DFSanState::TraceCmpCallback(size_t CmpSize, size_t CmpType, uint64_t Arg1,
   }
 }
 
-static DFSanState *DFSan;
+static TraceState *TS;
 
 void Fuzzer::StartTraceRecording() {
-  if (!DFSan) return;
-  DFSan->StartTraceRecording();
+  if (!TS) return;
+  TS->StartTraceRecording();
 }
 
 size_t Fuzzer::StopTraceRecording() {
-  if (!DFSan) return 0;
-  return DFSan->StopTraceRecording();
+  if (!TS) return 0;
+  return TS->StopTraceRecording();
 }
 
 void Fuzzer::ApplyTraceBasedMutation(size_t Idx, Unit *U) {
-  assert(DFSan);
-  DFSan->ApplyTraceBasedMutation(Idx, U);
+  assert(TS);
+  TS->ApplyTraceBasedMutation(Idx, U);
 }
 
-void Fuzzer::InitializeDFSan() {
-  if (!Options.UseDFSan) return;
-  DFSan = new DFSanState(Options, CurrentUnit);
+void Fuzzer::InitializeTraceState() {
+  if (!Options.UseTraces && !Options.UseDFSan) return;
+  TS = new TraceState(Options, CurrentUnit);
   CurrentUnit.resize(Options.MaxLen);
   // The rest really requires DFSan.
-  if (!ReallyHaveDFSan()) return;
+  if (!ReallyHaveDFSan() || !Options.UseDFSan) return;
   for (size_t i = 0; i < static_cast<size_t>(Options.MaxLen); i++) {
     dfsan_label L = dfsan_create_label("input", (void*)(i + 1));
     // We assume that no one else has called dfsan_create_label before.
@@ -331,22 +339,24 @@ void Fuzzer::InitializeDFSan() {
 
 }  // namespace fuzzer
 
-using fuzzer::DFSan;
+using fuzzer::TS;
 
 extern "C" {
 void __dfsw___sanitizer_cov_trace_cmp(uint64_t SizeAndType, uint64_t Arg1,
                                       uint64_t Arg2, dfsan_label L0,
                                       dfsan_label L1, dfsan_label L2) {
+  assert(TS);
   assert(L0 == 0);
   uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
   uint64_t CmpSize = (SizeAndType >> 32) / 8;
   uint64_t Type = (SizeAndType << 32) >> 32;
-  DFSan->DFSanCmpCallback(PC, CmpSize, Type, Arg1, Arg2, L1, L2);
+  TS->DFSanCmpCallback(PC, CmpSize, Type, Arg1, Arg2, L1, L2);
 }
 
 void dfsan_weak_hook_memcmp(void *caller_pc, const void *s1, const void *s2,
                             size_t n, dfsan_label s1_label,
                             dfsan_label s2_label, dfsan_label n_label) {
+  assert(TS);
   uintptr_t PC = reinterpret_cast<uintptr_t>(caller_pc);
   uint64_t S1 = 0, S2 = 0;
   // Simplification: handle only first 8 bytes.
@@ -354,15 +364,15 @@ void dfsan_weak_hook_memcmp(void *caller_pc, const void *s1, const void *s2,
   memcpy(&S2, s2, std::min(n, sizeof(S2)));
   dfsan_label L1 = dfsan_read_label(s1, n);
   dfsan_label L2 = dfsan_read_label(s2, n);
-  DFSan->DFSanCmpCallback(PC, n, fuzzer::ICMP_EQ, S1, S2, L1, L2);
+  TS->DFSanCmpCallback(PC, n, fuzzer::ICMP_EQ, S1, S2, L1, L2);
 }
 
 void __sanitizer_cov_trace_cmp(uint64_t SizeAndType, uint64_t Arg1,
                                uint64_t Arg2) {
-  if (!DFSan) return;
+  if (!TS) return;
   uint64_t CmpSize = (SizeAndType >> 32) / 8;
   uint64_t Type = (SizeAndType << 32) >> 32;
-  DFSan->TraceCmpCallback(CmpSize, Type, Arg1, Arg2);
+  TS->TraceCmpCallback(CmpSize, Type, Arg1, Arg2);
 }
 
 }  // extern "C"