aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKostya Serebryany <kcc@google.com>2017-07-22 00:10:29 +0000
committerKostya Serebryany <kcc@google.com>2017-07-22 00:10:29 +0000
commit5ae0dfe6b2220f98ae701c435b72a593fff23683 (patch)
tree375937a908b2d89a1d4e76a35934785d36929bfc
parente59b7e46c1b5e38b0e16b80f1a12c234d78f9a35 (diff)
[libFuzzer] reimplement experimental_len_control=1: bump the temporary max_len every time we failed to find new coverage during the last 1000 runs and 1 second. Also fix FileToVector to not load unfinished files
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@308811 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Fuzzer/FuzzerDriver.cpp2
-rw-r--r--lib/Fuzzer/FuzzerIO.cpp4
-rw-r--r--lib/Fuzzer/FuzzerInternal.h5
-rw-r--r--lib/Fuzzer/FuzzerLoop.cpp45
4 files changed, 34 insertions, 22 deletions
diff --git a/lib/Fuzzer/FuzzerDriver.cpp b/lib/Fuzzer/FuzzerDriver.cpp
index 36d9422bc28..17891d29c5d 100644
--- a/lib/Fuzzer/FuzzerDriver.cpp
+++ b/lib/Fuzzer/FuzzerDriver.cpp
@@ -564,8 +564,6 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
Options.Verbosity = Flags.verbosity;
Options.MaxLen = Flags.max_len;
Options.ExperimentalLenControl = Flags.experimental_len_control;
- if (Flags.experimental_len_control && Flags.max_len == kMinDefaultLen)
- Options.MaxLen = 1 << 20;
Options.UnitTimeoutSec = Flags.timeout;
Options.ErrorExitCode = Flags.error_exitcode;
Options.TimeoutExitCode = Flags.timeout_exitcode;
diff --git a/lib/Fuzzer/FuzzerIO.cpp b/lib/Fuzzer/FuzzerIO.cpp
index e3f609ed8a8..1a06d4420f9 100644
--- a/lib/Fuzzer/FuzzerIO.cpp
+++ b/lib/Fuzzer/FuzzerIO.cpp
@@ -38,7 +38,9 @@ Unit FileToVector(const std::string &Path, size_t MaxSize, bool ExitOnError) {
}
T.seekg(0, T.end);
- size_t FileLen = T.tellg();
+ auto EndPos = T.tellg();
+ if (EndPos < 0) return {};
+ size_t FileLen = EndPos;
if (MaxSize)
FileLen = std::min(FileLen, MaxSize);
diff --git a/lib/Fuzzer/FuzzerInternal.h b/lib/Fuzzer/FuzzerInternal.h
index 8602818a420..1d68c01908f 100644
--- a/lib/Fuzzer/FuzzerInternal.h
+++ b/lib/Fuzzer/FuzzerInternal.h
@@ -118,6 +118,10 @@ private:
size_t TotalNumberOfRuns = 0;
size_t NumberOfNewUnitsAdded = 0;
+ size_t LastCorpusUpdateRun = 0;
+ system_clock::time_point LastCorpusUpdateTime = system_clock::now();
+
+
bool HasMoreMallocsThanFrees = false;
size_t NumberOfLeakDetectionAttempts = 0;
@@ -133,6 +137,7 @@ private:
size_t MaxInputLen = 0;
size_t MaxMutationLen = 0;
+ size_t TmpMaxMutationLen = 0;
std::vector<uint32_t> UniqFeatureSetTmp;
diff --git a/lib/Fuzzer/FuzzerLoop.cpp b/lib/Fuzzer/FuzzerLoop.cpp
index b9e70b6dadd..682e4b7b05d 100644
--- a/lib/Fuzzer/FuzzerLoop.cpp
+++ b/lib/Fuzzer/FuzzerLoop.cpp
@@ -129,6 +129,7 @@ Fuzzer::Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD,
if (!Options.OutputCorpus.empty() && Options.ReloadIntervalSec)
EpochOfLastReadOfOutputCorpus = GetEpoch(Options.OutputCorpus);
MaxInputLen = MaxMutationLen = Options.MaxLen;
+ TmpMaxMutationLen = Max(size_t(4), Corpus.MaxInputSize());
AllocateCurrentUnitData();
CurrentUnitSize = 0;
memset(BaseSha1, 0, sizeof(BaseSha1));
@@ -511,7 +512,7 @@ void Fuzzer::WriteToOutputCorpus(const Unit &U) {
std::string Path = DirPlusFile(Options.OutputCorpus, Hash(U));
WriteToFile(U, Path);
if (Options.Verbosity >= 2)
- Printf("Written to %s\n", Path.c_str());
+ Printf("Written %zd bytes to %s\n", U.size(), Path.c_str());
}
void Fuzzer::WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix) {
@@ -532,7 +533,7 @@ void Fuzzer::PrintStatusForNewUnit(const Unit &U, const char *Text) {
return;
PrintStats(Text, "");
if (Options.Verbosity) {
- Printf(" L: %zd ", U.size());
+ Printf(" L: %zd/%zd ", U.size(), Corpus.MaxInputSize());
MD.PrintMutationSequence();
Printf("\n");
}
@@ -547,6 +548,8 @@ void Fuzzer::ReportNewCoverage(InputInfo *II, const Unit &U) {
NumberOfNewUnitsAdded++;
TPC.PrintNewPCs();
CheckExitOnSrcPosOrItem(); // Check only after the unit is saved to corpus.
+ LastCorpusUpdateRun = TotalNumberOfRuns;
+ LastCorpusUpdateTime = system_clock::now();
}
// Tries detecting a memory leak on the particular input that we have just
@@ -588,19 +591,6 @@ void Fuzzer::TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size,
}
}
-static size_t ComputeMutationLen(size_t MaxInputSize, size_t MaxMutationLen,
- Random &Rand) {
- assert(MaxInputSize <= MaxMutationLen);
- if (MaxInputSize == MaxMutationLen) return MaxMutationLen;
- size_t Result = MaxInputSize;
- size_t R = Rand.Rand();
- if ((R % (1U << 7)) == 0)
- Result++;
- if ((R % (1U << 15)) == 0)
- Result += 10 + Result / 2;
- return Min(Result, MaxMutationLen);
-}
-
void Fuzzer::MutateAndTestOne() {
MD.StartMutationSequence();
@@ -615,10 +605,8 @@ void Fuzzer::MutateAndTestOne() {
assert(MaxMutationLen > 0);
size_t CurrentMaxMutationLen =
- Options.ExperimentalLenControl
- ? ComputeMutationLen(Corpus.MaxInputSize(), MaxMutationLen,
- MD.GetRand())
- : MaxMutationLen;
+ Min(MaxMutationLen, Max(U.size(), TmpMaxMutationLen));
+ assert(CurrentMaxMutationLen > 0);
for (int i = 0; i < Options.MutateDepth; i++) {
if (TotalNumberOfRuns >= Options.MaxNumberOfRuns)
@@ -652,6 +640,25 @@ void Fuzzer::Loop() {
if (TotalNumberOfRuns >= Options.MaxNumberOfRuns)
break;
if (TimedOut()) break;
+
+ // Update TmpMaxMutationLen
+ if (Options.ExperimentalLenControl) {
+ if (TmpMaxMutationLen < MaxMutationLen &&
+ (TotalNumberOfRuns - LastCorpusUpdateRun > 1000 &&
+ duration_cast<seconds>(Now - LastCorpusUpdateTime).count() >= 1)) {
+ LastCorpusUpdateRun = TotalNumberOfRuns;
+ LastCorpusUpdateTime = Now;
+ TmpMaxMutationLen =
+ Min(MaxMutationLen,
+ TmpMaxMutationLen + Max(size_t(4), TmpMaxMutationLen / 8));
+ if (TmpMaxMutationLen <= MaxMutationLen)
+ Printf("#%zd\tTEMP_MAX_LEN: %zd\n", TotalNumberOfRuns,
+ TmpMaxMutationLen);
+ }
+ } else {
+ TmpMaxMutationLen = MaxMutationLen;
+ }
+
// Perform several mutations and runs.
MutateAndTestOne();
}