void PrintASCII(const Unit &U, const char *PrintAfter = "");
void PrintPC(const char *SymbolizedFMT, const char *FallbackFMT, uintptr_t PC);
+std::string DescribePC(const char *SymbolizedFMT, uintptr_t PC);
std::string Hash(const Unit &U);
void SetTimer(int Seconds);
void SetSigSegvHandler();
Options.PrintCorpusStats = Flags.print_corpus_stats;
Options.PrintCoverage = Flags.print_coverage;
Options.PruneCorpus = Flags.prune_corpus;
+ if (Flags.exit_on_src_pos)
+ Options.ExitOnSrcPos = Flags.exit_on_src_pos;
unsigned Seed = Flags.seed;
// Initialize Seed.
"reaching this limit of RSS memory usage.")
FUZZER_FLAG_INT(prune_corpus, 1, "Prune corpus items without new coverage when "
"loading corpus.")
+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_DEPRECATED_FLAG(exit_on_first)
FUZZER_DEPRECATED_FLAG(save_minimized_corpus)
void TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size,
bool DuringInitialCorpusExecution);
void AddToCorpusAndMaybeRerun(const Unit &U);
+ void CheckExitOnSrcPos();
bool UpdateMaxCoverage();
this->MaxMutationLen = MaxMutationLen;
}
+void Fuzzer::CheckExitOnSrcPos() {
+ if (!Options.ExitOnSrcPos.empty()) {
+ uintptr_t *PCIDs;
+ if (size_t NumNewPCIDs = TPC.GetNewPCIDs(&PCIDs)) {
+ for (size_t i = 0; i < NumNewPCIDs; i++) {
+ std::string Descr = DescribePC("%L", TPC.GetPCbyPCID(PCIDs[i]));
+ if (Descr.find(Options.ExitOnSrcPos) != std::string::npos) {
+ Printf("INFO: found line matching '%s', exiting.\n",
+ Options.ExitOnSrcPos.c_str());
+ _Exit(0);
+ }
+ }
+ }
+ }
+}
+
void Fuzzer::AddToCorpusAndMaybeRerun(const Unit &U) {
+ CheckExitOnSrcPos();
Corpus.AddToCorpus(U);
if (TPC.GetTotalPCCoverage()) {
TPC.ResetMaps();
std::string OutputCorpus;
std::string ArtifactPrefix = "./";
std::string ExactArtifactPath;
+ std::string ExitOnSrcPos;
bool SaveArtifacts = true;
bool PrintNEW = true; // Print a status line when new units are found;
bool OutputCSV = false;
void TracePC::FinalizeTrace() {
if (TotalPCCoverage) {
- for (size_t Idx = 1, N = Min(kNumCounters, NumGuards); Idx < N;
+ for (size_t Idx = 1, N = Min(kNumCounters, NumGuards + 1); Idx < N;
Idx++) {
uint8_t Counter = Counters[Idx];
if (!Counter) continue;
void TracePC::PrintCoverage() {
Printf("COVERAGE:\n");
- for (size_t i = 0; i < Min(NumGuards, kNumPCs); i++) {
+ for (size_t i = 0; i < Min(NumGuards + 1, kNumPCs); i++) {
if (PCs[i])
PrintPC("COVERED: %p %F %L\n", "COVERED: %p\n", PCs[i]);
}
return Min(kMaxNewPCIDs, NumNewPCIDs);
}
- void ResetNewPCIDs() { NumNewPCIDs = 0; }
uintptr_t GetPCbyPCID(uintptr_t PCID) { return PCs[PCID]; }
void ResetMaps() {
bool UseValueProfile = false;
size_t TotalPCCoverage = 0;
- static const size_t kMaxNewPCIDs = 64;
+ static const size_t kMaxNewPCIDs = 1024;
uintptr_t NewPCIDs[kMaxNewPCIDs];
size_t NumNewPCIDs = 0;
void AddNewPCID(uintptr_t PCID) {
return 0;
}
+std::string DescribePC(const char *SymbolizedFMT, uintptr_t PC) {
+ if (!EF->__sanitizer_symbolize_pc) return "<can not symbolize>";
+ char PcDescr[1024];
+ EF->__sanitizer_symbolize_pc(reinterpret_cast<void*>(PC),
+ SymbolizedFMT, PcDescr, sizeof(PcDescr));
+ PcDescr[sizeof(PcDescr) - 1] = 0; // Just in case.
+ return PcDescr;
+}
+
void PrintPC(const char *SymbolizedFMT, const char *FallbackFMT, uintptr_t PC) {
- if (EF->__sanitizer_symbolize_pc) {
- char PcDescr[1024];
- EF->__sanitizer_symbolize_pc(reinterpret_cast<void*>(PC),
- SymbolizedFMT, PcDescr, sizeof(PcDescr));
- PcDescr[sizeof(PcDescr) - 1] = 0; // Just in case.
- Printf("%s", PcDescr);
- } else {
+ if (EF->__sanitizer_symbolize_pc)
+ Printf("%s", DescribePC(SymbolizedFMT, PC).c_str());
+ else
Printf(FallbackFMT, PC);
- }
}
} // namespace fuzzer
--- /dev/null
+#!/bin/bash
+set -x
+SCRIPT_DIR=$(dirname $0)
+EXECUTABLE_NAME_BASE=$(basename $SCRIPT_DIR)
+CORPUS=CORPUS-$EXECUTABLE_NAME_BASE
+JOBS=8
+rm -rf $CORPUS
+mkdir $CORPUS
+[ -e $EXECUTABLE_NAME_BASE ] && ./$EXECUTABLE_NAME_BASE -exit_on_src_pos=re2/dfa.cc:474 -exit_on_src_pos=re2/dfa.cc:474 -runs=1000000 -jobs=$JOBS $CORPUS
+grep "INFO: found line matching 're2/dfa.cc:474', exiting." fuzz-0.log
int Z = Ids[(unsigned char)'Z'];
if (F >= 0 && U > F && Z > U) {
Sink++;
- // printf("IDS: %d %d %d\n", F, U, Z);
+ // fprintf(stderr, "IDS: %d %d %d\n", F, U, Z);
}
return 0;
}
DSO: INFO: Loaded 3 modules
DSO: BINGO
+RUN: LLVMFuzzer-SimpleTest-TracePC -exit_on_src_pos=SimpleTest.cpp:17 2>&1 | FileCheck %s --check-prefix=EXIT_ON_SRC_POS
+RUN: LLVMFuzzer-MinimizeCorpusTest-TracePC -exit_on_src_pos=MinimizeCorpusTest.cpp:23 2>&1 | FileCheck %s --check-prefix=EXIT_ON_SRC_POS
+EXIT_ON_SRC_POS: INFO: found line matching '{{.*}}', exiting.
+