summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Fuzzer/FuzzerFlags.def2
-rw-r--r--llvm/lib/Fuzzer/FuzzerIO.cpp8
-rw-r--r--llvm/lib/Fuzzer/FuzzerInternal.h3
-rw-r--r--llvm/lib/Fuzzer/FuzzerLoop.cpp4
-rw-r--r--llvm/lib/Fuzzer/FuzzerMain.cpp23
-rw-r--r--llvm/lib/Fuzzer/FuzzerMutate.cpp24
6 files changed, 46 insertions, 18 deletions
diff --git a/llvm/lib/Fuzzer/FuzzerFlags.def b/llvm/lib/Fuzzer/FuzzerFlags.def
index cbaa81e0384..0895fa7bac0 100644
--- a/llvm/lib/Fuzzer/FuzzerFlags.def
+++ b/llvm/lib/Fuzzer/FuzzerFlags.def
@@ -16,7 +16,7 @@ FUZZER_FLAG(int, iterations, -1,
"Number of iterations of the fuzzer (-1 for infinite runs).")
FUZZER_FLAG(int, max_len, 64, "Maximal length of the test input.")
FUZZER_FLAG(int, cross_over, 1, "If 1, cross over inputs.")
-FUZZER_FLAG(int, mutate_depth, 10,
+FUZZER_FLAG(int, mutate_depth, 5,
"Apply this number of consecutive mutations to each input.")
FUZZER_FLAG(int, exit_on_first, 0,
"If 1, exit after the first new interesting input is found.")
diff --git a/llvm/lib/Fuzzer/FuzzerIO.cpp b/llvm/lib/Fuzzer/FuzzerIO.cpp
index 4e0ac819218..224808c5e16 100644
--- a/llvm/lib/Fuzzer/FuzzerIO.cpp
+++ b/llvm/lib/Fuzzer/FuzzerIO.cpp
@@ -9,6 +9,8 @@
// IO functions.
//===----------------------------------------------------------------------===//
#include "FuzzerInternal.h"
+#include <iostream>
+#include <iterator>
#include <fstream>
#include <dirent.h>
namespace fuzzer {
@@ -31,6 +33,12 @@ Unit FileToVector(const std::string &Path) {
std::istreambuf_iterator<char>());
}
+void CopyFileToErr(const std::string &Path) {
+ std::ifstream T(Path);
+ std::copy(std::istreambuf_iterator<char>(T), std::istreambuf_iterator<char>(),
+ std::ostream_iterator<char>(std::cerr, ""));
+}
+
void WriteToFile(const Unit &U, const std::string &Path) {
std::ofstream OF(Path);
OF.write((const char*)U.data(), U.size());
diff --git a/llvm/lib/Fuzzer/FuzzerInternal.h b/llvm/lib/Fuzzer/FuzzerInternal.h
index 45379711db4..fbf26309f23 100644
--- a/llvm/lib/Fuzzer/FuzzerInternal.h
+++ b/llvm/lib/Fuzzer/FuzzerInternal.h
@@ -23,6 +23,7 @@ using namespace std::chrono;
Unit ReadFile(const char *Path);
void ReadDirToVectorOfUnits(const char *Path, std::vector<Unit> *V);
void WriteToFile(const Unit &U, const std::string &Path);
+void CopyFileToErr(const std::string &Path);
// Returns "Dir/FileName" or equivalent for the current OS.
std::string DirPlusFile(const std::string &DirPath,
const std::string &FileName);
@@ -42,7 +43,7 @@ class Fuzzer {
int Verbosity = 1;
int MaxLen = 0;
bool DoCrossOver = true;
- bool MutateDepth = 10;
+ int MutateDepth = 5;
bool ExitOnFirst = false;
bool UseFullCoverageSet = false;
std::string OutputCorpus;
diff --git a/llvm/lib/Fuzzer/FuzzerLoop.cpp b/llvm/lib/Fuzzer/FuzzerLoop.cpp
index 88ae6ca7320..04285895181 100644
--- a/llvm/lib/Fuzzer/FuzzerLoop.cpp
+++ b/llvm/lib/Fuzzer/FuzzerLoop.cpp
@@ -146,9 +146,8 @@ void Fuzzer::SaveCorpus() {
size_t Fuzzer::MutateAndTestOne(Unit *U) {
size_t NewUnits = 0;
- for (size_t i = 0; i < Options.MutateDepth; i++) {
+ for (int i = 0; i < Options.MutateDepth; i++) {
Mutate(U, Options.MaxLen);
- if (U->empty()) continue;
size_t NewCoverage = RunOne(*U);
if (NewCoverage) {
Corpus.push_back(*U);
@@ -158,6 +157,7 @@ size_t Fuzzer::MutateAndTestOne(Unit *U) {
<< "\tNEW: " << NewCoverage
<< " L: " << U->size()
<< " S: " << Corpus.size()
+ << " I: " << i
<< "\t";
if (U->size() < 30) {
PrintASCII(*U);
diff --git a/llvm/lib/Fuzzer/FuzzerMain.cpp b/llvm/lib/Fuzzer/FuzzerMain.cpp
index 3370a80339f..0a852ed4257 100644
--- a/llvm/lib/Fuzzer/FuzzerMain.cpp
+++ b/llvm/lib/Fuzzer/FuzzerMain.cpp
@@ -17,6 +17,7 @@
#include <iostream>
#include <thread>
#include <atomic>
+#include <mutex>
// ASAN options:
// * don't dump the coverage to disk.
@@ -105,20 +106,30 @@ static void ParseFlags(int argc, char **argv) {
}
static void WorkerThread(const std::string &Cmd, std::atomic<int> *Counter,
- int NumJobs) {
+ int NumJobs, std::atomic<bool> *HasErrors) {
+ static std::mutex CerrMutex;
while (true) {
int C = (*Counter)++;
- if (C >= NumJobs) return;
- std::string ToRun = Cmd + " > fuzz-" + std::to_string(C) + ".log 2>&1\n";
+ if (C >= NumJobs) break;
+ std::string Log = "fuzz-" + std::to_string(C) + ".log";
+ std::string ToRun = Cmd + " > " + Log + " 2>&1\n";
if (Flags.verbosity)
std::cerr << ToRun;
- system(ToRun.c_str());
+ int ExitCode = system(ToRun.c_str());
+ if (ExitCode != 0)
+ *HasErrors = true;
+ std::lock_guard<std::mutex> Lock(CerrMutex);
+ std::cerr << "================== Job " << C
+ << " exited with exit code " << ExitCode
+ << " =================\n";
+ fuzzer::CopyFileToErr(Log);
}
}
static int RunInMultipleProcesses(int argc, char **argv, int NumWorkers,
int NumJobs) {
std::atomic<int> Counter(0);
+ std::atomic<bool> HasErrors(false);
std::string Cmd;
for (int i = 0; i < argc; i++) {
if (FlagValue(argv[i], "jobs") || FlagValue(argv[i], "workers")) continue;
@@ -127,10 +138,10 @@ static int RunInMultipleProcesses(int argc, char **argv, int NumWorkers,
}
std::vector<std::thread> V;
for (int i = 0; i < NumWorkers; i++)
- V.push_back(std::thread(WorkerThread, Cmd, &Counter, NumJobs));
+ V.push_back(std::thread(WorkerThread, Cmd, &Counter, NumJobs, &HasErrors));
for (auto &T : V)
T.join();
- return 0;
+ return HasErrors ? 1 : 0;
}
int main(int argc, char **argv) {
diff --git a/llvm/lib/Fuzzer/FuzzerMutate.cpp b/llvm/lib/Fuzzer/FuzzerMutate.cpp
index 2db8fac9bc6..60d5623ada6 100644
--- a/llvm/lib/Fuzzer/FuzzerMutate.cpp
+++ b/llvm/lib/Fuzzer/FuzzerMutate.cpp
@@ -31,18 +31,25 @@ static char RandCh() {
return Special[rand() % (sizeof(Special) - 1)];
}
+// Mutate U in place.
void Mutate(Unit *U, size_t MaxLen) {
assert(MaxLen > 0);
assert(U->size() <= MaxLen);
+ if (U->empty()) {
+ for (size_t i = 0; i < MaxLen; i++)
+ U->push_back(RandCh());
+ return;
+ }
+ assert(!U->empty());
switch (rand() % 3) {
case 0:
- if (U->size())
+ if (U->size() > 1) {
U->erase(U->begin() + rand() % U->size());
- break;
+ break;
+ }
+ // Fallthrough
case 1:
- if (U->empty()) {
- U->push_back(RandCh());
- } else if (U->size() < MaxLen) {
+ if (U->size() < MaxLen) {
U->insert(U->begin() + rand() % U->size(), RandCh());
} else { // At MaxLen.
uint8_t Ch = RandCh();
@@ -51,12 +58,13 @@ void Mutate(Unit *U, size_t MaxLen) {
}
break;
default:
- if (!U->empty()) {
- size_t idx = rand() % U->size();
- (*U)[idx] = FlipRandomBit((*U)[idx]);
+ {
+ size_t Idx = rand() % U->size();
+ (*U)[Idx] = FlipRandomBit((*U)[Idx]);
}
break;
}
+ assert(!U->empty());
}
} // namespace fuzzer
OpenPOWER on IntegriCloud