[libFuzzer] introduce an experimental mode -fork=1, where fuzzing happens in a subprocess (still running multiple inputs per process), thus making the fuzzing more resilient to timeouts and OOMs. This is just a skeleton of the code, and some associated refactoring, not a fully working feature yet. 

git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk/lib/fuzzer@353570 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/FuzzerMerge.cpp b/FuzzerMerge.cpp
index 77b8a78..b4f05e3 100644
--- a/FuzzerMerge.cpp
+++ b/FuzzerMerge.cpp
@@ -122,7 +122,7 @@
 
 // Decides which files need to be merged (add thost to NewFiles).
 // Returns the number of new features added.
-size_t Merger::Merge(const Set<uint32_t> &InitialFeatures,
+size_t Merger::Merge(const Set<uint32_t> &InitialFeatures, 
                      Vector<std::string> *NewFiles) {
   NewFiles->clear();
   assert(NumFilesInFirstCorpus <= Files.size());
@@ -223,7 +223,7 @@
   std::ofstream OF(CFPath, std::ofstream::out | std::ofstream::app);
   Set<size_t> AllFeatures;
   for (size_t i = M.FirstNotProcessedFile; i < M.Files.size(); i++) {
-    MaybeExitGracefully();
+    Fuzzer::MaybeExitGracefully();
     auto U = FileToVector(M.Files[i].Name);
     if (U.size() > MaxInputLen) {
       U.resize(MaxInputLen);
@@ -275,27 +275,18 @@
 }
 
 // Outer process. Does not call the target code and thus sohuld not fail.
-void Fuzzer::CrashResistantMerge(const Vector<std::string> &Args,
-                                 const Vector<std::string> &Corpora,
-                                 const char *CoverageSummaryInputPathOrNull,
-                                 const char *CoverageSummaryOutputPathOrNull,
-                                 const char *MergeControlFilePathOrNull) {
-  if (Corpora.size() <= 1) {
-    Printf("Merge requires two or more corpus dirs\n");
-    return;
-  }
-  auto CFPath =
-      MergeControlFilePathOrNull
-          ? MergeControlFilePathOrNull
-          : DirPlusFile(TmpDir(),
-                        "libFuzzerTemp." + std::to_string(GetPid()) + ".txt");
-
+Vector<std::string>
+CrashResistantMerge(const Vector<std::string> &Args,
+                    const Vector<std::string> &Corpora,
+                    const std::string &CFPath,
+                    const char *CoverageSummaryInputPathOrNull,
+                    const char *CoverageSummaryOutputPathOrNull) {
   size_t NumAttempts = 0;
-  if (MergeControlFilePathOrNull && FileSize(MergeControlFilePathOrNull)) {
+  if (FileSize(CFPath)) {
     Printf("MERGE-OUTER: non-empty control file provided: '%s'\n",
-           MergeControlFilePathOrNull);
+           CFPath.c_str());
     Merger M;
-    std::ifstream IF(MergeControlFilePathOrNull);
+    std::ifstream IF(CFPath);
     if (M.Parse(IF, /*ParseCoverage=*/false)) {
       Printf("MERGE-OUTER: control file ok, %zd files total,"
              " first not processed file %zd\n",
@@ -334,9 +325,10 @@
   // Every inner process should execute at least one input.
   Command BaseCmd(Args);
   BaseCmd.removeFlag("merge");
+  BaseCmd.removeFlag("fork");
   bool Success = false;
   for (size_t Attempt = 1; Attempt <= NumAttempts; Attempt++) {
-    MaybeExitGracefully();
+    Fuzzer::MaybeExitGracefully();
     Printf("MERGE-OUTER: attempt %zd\n", Attempt);
     Command Cmd(BaseCmd);
     Cmd.addFlag("merge_control_file", CFPath);
@@ -368,7 +360,6 @@
     std::ofstream SummaryOut(CoverageSummaryOutputPathOrNull);
     M.PrintSummary(SummaryOut);
   }
-  Vector<std::string> NewFiles;
   Set<uint32_t> InitialFeatures;
   if (CoverageSummaryInputPathOrNull) {
     std::ifstream SummaryIn(CoverageSummaryInputPathOrNull);
@@ -376,14 +367,11 @@
     Printf("MERGE-OUTER: coverage summary loaded from %s, %zd features found\n",
            CoverageSummaryInputPathOrNull, InitialFeatures.size());
   }
+  Vector<std::string> NewFiles;
   size_t NumNewFeatures = M.Merge(InitialFeatures, &NewFiles);
   Printf("MERGE-OUTER: %zd new files with %zd new features added\n",
          NewFiles.size(), NumNewFeatures);
-  for (auto &F: NewFiles)
-    WriteToOutputCorpus(FileToVector(F, MaxInputLen));
-  // We are done, delete the control file if it was a temporary one.
-  if (!MergeControlFilePathOrNull)
-    RemoveFile(CFPath);
+  return NewFiles;
 }
 
 } // namespace fuzzer