[libFuzzer] add -only_ascii flag
authorKostya Serebryany <kcc@google.com>
Tue, 11 Aug 2015 01:44:42 +0000 (01:44 +0000)
committerKostya Serebryany <kcc@google.com>
Tue, 11 Aug 2015 01:44:42 +0000 (01:44 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@244559 91177308-0d34-0410-b5e6-96231b3b80d8

docs/LibFuzzer.rst
lib/Fuzzer/FuzzerDriver.cpp
lib/Fuzzer/FuzzerFlags.def
lib/Fuzzer/FuzzerInternal.h
lib/Fuzzer/FuzzerLoop.cpp
lib/Fuzzer/FuzzerUtil.cpp

index 0eabb5d..4aeace1 100644 (file)
@@ -69,6 +69,7 @@ The most important flags are::
   sync_command                         0       Execute an external command "<sync_command> <test_corpus>" to synchronize the test corpus.
   sync_timeout                         600     Minimum timeout between syncs.
   use_traces                            0       Experimental: use instruction traces
+  only_ascii                            0       If 1, generate only ASCII (isprint+isspace) inputs.
 
 
 For the full list of flags run the fuzzer binary with ``-help=1``.
index 7f3ec7b..4136e01 100644 (file)
@@ -240,6 +240,7 @@ int FuzzerDriver(int argc, char **argv, UserSuppliedFuzzer &USF) {
       Flags.prefer_small_during_initial_shuffle;
   Options.Tokens = ReadTokensFile(Flags.tokens);
   Options.Reload = Flags.reload;
+  Options.OnlyASCII = Flags.only_ascii;
   if (Flags.runs >= 0)
     Options.MaxNumberOfRuns = Flags.runs;
   if (!inputs.empty())
index ac3ac6e..91aff99 100644 (file)
@@ -60,3 +60,5 @@ FUZZER_FLAG_STRING(sync_command, "Execute an external command "
 FUZZER_FLAG_INT(sync_timeout, 600, "Minimum timeout between syncs.")
 FUZZER_FLAG_INT(report_slow_units, 10,
     "Report slowest units if they run for more than this number of seconds.")
+FUZZER_FLAG_INT(only_ascii, 0,
+                "If 1, generate only ASCII (isprint+isspace) inputs.")
index abda08b..6f7525e 100644 (file)
@@ -50,6 +50,10 @@ static const int kSHA1NumBytes = 20;
 // Computes SHA1 hash of 'Len' bytes in 'Data', writes kSHA1NumBytes to 'Out'.
 void ComputeSHA1(const uint8_t *Data, size_t Len, uint8_t *Out);
 
+// Changes U to contain only ASCII (isprint+isspace) characters.
+// Returns true iff U has been changed.
+bool ToASCII(Unit &U);
+
 int NumberOfCpuCores();
 
 class Fuzzer {
@@ -69,6 +73,7 @@ class Fuzzer {
     size_t MaxNumberOfRuns = ULONG_MAX;
     int SyncTimeout = 600;
     int ReportSlowUnits = 10;
+    bool OnlyASCII = false;
     std::string OutputCorpus;
     std::string SyncCommand;
     std::vector<std::string> Tokens;
@@ -103,7 +108,7 @@ class Fuzzer {
   void MutateAndTestOne(Unit *U);
   void ReportNewCoverage(size_t NewCoverage, const Unit &U);
   size_t RunOne(const Unit &U);
-  void RunOneAndUpdateCorpus(const Unit &U);
+  void RunOneAndUpdateCorpus(Unit &U);
   size_t RunOneMaximizeTotalCoverage(const Unit &U);
   size_t RunOneMaximizeFullCoverageSet(const Unit &U);
   size_t RunOneMaximizeCoveragePairs(const Unit &U);
index 69b49b0..3f7fcb5 100644 (file)
@@ -170,9 +170,11 @@ size_t Fuzzer::RunOne(const Unit &U) {
   return Res;
 }
 
-void Fuzzer::RunOneAndUpdateCorpus(const Unit &U) {
+void Fuzzer::RunOneAndUpdateCorpus(Unit &U) {
   if (TotalNumberOfRuns >= Options.MaxNumberOfRuns)
     return;
+  if (Options.OnlyASCII)
+    ToASCII(U);
   ReportNewCoverage(RunOne(U), U);
 }
 
@@ -251,6 +253,9 @@ void Fuzzer::WriteToOutputCorpus(const Unit &U) {
   WriteToFile(U, Path);
   if (Options.Verbosity >= 2)
     Printf("Written to %s\n", Path.c_str());
+  if (Options.OnlyASCII)
+    for (auto X : U)
+      assert(isprint(X) || isspace(X));
 }
 
 void Fuzzer::WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix) {
index e381c04..e76adb3 100644 (file)
@@ -73,4 +73,17 @@ void ExecuteCommand(const std::string &Command) {
   system(Command.c_str());
 }
 
+bool ToASCII(Unit &U) {
+  bool Changed = false;
+  for (auto &X : U) {
+    auto NewX = X;
+    NewX &= 127;
+    if (!isspace(NewX) && !isprint(NewX))
+      NewX = ' ';
+    Changed |= NewX != X;
+    X = NewX;
+  }
+  return Changed;
+}
+
 }  // namespace fuzzer