diff options
author | Kostya Serebryany <kcc@google.com> | 2017-08-25 20:09:25 +0000 |
---|---|---|
committer | Kostya Serebryany <kcc@google.com> | 2017-08-25 20:09:25 +0000 |
commit | 70c68ad58bdc2727782b78eaf06347c77120219e (patch) | |
tree | 12609bd4b3d0ee23f918e3f218d0c8b74d86df89 | |
parent | 62ddf6220c3bc9c7ecc53bceec6d4548827a79e3 (diff) |
[libFuzzer] add -print_funcs=1 (on bey default): print newly discovered functions during fuzzing
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@311797 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/fuzzer/FuzzerDriver.cpp | 1 | ||||
-rw-r--r-- | lib/fuzzer/FuzzerFlags.def | 1 | ||||
-rw-r--r-- | lib/fuzzer/FuzzerLoop.cpp | 1 | ||||
-rw-r--r-- | lib/fuzzer/FuzzerOptions.h | 1 | ||||
-rw-r--r-- | lib/fuzzer/FuzzerTracePC.cpp | 19 | ||||
-rw-r--r-- | lib/fuzzer/FuzzerTracePC.h | 3 | ||||
-rw-r--r-- | test/fuzzer/PrintFuncTest.cpp | 39 | ||||
-rw-r--r-- | test/fuzzer/print-func.test | 10 |
8 files changed, 69 insertions, 6 deletions
diff --git a/lib/fuzzer/FuzzerDriver.cpp b/lib/fuzzer/FuzzerDriver.cpp index 17891d29c..d0d0f7dd0 100644 --- a/lib/fuzzer/FuzzerDriver.cpp +++ b/lib/fuzzer/FuzzerDriver.cpp @@ -603,6 +603,7 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) { Options.SaveArtifacts = !DoPlainRun || Flags.minimize_crash_internal_step; Options.PrintNewCovPcs = Flags.print_pcs; + Options.PrintNewCovFuncs = Flags.print_funcs; Options.PrintFinalStats = Flags.print_final_stats; Options.PrintCorpusStats = Flags.print_corpus_stats; Options.PrintCoverage = Flags.print_coverage; diff --git a/lib/fuzzer/FuzzerFlags.def b/lib/fuzzer/FuzzerFlags.def index 2887fd24d..6968c770a 100644 --- a/lib/fuzzer/FuzzerFlags.def +++ b/lib/fuzzer/FuzzerFlags.def @@ -91,6 +91,7 @@ FUZZER_FLAG_STRING(exact_artifact_path, "and will not use checksum in the file name. Do not " "use the same path for several parallel processes.") FUZZER_FLAG_INT(print_pcs, 0, "If 1, print out newly covered PCs.") +FUZZER_FLAG_INT(print_funcs, 1, "If 1, print out newly covered functions.") FUZZER_FLAG_INT(print_final_stats, 0, "If 1, print statistics at exit.") FUZZER_FLAG_INT(print_corpus_stats, 0, "If 1, print statistics on corpus elements at exit.") diff --git a/lib/fuzzer/FuzzerLoop.cpp b/lib/fuzzer/FuzzerLoop.cpp index 234945932..d2d096af4 100644 --- a/lib/fuzzer/FuzzerLoop.cpp +++ b/lib/fuzzer/FuzzerLoop.cpp @@ -626,6 +626,7 @@ void Fuzzer::MutateAndTestOne() { void Fuzzer::Loop() { TPC.SetPrintNewPCs(Options.PrintNewCovPcs); + TPC.SetPrintNewFuncs(Options.PrintNewCovFuncs); system_clock::time_point LastCorpusReload = system_clock::now(); if (Options.DoCrossOver) MD.SetCorpus(&Corpus); diff --git a/lib/fuzzer/FuzzerOptions.h b/lib/fuzzer/FuzzerOptions.h index 9500235e2..d38724209 100644 --- a/lib/fuzzer/FuzzerOptions.h +++ b/lib/fuzzer/FuzzerOptions.h @@ -47,6 +47,7 @@ struct FuzzingOptions { bool SaveArtifacts = true; bool PrintNEW = true; // Print a status line when new units are found; bool PrintNewCovPcs = false; + bool PrintNewCovFuncs = false; bool PrintFinalStats = false; bool PrintCorpusStats = false; bool PrintCoverage = false; diff --git a/lib/fuzzer/FuzzerTracePC.cpp b/lib/fuzzer/FuzzerTracePC.cpp index 2df850b2c..812a6190a 100644 --- a/lib/fuzzer/FuzzerTracePC.cpp +++ b/lib/fuzzer/FuzzerTracePC.cpp @@ -143,11 +143,18 @@ void TracePC::HandleCallerCallee(uintptr_t Caller, uintptr_t Callee) { } void TracePC::UpdateObservedPCs() { - auto Observe = [&](uintptr_t PC) { - bool Inserted = ObservedPCs.insert(PC).second; - if (Inserted && DoPrintNewPCs) + auto ObservePC = [&](uintptr_t PC) { + if (ObservedPCs.insert(PC).second && DoPrintNewPCs) PrintPC("\tNEW_PC: %p %F %L\n", "\tNEW_PC: %p\n", PC + 1); }; + + auto Observe = [&](const PCTableEntry &TE) { + if (TE.PCFlags & 1) + if (ObservedFuncs.insert(TE.PC).second && DoPrintNewFuncs) + PrintPC("\tNEW_FUNC: %p %F %L\n", "\tNEW_PC: %p\n", TE.PC + 1); + ObservePC(TE.PC); + }; + if (NumPCsInPCTables) { if (NumInline8bitCounters == NumPCsInPCTables) { for (size_t i = 0; i < NumModulesWithInline8bitCounters; i++) { @@ -157,7 +164,7 @@ void TracePC::UpdateObservedPCs() { (size_t)(ModulePCTable[i].Stop - ModulePCTable[i].Start)); for (size_t j = 0; j < Size; j++) if (Beg[j]) - Observe(ModulePCTable[i].Start[j].PC); + Observe(ModulePCTable[i].Start[j]); } } else if (NumGuards == NumPCsInPCTables) { size_t GuardIdx = 1; @@ -168,7 +175,7 @@ void TracePC::UpdateObservedPCs() { (size_t)(ModulePCTable[i].Stop - ModulePCTable[i].Start)); for (size_t j = 0; j < Size; j++, GuardIdx++) if (Counters()[GuardIdx]) - Observe(ModulePCTable[i].Start[j].PC); + Observe(ModulePCTable[i].Start[j]); } } } @@ -177,7 +184,7 @@ void TracePC::UpdateObservedPCs() { auto P = ClangCountersBegin(); for (size_t Idx = 0; Idx < NumClangCounters; Idx++) if (P[Idx]) - Observe((uintptr_t)Idx); + ObservePC((uintptr_t)Idx); } } diff --git a/lib/fuzzer/FuzzerTracePC.h b/lib/fuzzer/FuzzerTracePC.h index 0c9d4b69b..76aa0748f 100644 --- a/lib/fuzzer/FuzzerTracePC.h +++ b/lib/fuzzer/FuzzerTracePC.h @@ -82,6 +82,7 @@ class TracePC { void SetUseCounters(bool UC) { UseCounters = UC; } void SetUseValueProfile(bool VP) { UseValueProfile = VP; } void SetPrintNewPCs(bool P) { DoPrintNewPCs = P; } + void SetPrintNewFuncs(bool P) { DoPrintNewFuncs = P; } void UpdateObservedPCs(); template <class Callback> void CollectFeatures(Callback CB) const; @@ -133,6 +134,7 @@ private: bool UseCounters = false; bool UseValueProfile = false; bool DoPrintNewPCs = false; + bool DoPrintNewFuncs = false; struct Module { uint32_t *Start, *Stop; @@ -158,6 +160,7 @@ private: uintptr_t *PCs() const; std::set<uintptr_t> ObservedPCs; + std::set<uintptr_t> ObservedFuncs; ValueBitMap ValueProfileMap; uintptr_t InitialStack; diff --git a/test/fuzzer/PrintFuncTest.cpp b/test/fuzzer/PrintFuncTest.cpp new file mode 100644 index 000000000..d41b46239 --- /dev/null +++ b/test/fuzzer/PrintFuncTest.cpp @@ -0,0 +1,39 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find the string "Hi!". +#include <cstddef> +#include <cstdint> +#include <cstdlib> +#include <iostream> + +extern "C" { +__attribute__((noinline)) +void FunctionC(const uint8_t *Data, size_t Size) { + if (Size > 3 && Data[3] == 'Z') { + static bool PrintedOnce = false; + if (!PrintedOnce) { + std::cout << "BINGO\n"; + PrintedOnce = true; + } + } +} + +__attribute__((noinline)) +void FunctionB(const uint8_t *Data, size_t Size) { + if (Size > 2 && Data[2] == 'Z') + FunctionC(Data, Size); +} +__attribute__((noinline)) +void FunctionA(const uint8_t *Data, size_t Size) { + if (Size > 1 && Data[1] == 'U') + FunctionB(Data, Size); +} +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size > 0 && Data[0] == 'F') + FunctionA(Data, Size); + return 0; +} + diff --git a/test/fuzzer/print-func.test b/test/fuzzer/print-func.test new file mode 100644 index 000000000..12d52cb0b --- /dev/null +++ b/test/fuzzer/print-func.test @@ -0,0 +1,10 @@ +RUN: %cpp_compiler %S/PrintFuncTest.cpp -o %t +RUN: %t -seed=1 -runs=100000 2>&1 | FileCheck %s +RUN: %t -seed=1 -runs=100000 -print_funcs=0 2>&1 | FileCheck %s --check-prefix=NO +CHECK: NEW_FUNC: {{.*}} FunctionA +CHECK: NEW_FUNC: {{.*}} FunctionB +CHECK: NEW_FUNC: {{.*}} FunctionC +CHECK: BINGO + +NO-NOT: NEW_FUNC +NO: BINGO |