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)];
};
}
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;
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;
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.
"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.")
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)
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
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;
}
}
- if (TPC.UpdateCounterMap(&C->TPCMap))
- Res = true;
-
- if (TPC.UpdateValueProfileMap(&C->VPMap))
- Res = true;
-
return Res;
}
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;
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 =
if (RunOne(CurrentUnitData, Size)) {
Corpus.AddToCorpus({CurrentUnitData, CurrentUnitData + Size});
ReportNewCoverage(&II, {CurrentUnitData, CurrentUnitData + Size});
+ CheckExitOnItem();
}
StopTraceRecording();
TryDetectingAMemoryLeak(CurrentUnitData, Size,
bool UseMemcmp = true;
bool UseMemmem = true;
bool UseValueProfile = false;
+ bool Shrink = false;
bool Reload = true;
bool ShuffleAtStartUp = true;
bool PreferSmall = true;
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;
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);
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) {
bool UpdateValueProfileMap(ValueBitMap *MaxValueProfileMap) {
return UseValueProfile && MaxValueProfileMap->MergeFrom(ValueProfileMap);
}
- void FinalizeTrace();
+ bool FinalizeTrace(size_t InputSize);
size_t GetNewPCIDs(uintptr_t **NewPCIDsPtr) {
*NewPCIDsPtr = NewPCIDs;
ValueBitMap CounterMap;
ValueBitMap ValueProfileMap;
+ uint32_t InputSizesPerFeature[kFeatureSetSize];
};
extern TracePC TPC;