summaryrefslogtreecommitdiffstats
path: root/compiler-rt/lib/fuzzer/FuzzerDriver.cpp
diff options
context:
space:
mode:
authorKostya Serebryany <kcc@google.com>2019-02-08 21:27:23 +0000
committerKostya Serebryany <kcc@google.com>2019-02-08 21:27:23 +0000
commitf762a11544b77bcb5cbb45e9726562018cd5c8fa (patch)
treed9a22b41759cdc51c01d54feeb26a7d1a5a23044 /compiler-rt/lib/fuzzer/FuzzerDriver.cpp
parent3bf72d7d64b8465acd4f4af1a469d68d9dc86058 (diff)
downloadbcm5719-llvm-f762a11544b77bcb5cbb45e9726562018cd5c8fa.tar.gz
bcm5719-llvm-f762a11544b77bcb5cbb45e9726562018cd5c8fa.zip
[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.
llvm-svn: 353570
Diffstat (limited to 'compiler-rt/lib/fuzzer/FuzzerDriver.cpp')
-rw-r--r--compiler-rt/lib/fuzzer/FuzzerDriver.cpp68
1 files changed, 58 insertions, 10 deletions
diff --git a/compiler-rt/lib/fuzzer/FuzzerDriver.cpp b/compiler-rt/lib/fuzzer/FuzzerDriver.cpp
index 2bc895d008c..418bebb9388 100644
--- a/compiler-rt/lib/fuzzer/FuzzerDriver.cpp
+++ b/compiler-rt/lib/fuzzer/FuzzerDriver.cpp
@@ -16,6 +16,7 @@
#include "FuzzerMutate.h"
#include "FuzzerRandom.h"
#include "FuzzerTracePC.h"
+#include "FuzzerMerge.h"
#include <algorithm>
#include <atomic>
#include <chrono>
@@ -24,6 +25,7 @@
#include <mutex>
#include <string>
#include <thread>
+#include <fstream>
// This function should be present in the libFuzzer so that the client
// binary can test for its existence.
@@ -304,6 +306,11 @@ static std::string GetDedupTokenFromFile(const std::string &Path) {
return S.substr(Beg, End - Beg);
}
+static std::string TempPath(const char *Extension) {
+ return DirPlusFile(TmpDir(),
+ "libFuzzerTemp." + std::to_string(GetPid()) + Extension);
+}
+
int CleanseCrashInput(const Vector<std::string> &Args,
const FuzzingOptions &Options) {
if (Inputs->size() != 1 || !Flags.exact_artifact_path) {
@@ -319,10 +326,8 @@ int CleanseCrashInput(const Vector<std::string> &Args,
assert(Cmd.hasArgument(InputFilePath));
Cmd.removeArgument(InputFilePath);
- auto LogFilePath = DirPlusFile(
- TmpDir(), "libFuzzerTemp." + std::to_string(GetPid()) + ".txt");
- auto TmpFilePath = DirPlusFile(
- TmpDir(), "libFuzzerTemp." + std::to_string(GetPid()) + ".repro");
+ auto LogFilePath = TempPath(".txt");
+ auto TmpFilePath = TempPath(".repro");
Cmd.addArgument(TmpFilePath);
Cmd.setOutputFile(LogFilePath);
Cmd.combineOutAndErr();
@@ -382,8 +387,7 @@ int MinimizeCrashInput(const Vector<std::string> &Args,
BaseCmd.addFlag("max_total_time", "600");
}
- auto LogFilePath = DirPlusFile(
- TmpDir(), "libFuzzerTemp." + std::to_string(GetPid()) + ".txt");
+ auto LogFilePath = TempPath(".txt");
BaseCmd.setOutputFile(LogFilePath);
BaseCmd.combineOutAndErr();
@@ -467,6 +471,36 @@ int MinimizeCrashInputInternalStep(Fuzzer *F, InputCorpus *Corpus) {
return 0;
}
+// This is just a sceleton of an experimental -fork=1 feature.
+void FuzzWithFork(const FuzzingOptions &Options,
+ const Vector<std::string> &Args,
+ const Vector<std::string> &Corpora) {
+ auto CFPath = TempPath(".fork");
+ Printf("INFO: -fork=1: doing fuzzing in a separate process in order to "
+ "be more resistant to crashes, timeouts, and OOMs\n");
+ auto Files =
+ CrashResistantMerge(Args, Corpora, CFPath, nullptr, nullptr);
+ Printf("INFO: -fork=1: seed corpus analyzed, %zd seeds chosen, starting to "
+ "fuzz in separate processes\n", Files.size());
+
+ Command Cmd(Args);
+ Cmd.removeFlag("fork");
+ if (Files.size() >= 2)
+ Cmd.addFlag("seed_inputs",
+ Files.back() + "," + Files[Files.size() - 2]);
+ Cmd.addFlag("runs", "1000000");
+ Cmd.addFlag("max_total_time", "30");
+ for (size_t i = 0; i < 1000; i++) {
+ Printf("RUN %s\n", Cmd.toString().c_str());
+ int ExitCode = ExecuteCommand(Cmd);
+ // TODO: sniff the crash, ignore OOMs and timeouts.
+ if (ExitCode != 0) break;
+ }
+
+ RemoveFile(CFPath);
+ exit(0);
+}
+
int AnalyzeDictionary(Fuzzer *F, const Vector<Unit>& Dict,
UnitVector& Corpus) {
Printf("Started dictionary minimization (up to %d tests)\n",
@@ -694,11 +728,25 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
exit(0);
}
+ if (Flags.fork)
+ FuzzWithFork(Options, Args, *Inputs);
+
if (Flags.merge) {
- F->CrashResistantMerge(Args, *Inputs,
- Flags.load_coverage_summary,
- Flags.save_coverage_summary,
- Flags.merge_control_file);
+ if (Inputs->size() < 2) {
+ Printf("INFO: Merge requires two or more corpus dirs\n");
+ exit(0);
+ }
+ std::string CFPath =
+ Flags.merge_control_file ? Flags.merge_control_file : TempPath(".txt");
+ auto Files =
+ CrashResistantMerge(Args, *Inputs, CFPath, Flags.load_coverage_summary,
+ Flags.save_coverage_summary);
+ for (auto &Path : Files)
+ F->WriteToOutputCorpus(FileToVector(Path, Options.MaxLen));
+ // We are done, delete the control file if it was a temporary one.
+ if (!Flags.merge_control_file)
+ RemoveFile(CFPath);
+
exit(0);
}
OpenPOWER on IntegriCloud