summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Fuzzer/FuzzerDriver.cpp17
-rw-r--r--llvm/lib/Fuzzer/FuzzerFlags.def4
-rw-r--r--llvm/lib/Fuzzer/FuzzerInternal.h6
-rw-r--r--llvm/lib/Fuzzer/FuzzerLoop.cpp30
-rw-r--r--llvm/lib/Fuzzer/FuzzerTraceState.cpp23
5 files changed, 56 insertions, 24 deletions
diff --git a/llvm/lib/Fuzzer/FuzzerDriver.cpp b/llvm/lib/Fuzzer/FuzzerDriver.cpp
index a91d9deddb5..50a9cff2624 100644
--- a/llvm/lib/Fuzzer/FuzzerDriver.cpp
+++ b/llvm/lib/Fuzzer/FuzzerDriver.cpp
@@ -131,7 +131,7 @@ static bool ParseOneFlag(const char *Param) {
static bool PrintedWarning = false;
if (!PrintedWarning) {
PrintedWarning = true;
- Printf("WARNING: libFuzzer ignores flags that start with '--'\n");
+ Printf("INFO: libFuzzer ignores flags that start with '--'\n");
}
return true;
}
@@ -269,6 +269,7 @@ static int FuzzerDriver(const std::vector<std::string> &Args,
if (Flags.workers > 0 && Flags.jobs > 0)
return RunInMultipleProcesses(Args, Flags.workers, Flags.jobs);
+ const size_t kMaxSaneLen = 1 << 20;
Fuzzer::FuzzingOptions Options;
Options.Verbosity = Flags.verbosity;
Options.MaxLen = Flags.max_len;
@@ -315,7 +316,7 @@ static int FuzzerDriver(const std::vector<std::string> &Args,
Seed = (std::chrono::system_clock::now().time_since_epoch().count() << 10) +
getpid();
if (Flags.verbosity)
- Printf("Seed: %u\n", Seed);
+ Printf("INFO: Seed: %u\n", Seed);
Random Rand(Seed);
MutationDispatcher MD(Rand);
@@ -355,16 +356,24 @@ static int FuzzerDriver(const std::vector<std::string> &Args,
exit(0);
}
+
if (Flags.merge) {
+ if (Options.MaxLen == 0)
+ F.SetMaxLen(kMaxSaneLen);
F.Merge(*Inputs);
exit(0);
}
+ size_t TemporaryMaxLen = Options.MaxLen ? Options.MaxLen : kMaxSaneLen;
- F.RereadOutputCorpus();
+ F.RereadOutputCorpus(TemporaryMaxLen);
for (auto &inp : *Inputs)
if (inp != Options.OutputCorpus)
- F.ReadDir(inp, nullptr, Options.MaxLen);
+ F.ReadDir(inp, nullptr, TemporaryMaxLen);
+
+ if (Options.MaxLen == 0)
+ F.SetMaxLen(
+ std::min(std::max(64UL, 2 * F.MaxUnitSizeInCorpus()), kMaxSaneLen));
if (F.CorpusSize() == 0)
F.AddToCorpus(Unit()); // Can't fuzz empty corpus, so add an empty input.
diff --git a/llvm/lib/Fuzzer/FuzzerFlags.def b/llvm/lib/Fuzzer/FuzzerFlags.def
index eddd6044408..caf3d55f46a 100644
--- a/llvm/lib/Fuzzer/FuzzerFlags.def
+++ b/llvm/lib/Fuzzer/FuzzerFlags.def
@@ -14,7 +14,9 @@ FUZZER_FLAG_INT(verbosity, 1, "Verbosity level.")
FUZZER_FLAG_UNSIGNED(seed, 0, "Random seed. If 0, seed is generated.")
FUZZER_FLAG_INT(runs, -1,
"Number of individual test runs (-1 for infinite runs).")
-FUZZER_FLAG_INT(max_len, 64, "Maximum length of the test input.")
+FUZZER_FLAG_INT(max_len, 0, "Maximum length of the test input. "
+ "If 0, libFuzzer tries to guess a good value based on the corpus "
+ "and reports it. ")
FUZZER_FLAG_INT(cross_over, 1, "If 1, cross over inputs.")
FUZZER_FLAG_INT(mutate_depth, 5,
"Apply this number of consecutive mutations to each input.")
diff --git a/llvm/lib/Fuzzer/FuzzerInternal.h b/llvm/lib/Fuzzer/FuzzerInternal.h
index 5d66040b0a3..29a00507c0e 100644
--- a/llvm/lib/Fuzzer/FuzzerInternal.h
+++ b/llvm/lib/Fuzzer/FuzzerInternal.h
@@ -274,7 +274,7 @@ class Fuzzer {
public:
struct FuzzingOptions {
int Verbosity = 1;
- int MaxLen = 0;
+ size_t MaxLen = 0;
int UnitTimeoutSec = 300;
int TimeoutExitCode = 77;
int ErrorExitCode = 77;
@@ -316,11 +316,12 @@ public:
void InitializeTraceState();
void AssignTaintLabels(uint8_t *Data, size_t Size);
size_t CorpusSize() const { return Corpus.size(); }
+ size_t MaxUnitSizeInCorpus() const;
void ReadDir(const std::string &Path, long *Epoch, size_t MaxSize) {
Printf("Loading corpus: %s\n", Path.c_str());
ReadDirToVectorOfUnits(Path.c_str(), &Corpus, Epoch, MaxSize);
}
- void RereadOutputCorpus();
+ void RereadOutputCorpus(size_t MaxSize);
// Save the current corpus to OutputCorpus.
void SaveCorpus();
@@ -345,6 +346,7 @@ public:
void Merge(const std::vector<std::string> &Corpora);
MutationDispatcher &GetMD() { return MD; }
void PrintFinalStats();
+ void SetMaxLen(size_t MaxLen);
private:
void AlarmCallback();
diff --git a/llvm/lib/Fuzzer/FuzzerLoop.cpp b/llvm/lib/Fuzzer/FuzzerLoop.cpp
index 0438f418957..2bae76195e7 100644
--- a/llvm/lib/Fuzzer/FuzzerLoop.cpp
+++ b/llvm/lib/Fuzzer/FuzzerLoop.cpp
@@ -199,12 +199,27 @@ void Fuzzer::PrintFinalStats() {
Printf("stat::peak_rss_mb: %zd\n", GetPeakRSSMb());
}
-void Fuzzer::RereadOutputCorpus() {
+size_t Fuzzer::MaxUnitSizeInCorpus() const {
+ size_t Res = 0;
+ for (auto &X : Corpus)
+ Res = std::max(Res, X.size());
+ return Res;
+}
+
+void Fuzzer::SetMaxLen(size_t MaxLen) {
+ assert(Options.MaxLen == 0); // Can only reset MaxLen from 0 to non-0.
+ assert(MaxLen);
+ Options.MaxLen = MaxLen;
+ Printf("INFO: -max_len is not provided, using %zd\n", Options.MaxLen);
+}
+
+
+void Fuzzer::RereadOutputCorpus(size_t MaxSize) {
if (Options.OutputCorpus.empty())
return;
std::vector<Unit> AdditionalCorpus;
ReadDirToVectorOfUnits(Options.OutputCorpus.c_str(), &AdditionalCorpus,
- &EpochOfLastReadOfOutputCorpus, Options.MaxLen);
+ &EpochOfLastReadOfOutputCorpus, MaxSize);
if (Corpus.empty()) {
Corpus = AdditionalCorpus;
return;
@@ -214,8 +229,8 @@ void Fuzzer::RereadOutputCorpus() {
if (Options.Verbosity >= 2)
Printf("Reload: read %zd new units.\n", AdditionalCorpus.size());
for (auto &X : AdditionalCorpus) {
- if (X.size() > (size_t)Options.MaxLen)
- X.resize(Options.MaxLen);
+ if (X.size() > MaxSize)
+ X.resize(MaxSize);
if (UnitHashesAddedToCorpus.insert(Hash(X)).second) {
if (RunOne(X)) {
Corpus.push_back(X);
@@ -231,7 +246,7 @@ void Fuzzer::ShuffleAndMinimize() {
(Options.PreferSmallDuringInitialShuffle == -1 &&
MD.GetRand().RandBool()));
if (Options.Verbosity)
- Printf("PreferSmall: %d\n", PreferSmall);
+ Printf("INFO: PreferSmall: %d\n", PreferSmall);
PrintStats("READ ");
std::vector<Unit> NewCorpus;
if (Options.ShuffleAtStartUp) {
@@ -427,6 +442,7 @@ void Fuzzer::Merge(const std::vector<std::string> &Corpora) {
return;
}
auto InitialCorpusDir = Corpora[0];
+ assert(Options.MaxLen > 0);
ReadDir(InitialCorpusDir, nullptr, Options.MaxLen);
Printf("Merge: running the initial corpus '%s' of %d units\n",
InitialCorpusDir.c_str(), Corpus.size());
@@ -469,7 +485,7 @@ void Fuzzer::MutateAndTestOne() {
else
NewSize = MD.Mutate(MutateInPlaceHere.data(), Size, Options.MaxLen);
assert(NewSize > 0 && "Mutator returned empty unit");
- assert(NewSize <= (size_t)Options.MaxLen &&
+ assert(NewSize <= Options.MaxLen &&
"Mutator return overisized unit");
Size = NewSize;
if (i == 0)
@@ -546,7 +562,7 @@ void Fuzzer::Loop() {
SyncCorpus();
auto Now = system_clock::now();
if (duration_cast<seconds>(Now - LastCorpusReload).count()) {
- RereadOutputCorpus();
+ RereadOutputCorpus(Options.MaxLen);
LastCorpusReload = Now;
}
if (TotalNumberOfRuns >= Options.MaxNumberOfRuns)
diff --git a/llvm/lib/Fuzzer/FuzzerTraceState.cpp b/llvm/lib/Fuzzer/FuzzerTraceState.cpp
index dc4f18c353a..8123407e98c 100644
--- a/llvm/lib/Fuzzer/FuzzerTraceState.cpp
+++ b/llvm/lib/Fuzzer/FuzzerTraceState.cpp
@@ -253,6 +253,17 @@ class TraceState {
AddMutation(Pos, Size, reinterpret_cast<uint8_t*>(&Data));
}
+ void EnsureDfsanLabels(size_t Size) {
+ for (; LastDfsanLabel < Size; LastDfsanLabel++) {
+ dfsan_label L = dfsan_create_label("input", (void *)(LastDfsanLabel + 1));
+ // We assume that no one else has called dfsan_create_label before.
+ if (L != LastDfsanLabel + 1) {
+ Printf("DFSan labels are not starting from 1, exiting\n");
+ exit(1);
+ }
+ }
+ }
+
private:
bool IsTwoByteData(uint64_t Data) {
int64_t Signed = static_cast<int64_t>(Data);
@@ -279,6 +290,7 @@ class TraceState {
size_t NumMutations;
TraceBasedMutation Mutations[kMaxMutations];
LabelRange LabelRanges[1 << (sizeof(dfsan_label) * 8)];
+ size_t LastDfsanLabel = 0;
MutationDispatcher &MD;
const Fuzzer::FuzzingOptions &Options;
uint8_t **CurrentUnitData;
@@ -480,6 +492,7 @@ void Fuzzer::StopTraceRecording() {
void Fuzzer::AssignTaintLabels(uint8_t *Data, size_t Size) {
if (!Options.UseTraces && !Options.UseMemcmp) return;
if (!ReallyHaveDFSan()) return;
+ TS->EnsureDfsanLabels(Size);
for (size_t i = 0; i < Size; i++)
dfsan_set_label(i + 1, &Data[i], 1);
}
@@ -487,16 +500,6 @@ void Fuzzer::AssignTaintLabels(uint8_t *Data, size_t Size) {
void Fuzzer::InitializeTraceState() {
if (!Options.UseTraces && !Options.UseMemcmp) return;
TS = new TraceState(MD, Options, &CurrentUnitData, &CurrentUnitSize);
- if (ReallyHaveDFSan()) {
- for (size_t i = 0; i < static_cast<size_t>(Options.MaxLen); i++) {
- dfsan_label L = dfsan_create_label("input", (void *)(i + 1));
- // We assume that no one else has called dfsan_create_label before.
- if (L != i + 1) {
- Printf("DFSan labels are not starting from 1, exiting\n");
- exit(1);
- }
- }
- }
}
static size_t InternalStrnlen(const char *S, size_t MaxLen) {
OpenPOWER on IntegriCloud