[libFuzzer] allow passing 1 or more files as individual inputs
authorKostya Serebryany <kcc@google.com>
Tue, 2 Feb 2016 03:03:47 +0000 (03:03 +0000)
committerKostya Serebryany <kcc@google.com>
Tue, 2 Feb 2016 03:03:47 +0000 (03:03 +0000)
llvm-svn: 259459

llvm/docs/LibFuzzer.rst
llvm/lib/Fuzzer/FuzzerDriver.cpp
llvm/lib/Fuzzer/FuzzerIO.cpp
llvm/lib/Fuzzer/FuzzerInternal.h
llvm/lib/Fuzzer/test/fuzzer.test

index b4c8919..914a782 100644 (file)
@@ -51,8 +51,16 @@ and is used to fuzz various parts of LLVM,
 but the Fuzzer itself does not (and should not) depend on any
 part of LLVM and can be used for other projects w/o requiring the rest of LLVM.
 
-Flags
-=====
+Usage:
+======
+To run fuzzing pass 0 or more directories::
+
+./fuzzer [-flag1=val1 [-flag2=val2 ...] ] [dir1 [dir2 ...] ]
+
+To run individual tests without fuzzing pass 1 or more files::
+
+./fuzzer [-flag1=val1 [-flag2=val2 ...] ] file1 [file2 ...]
+
 The most important flags are::
 
   seed                                 0       Random seed. If 0, seed is generated.
@@ -72,7 +80,6 @@ The most important flags are::
   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.
-  test_single_input                     ""      Use specified file content as test input. Test will be run only once. Useful for debugging a particular case.
   artifact_prefix                       ""      Write fuzzing artifacts (crash, timeout, or slow inputs) as $(artifact_prefix)file
   exact_artifact_path                   ""      Write the single artifact on failure (crash, timeout) as $(exact_artifact_path). This overrides -artifact_prefix and will not use checksum in the file name. Do not use the same path for several parallel processes.
 
index e73feaf..8c81c9d 100644 (file)
@@ -70,8 +70,14 @@ static std::vector<std::string> *Inputs;
 static std::string *ProgName;
 
 static void PrintHelp() {
-  Printf("Usage: %s [-flag1=val1 [-flag2=val2 ...] ] [dir1 [dir2 ...] ]\n",
-         ProgName->c_str());
+  Printf("Usage:\n");
+  auto Prog = ProgName->c_str();
+  Printf("\nTo run fuzzing pass 0 or more directories.\n");
+  Printf("%s [-flag1=val1 [-flag2=val2 ...] ] [dir1 [dir2 ...] ]\n", Prog);
+
+  Printf("\nTo run individual tests without fuzzing pass 1 or more files:\n");
+  Printf("%s [-flag1=val1 [-flag2=val2 ...] ] file1 [file2 ...]\n", Prog);
+
   Printf("\nFlags: (strictly in form -flag=value)\n");
   size_t MaxFlagLen = 0;
   for (size_t F = 0; F < kNumFlags; F++)
@@ -227,6 +233,14 @@ int RunOneTest(Fuzzer *F, const char *InputFilePath) {
   return 0;
 }
 
+static bool AllInputsAreFiles() {
+  if (Inputs->empty()) return false;
+  for (auto &Path : *Inputs)
+    if (!IsFile(Path))
+      return false;
+  return true;
+}
+
 int FuzzerDriver(int argc, char **argv, UserCallback Callback) {
   FuzzerRandom_mt19937 Rand(0);
   SimpleUserSuppliedFuzzer SUSF(&Rand, Callback);
@@ -320,6 +334,18 @@ int FuzzerDriver(const std::vector<std::string> &Args,
     exit(0);
   }
 
+  if (AllInputsAreFiles()) {
+    Printf("%s: Running %zd inputs.\n", ProgName->c_str(), Inputs->size());
+    for (auto &Path : *Inputs) {
+      auto StartTime = system_clock::now();
+      RunOneTest(&F, Path.c_str());
+      auto StopTime = system_clock::now();
+      auto MS = duration_cast<milliseconds>(StopTime - StartTime).count();
+      Printf("%s: %zd ms\n", Path.c_str(), (long)MS);
+    }
+    exit(0);
+  }
+
   if (Flags.save_minimized_corpus) {
     Printf("The flag -save_minimized_corpus is deprecated; use -merge=1\n");
     exit(1);
index cc65876..9df6837 100644 (file)
 
 namespace fuzzer {
 
+bool IsFile(const std::string &Path) {
+  struct stat St;
+  if (stat(Path.c_str(), &St))
+    return false;
+  return S_ISREG(St.st_mode);
+}
+
 static long GetEpoch(const std::string &Path) {
   struct stat St;
   if (stat(Path.c_str(), &St))
index d506f8f..07f45af 100644 (file)
@@ -62,6 +62,7 @@ private:
 
 typedef FixedWord<27> Word; // 28 bytes.
 
+bool IsFile(const std::string &Path);
 std::string FileToString(const std::string &Path);
 Unit FileToVector(const std::string &Path);
 void ReadDirToVectorOfUnits(const char *Path, std::vector<Unit> *V,
index 86ef32a..3a61778 100644 (file)
@@ -45,3 +45,15 @@ CHECK_SEED_MINUS_ONE: Seed: 4294967295
 
 RUN: not LLVMFuzzer-SimpleTest NONEXISTENT_DIR 2>&1 | FileCheck %s --check-prefix=NONEXISTENT_DIR
 NONEXISTENT_DIR: No such directory: NONEXISTENT_DIR; exiting
+
+
+RUN: rm -rf  %tmp/SINGLE_INPUTS
+RUN: mkdir -p  %tmp/SINGLE_INPUTS
+RUN: echo aaa > %tmp/SINGLE_INPUTS/aaa
+RUN: echo bbb > %tmp/SINGLE_INPUTS/bbb
+RUN: LLVMFuzzer-SimpleTest %tmp/SINGLE_INPUTS/aaa %tmp/SINGLE_INPUTS/bbb 2>&1 | FileCheck %s --check-prefix=SINGLE_INPUTS
+RUN: rm -rf  %tmp/SINGLE_INPUTS
+SINGLE_INPUTS: LLVMFuzzer-SimpleTest: Running 2 inputs.
+SINGLE_INPUTS: aaa:
+SINGLE_INPUTS: bbb:
+