summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Fuzzer/FuzzerCorpus.h3
-rw-r--r--llvm/lib/Fuzzer/FuzzerDriver.cpp3
-rw-r--r--llvm/lib/Fuzzer/FuzzerFlags.def4
-rw-r--r--llvm/lib/Fuzzer/FuzzerInternal.h1
-rw-r--r--llvm/lib/Fuzzer/FuzzerLoop.cpp36
-rw-r--r--llvm/lib/Fuzzer/FuzzerOptions.h2
-rw-r--r--llvm/lib/Fuzzer/FuzzerTracePC.cpp12
-rw-r--r--llvm/lib/Fuzzer/FuzzerTracePC.h3
8 files changed, 51 insertions, 13 deletions
diff --git a/llvm/lib/Fuzzer/FuzzerCorpus.h b/llvm/lib/Fuzzer/FuzzerCorpus.h
index 6438a6035f1..802f700f5c9 100644
--- a/llvm/lib/Fuzzer/FuzzerCorpus.h
+++ b/llvm/lib/Fuzzer/FuzzerCorpus.h
@@ -58,6 +58,7 @@ class InputCorpus {
ConstIter end() const { return Inputs.end(); }
bool HasUnit(const Unit &U) { return Hashes.count(Hash(U)); }
+ bool HasUnit(const std::string &H) { return Hashes.count(H); }
InputInfo &ChooseUnitToMutate(Random &Rand) {
return Inputs[ChooseUnitIdxToMutate(Rand)];
};
@@ -81,7 +82,7 @@ class InputCorpus {
}
void PrintFeatureSet() {
- Printf("Features [id: cnt idx sz] ");
+ Printf("Features [id: idx sz] ");
for (size_t i = 0; i < kFeatureSetSize; i++) {
auto &Fe = FeatureSet[i];
if (!Fe.Count) continue;
diff --git a/llvm/lib/Fuzzer/FuzzerDriver.cpp b/llvm/lib/Fuzzer/FuzzerDriver.cpp
index 484d8901525..8f7820d521d 100644
--- a/llvm/lib/Fuzzer/FuzzerDriver.cpp
+++ b/llvm/lib/Fuzzer/FuzzerDriver.cpp
@@ -398,6 +398,7 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
Options.UseMemcmp = Flags.use_memcmp;
Options.UseMemmem = Flags.use_memmem;
Options.UseValueProfile = Flags.use_value_profile;
+ Options.Shrink = Flags.shrink;
Options.ShuffleAtStartUp = Flags.shuffle;
Options.PreferSmall = Flags.prefer_small;
Options.Reload = Flags.reload;
@@ -429,6 +430,8 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
Options.PrintCoverage = Flags.print_coverage;
if (Flags.exit_on_src_pos)
Options.ExitOnSrcPos = Flags.exit_on_src_pos;
+ if (Flags.exit_on_item)
+ Options.ExitOnItem = Flags.exit_on_item;
unsigned Seed = Flags.seed;
// Initialize Seed.
diff --git a/llvm/lib/Fuzzer/FuzzerFlags.def b/llvm/lib/Fuzzer/FuzzerFlags.def
index 230ad579955..ea998bb9a9e 100644
--- a/llvm/lib/Fuzzer/FuzzerFlags.def
+++ b/llvm/lib/Fuzzer/FuzzerFlags.def
@@ -49,6 +49,7 @@ FUZZER_FLAG_INT(use_memmem, 1,
"Use hints from intercepting memmem, strstr, etc")
FUZZER_FLAG_INT(use_value_profile, 0,
"Experimental. Use value profile to guide fuzzing.")
+FUZZER_FLAG_INT(shrink, 0, "Experimental. Try to shrink corpus elements.")
FUZZER_FLAG_INT(jobs, 0, "Number of jobs to run. If jobs >= 1 we spawn"
" this number of jobs in separate worker processes"
" with stdout/stderr redirected to fuzz-JOB.log.")
@@ -95,6 +96,9 @@ FUZZER_FLAG_INT(rss_limit_mb, 2048, "If non-zero, the fuzzer will exit upon"
FUZZER_FLAG_STRING(exit_on_src_pos, "Exit if a newly found PC originates"
" from the given source location. Example: -exit_on_src_pos=foo.cc:123. "
"Used primarily for testing libFuzzer itself.")
+FUZZER_FLAG_STRING(exit_on_item, "Exit if an item with a given sha1 sum"
+ " was added to the corpus. "
+ "Used primarily for testing libFuzzer itself.")
FUZZER_DEPRECATED_FLAG(exit_on_first)
FUZZER_DEPRECATED_FLAG(save_minimized_corpus)
diff --git a/llvm/lib/Fuzzer/FuzzerInternal.h b/llvm/lib/Fuzzer/FuzzerInternal.h
index e85bd8aa17e..ba538b89826 100644
--- a/llvm/lib/Fuzzer/FuzzerInternal.h
+++ b/llvm/lib/Fuzzer/FuzzerInternal.h
@@ -117,6 +117,7 @@ private:
bool DuringInitialCorpusExecution);
void AddToCorpus(const Unit &U);
void CheckExitOnSrcPos();
+ void CheckExitOnItem();
// Trace-based fuzzing: we run a unit with some kind of tracing
// enabled and record potentially useful mutations. Then
diff --git a/llvm/lib/Fuzzer/FuzzerLoop.cpp b/llvm/lib/Fuzzer/FuzzerLoop.cpp
index ab4a25da8ee..f2e0f243a1a 100644
--- a/llvm/lib/Fuzzer/FuzzerLoop.cpp
+++ b/llvm/lib/Fuzzer/FuzzerLoop.cpp
@@ -79,8 +79,6 @@ void Fuzzer::PrepareCounters(Fuzzer::Coverage *C) {
bool Fuzzer::RecordMaxCoverage(Fuzzer::Coverage *C) {
bool Res = false;
- TPC.FinalizeTrace();
-
uint64_t NewBlockCoverage = EF->__sanitizer_get_total_unique_coverage();
if (NewBlockCoverage > C->BlockCoverage) {
Res = true;
@@ -107,12 +105,6 @@ bool Fuzzer::RecordMaxCoverage(Fuzzer::Coverage *C) {
}
}
- if (TPC.UpdateCounterMap(&C->TPCMap))
- Res = true;
-
- if (TPC.UpdateValueProfileMap(&C->VPMap))
- Res = true;
-
return Res;
}
@@ -353,6 +345,16 @@ void Fuzzer::SetMaxMutationLen(size_t MaxMutationLen) {
this->MaxMutationLen = MaxMutationLen;
}
+void Fuzzer::CheckExitOnItem() {
+ if (!Options.ExitOnItem.empty()) {
+ if (Corpus.HasUnit(Options.ExitOnItem)) {
+ Printf("INFO: found item with checksum '%s', exiting.\n",
+ Options.ExitOnItem.c_str());
+ _Exit(0);
+ }
+ }
+}
+
void Fuzzer::CheckExitOnSrcPos() {
if (!Options.ExitOnSrcPos.empty()) {
uintptr_t *PCIDs;
@@ -422,7 +424,22 @@ bool Fuzzer::RunOne(const uint8_t *Data, size_t Size) {
TotalNumberOfRuns++;
ExecuteCallback(Data, Size);
- bool Res = RecordMaxCoverage(&MaxCoverage);
+ bool Res = false;
+
+ if (TPC.FinalizeTrace(Size))
+ if (Options.Shrink)
+ Res = true;
+
+ if (!Res) {
+ if (TPC.UpdateCounterMap(&MaxCoverage.TPCMap))
+ Res = true;
+
+ if (TPC.UpdateValueProfileMap(&MaxCoverage.VPMap))
+ Res = true;
+ }
+
+ if (RecordMaxCoverage(&MaxCoverage))
+ Res = true;
CheckExitOnSrcPos();
auto TimeOfUnit =
@@ -667,6 +684,7 @@ void Fuzzer::MutateAndTestOne() {
if (RunOne(CurrentUnitData, Size)) {
Corpus.AddToCorpus({CurrentUnitData, CurrentUnitData + Size});
ReportNewCoverage(&II, {CurrentUnitData, CurrentUnitData + Size});
+ CheckExitOnItem();
}
StopTraceRecording();
TryDetectingAMemoryLeak(CurrentUnitData, Size,
diff --git a/llvm/lib/Fuzzer/FuzzerOptions.h b/llvm/lib/Fuzzer/FuzzerOptions.h
index 09b2cdec945..04a44d8c9ff 100644
--- a/llvm/lib/Fuzzer/FuzzerOptions.h
+++ b/llvm/lib/Fuzzer/FuzzerOptions.h
@@ -31,6 +31,7 @@ struct FuzzingOptions {
bool UseMemcmp = true;
bool UseMemmem = true;
bool UseValueProfile = false;
+ bool Shrink = false;
bool Reload = true;
bool ShuffleAtStartUp = true;
bool PreferSmall = true;
@@ -41,6 +42,7 @@ struct FuzzingOptions {
std::string ArtifactPrefix = "./";
std::string ExactArtifactPath;
std::string ExitOnSrcPos;
+ std::string ExitOnItem;
bool SaveArtifacts = true;
bool PrintNEW = true; // Print a status line when new units are found;
bool OutputCSV = false;
diff --git a/llvm/lib/Fuzzer/FuzzerTracePC.cpp b/llvm/lib/Fuzzer/FuzzerTracePC.cpp
index f97da96589d..f02b71dc9de 100644
--- a/llvm/lib/Fuzzer/FuzzerTracePC.cpp
+++ b/llvm/lib/Fuzzer/FuzzerTracePC.cpp
@@ -68,7 +68,8 @@ void TracePC::ResetGuards() {
assert(N == NumGuards);
}
-void TracePC::FinalizeTrace() {
+bool TracePC::FinalizeTrace(size_t InputSize) {
+ bool Res = false;
if (TotalPCCoverage) {
const size_t Step = 8;
assert(reinterpret_cast<uintptr_t>(Counters) % Step == 0);
@@ -89,10 +90,17 @@ void TracePC::FinalizeTrace() {
else if (Counter >= 4) Bit = 3;
else if (Counter >= 3) Bit = 2;
else if (Counter >= 2) Bit = 1;
- CounterMap.AddValue(i * 8 + Bit);
+ size_t Feature = i * 8 + Bit;
+ CounterMap.AddValue(Feature);
+ uint32_t *SizePtr = &InputSizesPerFeature[Feature];
+ if (!*SizePtr || *SizePtr > InputSize) {
+ *SizePtr = InputSize;
+ Res = true;
+ }
}
}
}
+ return Res;
}
void TracePC::HandleCallerCallee(uintptr_t Caller, uintptr_t Callee) {
diff --git a/llvm/lib/Fuzzer/FuzzerTracePC.h b/llvm/lib/Fuzzer/FuzzerTracePC.h
index 1eb4a303ef0..79ec7fb70c5 100644
--- a/llvm/lib/Fuzzer/FuzzerTracePC.h
+++ b/llvm/lib/Fuzzer/FuzzerTracePC.h
@@ -35,7 +35,7 @@ class TracePC {
bool UpdateValueProfileMap(ValueBitMap *MaxValueProfileMap) {
return UseValueProfile && MaxValueProfileMap->MergeFrom(ValueProfileMap);
}
- void FinalizeTrace();
+ bool FinalizeTrace(size_t InputSize);
size_t GetNewPCIDs(uintptr_t **NewPCIDsPtr) {
*NewPCIDsPtr = NewPCIDs;
@@ -90,6 +90,7 @@ private:
ValueBitMap CounterMap;
ValueBitMap ValueProfileMap;
+ uint32_t InputSizesPerFeature[kFeatureSetSize];
};
extern TracePC TPC;
OpenPOWER on IntegriCloud