[llvm] r324225 - [llvm-opt-fuzzer] Avoid adding incorrect inputs to the fuzzer corpus

Igor Laevsky via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 5 03:05:47 PST 2018


Author: igor.laevsky
Date: Mon Feb  5 03:05:47 2018
New Revision: 324225

URL: http://llvm.org/viewvc/llvm-project?rev=324225&view=rev
Log:
[llvm-opt-fuzzer] Avoid adding incorrect inputs to the fuzzer corpus

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


Modified:
    llvm/trunk/include/llvm/FuzzMutate/FuzzerCLI.h
    llvm/trunk/lib/FuzzMutate/FuzzerCLI.cpp
    llvm/trunk/tools/llvm-isel-fuzzer/llvm-isel-fuzzer.cpp
    llvm/trunk/tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp

Modified: llvm/trunk/include/llvm/FuzzMutate/FuzzerCLI.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/FuzzMutate/FuzzerCLI.h?rev=324225&r1=324224&r2=324225&view=diff
==============================================================================
--- llvm/trunk/include/llvm/FuzzMutate/FuzzerCLI.h (original)
+++ llvm/trunk/include/llvm/FuzzMutate/FuzzerCLI.h Mon Feb  5 03:05:47 2018
@@ -68,6 +68,12 @@ std::unique_ptr<Module> parseModule(cons
 ///         returns 0 and leaves Dest unchanged.
 size_t writeModule(const Module &M, uint8_t *Dest, size_t MaxSize);
 
+/// Try to parse module and verify it. May output verification errors to the
+/// errs().
+/// \return New module or nullptr in case of error.
+std::unique_ptr<Module> parseAndVerify(const uint8_t *Data, size_t Size,
+                                       LLVMContext &Context);
+
 } // end llvm namespace
 
 #endif // LLVM_FUZZMUTATE_FUZZER_CLI_H

Modified: llvm/trunk/lib/FuzzMutate/FuzzerCLI.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/FuzzMutate/FuzzerCLI.cpp?rev=324225&r1=324224&r2=324225&view=diff
==============================================================================
--- llvm/trunk/lib/FuzzMutate/FuzzerCLI.cpp (original)
+++ llvm/trunk/lib/FuzzMutate/FuzzerCLI.cpp Mon Feb  5 03:05:47 2018
@@ -18,6 +18,7 @@
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/SourceMgr.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/IR/Verifier.h"
 
 using namespace llvm;
 
@@ -175,3 +176,12 @@ size_t llvm::writeModule(const Module &M
   memcpy(Dest, Buf.data(), Buf.size());
   return Buf.size();
 }
+
+std::unique_ptr<Module> llvm::parseAndVerify(const uint8_t *Data, size_t Size,
+                                             LLVMContext &Context) {
+  auto M = parseModule(Data, Size, Context);
+  if (!M || verifyModule(*M, &errs()))
+    return nullptr;
+  
+  return M;
+}

Modified: llvm/trunk/tools/llvm-isel-fuzzer/llvm-isel-fuzzer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-isel-fuzzer/llvm-isel-fuzzer.cpp?rev=324225&r1=324224&r2=324225&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-isel-fuzzer/llvm-isel-fuzzer.cpp (original)
+++ llvm/trunk/tools/llvm-isel-fuzzer/llvm-isel-fuzzer.cpp Mon Feb  5 03:05:47 2018
@@ -84,8 +84,8 @@ extern "C" int LLVMFuzzerTestOneInput(co
     return 0;
 
   LLVMContext Context;
-  auto M = parseModule(Data, Size, Context);
-  if (!M || verifyModule(*M, &errs())) {
+  auto M = parseAndVerify(Data, Size, Context);
+  if (!M) {
     errs() << "error: input module is broken!\n";
     return 0;
   }

Modified: llvm/trunk/tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp?rev=324225&r1=324224&r2=324225&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp (original)
+++ llvm/trunk/tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp Mon Feb  5 03:05:47 2018
@@ -57,23 +57,45 @@ extern "C" LLVM_ATTRIBUTE_USED size_t LL
       "IR mutator should have been created during fuzzer initialization");
 
   LLVMContext Context;
-  auto M = parseModule(Data, Size, Context);
-  if (!M || verifyModule(*M, &errs())) {
+  auto M = parseAndVerify(Data, Size, Context);
+  if (!M) {
     errs() << "error: mutator input module is broken!\n";
     return 0;
   }
 
   Mutator->mutateModule(*M, Seed, Size, MaxSize);
 
-#ifndef NDEBUG
   if (verifyModule(*M, &errs())) {
     errs() << "mutation result doesn't pass verification\n";
     M->dump();
-    abort();
+    // Avoid adding incorrect test cases to the corpus.
+    return 0;
+  }
+  
+  std::string Buf;
+  {
+    raw_string_ostream OS(Buf);
+    WriteBitcodeToFile(M.get(), OS);
+  }
+  if (Buf.size() > MaxSize)
+    return 0;
+  
+  // There are some invariants which are not checked by the verifier in favor
+  // of having them checked by the parser. They may be considered as bugs in the
+  // verifier and should be fixed there. However until all of those are covered
+  // we want to check for them explicitly. Otherwise we will add incorrect input
+  // to the corpus and this is going to confuse the fuzzer which will start 
+  // exploration of the bitcode reader error handling code.
+  auto NewM = parseAndVerify(
+      reinterpret_cast<const uint8_t*>(Buf.data()), Buf.size(), Context);
+  if (!NewM) {
+    errs() << "mutator failed to re-read the module\n";
+    M->dump();
+    return 0;
   }
-#endif
 
-  return writeModule(*M, Data, MaxSize);
+  memcpy(Data, Buf.data(), Buf.size());
+  return Buf.size();
 }
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
@@ -87,8 +109,8 @@ extern "C" int LLVMFuzzerTestOneInput(co
   //
 
   LLVMContext Context;
-  auto M = parseModule(Data, Size, Context);
-  if (!M || verifyModule(*M, &errs())) {
+  auto M = parseAndVerify(Data, Size, Context);
+  if (!M) {
     errs() << "error: input module is broken!\n";
     return 0;
   }




More information about the llvm-commits mailing list