From 65f502816cb0add5e4b40388e933c1061368df3a Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Tue, 27 Sep 2016 00:10:20 +0000 Subject: [PATCH] [libFuzzer] add -exit_on_src_pos to test libFuzzer itself, add a test script for RE2 that uses this flag git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@282458 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Fuzzer/FuzzerDefs.h | 1 + lib/Fuzzer/FuzzerDriver.cpp | 2 ++ lib/Fuzzer/FuzzerFlags.def | 3 +++ lib/Fuzzer/FuzzerInternal.h | 1 + lib/Fuzzer/FuzzerLoop.cpp | 17 +++++++++++++++++ lib/Fuzzer/FuzzerOptions.h | 1 + lib/Fuzzer/FuzzerTracePC.cpp | 4 ++-- lib/Fuzzer/FuzzerTracePC.h | 3 +-- lib/Fuzzer/FuzzerUtil.cpp | 20 ++++++++++++-------- lib/Fuzzer/fuzzer-test-suite/re2-2014-12-09/test.sh | 10 ++++++++++ lib/Fuzzer/test/MinimizeCorpusTest.cpp | 2 +- lib/Fuzzer/test/fuzzer.test | 4 ++++ 12 files changed, 55 insertions(+), 13 deletions(-) create mode 100755 lib/Fuzzer/fuzzer-test-suite/re2-2014-12-09/test.sh diff --git a/lib/Fuzzer/FuzzerDefs.h b/lib/Fuzzer/FuzzerDefs.h index 4c60572ab4c..3fc62da7ae9 100644 --- a/lib/Fuzzer/FuzzerDefs.h +++ b/lib/Fuzzer/FuzzerDefs.h @@ -79,6 +79,7 @@ void PrintASCII(const uint8_t *Data, size_t Size, const char *PrintAfter = ""); 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(); diff --git a/lib/Fuzzer/FuzzerDriver.cpp b/lib/Fuzzer/FuzzerDriver.cpp index b826b9f0729..f2452dc95f2 100644 --- a/lib/Fuzzer/FuzzerDriver.cpp +++ b/lib/Fuzzer/FuzzerDriver.cpp @@ -428,6 +428,8 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) { 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. diff --git a/lib/Fuzzer/FuzzerFlags.def b/lib/Fuzzer/FuzzerFlags.def index ff6f1c08acc..1d62e429b30 100644 --- a/lib/Fuzzer/FuzzerFlags.def +++ b/lib/Fuzzer/FuzzerFlags.def @@ -94,6 +94,9 @@ FUZZER_FLAG_INT(rss_limit_mb, 2048, "If non-zero, the fuzzer will exit upon" "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) diff --git a/lib/Fuzzer/FuzzerInternal.h b/lib/Fuzzer/FuzzerInternal.h index 1188b052a1b..49f6a6a7cf3 100644 --- a/lib/Fuzzer/FuzzerInternal.h +++ b/lib/Fuzzer/FuzzerInternal.h @@ -116,6 +116,7 @@ private: void TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size, bool DuringInitialCorpusExecution); void AddToCorpusAndMaybeRerun(const Unit &U); + void CheckExitOnSrcPos(); bool UpdateMaxCoverage(); diff --git a/lib/Fuzzer/FuzzerLoop.cpp b/lib/Fuzzer/FuzzerLoop.cpp index 4a9b5694956..f7d4e4ef362 100644 --- a/lib/Fuzzer/FuzzerLoop.cpp +++ b/lib/Fuzzer/FuzzerLoop.cpp @@ -374,7 +374,24 @@ void Fuzzer::SetMaxMutationLen(size_t MaxMutationLen) { 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(); diff --git a/lib/Fuzzer/FuzzerOptions.h b/lib/Fuzzer/FuzzerOptions.h index cb3679d6a85..56c35aa5253 100644 --- a/lib/Fuzzer/FuzzerOptions.h +++ b/lib/Fuzzer/FuzzerOptions.h @@ -40,6 +40,7 @@ struct FuzzingOptions { 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; diff --git a/lib/Fuzzer/FuzzerTracePC.cpp b/lib/Fuzzer/FuzzerTracePC.cpp index 393470770c9..d533eac1501 100644 --- a/lib/Fuzzer/FuzzerTracePC.cpp +++ b/lib/Fuzzer/FuzzerTracePC.cpp @@ -70,7 +70,7 @@ void TracePC::ResetGuards() { 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; @@ -96,7 +96,7 @@ void TracePC::HandleCallerCallee(uintptr_t Caller, uintptr_t Callee) { 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]); } diff --git a/lib/Fuzzer/FuzzerTracePC.h b/lib/Fuzzer/FuzzerTracePC.h index facd98d5262..47ba160df92 100644 --- a/lib/Fuzzer/FuzzerTracePC.h +++ b/lib/Fuzzer/FuzzerTracePC.h @@ -40,7 +40,6 @@ class TracePC { return Min(kMaxNewPCIDs, NumNewPCIDs); } - void ResetNewPCIDs() { NumNewPCIDs = 0; } uintptr_t GetPCbyPCID(uintptr_t PCID) { return PCs[PCID]; } void ResetMaps() { @@ -64,7 +63,7 @@ private: 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) { diff --git a/lib/Fuzzer/FuzzerUtil.cpp b/lib/Fuzzer/FuzzerUtil.cpp index a21570c13fd..254d9c826df 100644 --- a/lib/Fuzzer/FuzzerUtil.cpp +++ b/lib/Fuzzer/FuzzerUtil.cpp @@ -290,16 +290,20 @@ size_t GetPeakRSSMb() { return 0; } +std::string DescribePC(const char *SymbolizedFMT, uintptr_t PC) { + if (!EF->__sanitizer_symbolize_pc) return ""; + char PcDescr[1024]; + EF->__sanitizer_symbolize_pc(reinterpret_cast(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(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 diff --git a/lib/Fuzzer/fuzzer-test-suite/re2-2014-12-09/test.sh b/lib/Fuzzer/fuzzer-test-suite/re2-2014-12-09/test.sh new file mode 100755 index 00000000000..afcc0ed004a --- /dev/null +++ b/lib/Fuzzer/fuzzer-test-suite/re2-2014-12-09/test.sh @@ -0,0 +1,10 @@ +#!/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 diff --git a/lib/Fuzzer/test/MinimizeCorpusTest.cpp b/lib/Fuzzer/test/MinimizeCorpusTest.cpp index 02ef99fb26e..2fa17f156e2 100644 --- a/lib/Fuzzer/test/MinimizeCorpusTest.cpp +++ b/lib/Fuzzer/test/MinimizeCorpusTest.cpp @@ -21,7 +21,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { 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; } diff --git a/lib/Fuzzer/test/fuzzer.test b/lib/Fuzzer/test/fuzzer.test index ce207855e52..b48d734ef67 100644 --- a/lib/Fuzzer/test/fuzzer.test +++ b/lib/Fuzzer/test/fuzzer.test @@ -53,3 +53,7 @@ RUN: not LLVMFuzzer-DSOTest 2>&1 | FileCheck %s --check-prefix=DSO 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. + -- 2.11.0