[compiler-rt] r337175 - [libFuzzer] Implement stat::stability_rate based on the percentage of unstable edges.
Kostya Serebryany via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 16 08:08:10 PDT 2018
any idea why this change shows so many formatting changes, while
phabricator doesn't?
On Mon, Jul 16, 2018 at 7:59 AM Max Moroz via llvm-commits <
llvm-commits at lists.llvm.org> wrote:
> Author: dor1s
> Date: Mon Jul 16 07:54:23 2018
> New Revision: 337175
>
> URL: http://llvm.org/viewvc/llvm-project?rev=337175&view=rev
> Log:
> [libFuzzer] Implement stat::stability_rate based on the percentage of
> unstable edges.
>
> Summary:
> Created a -print_unstable_stats flag.
> When -print_unstable_stats=1, we run it 2 more times on interesting inputs
> poisoning unstable edges in an array.
> On program termination, we run PrintUnstableStats() which will print a
> line with a stability percentage like AFL does.
>
> Patch by Kyungtak Woo (@kevinwkt).
>
> Reviewers: metzman, Dor1s, kcc, morehouse
>
> Reviewed By: metzman, Dor1s, morehouse
>
> Subscribers: delcypher, llvm-commits, #sanitizers, kcc, morehouse, Dor1s
>
> Differential Revision: https://reviews.llvm.org/D49212
>
> Added:
> compiler-rt/trunk/test/fuzzer/PrintUnstableStatsTest.cpp
> compiler-rt/trunk/test/fuzzer/print_unstable_stats.test
> Modified:
> compiler-rt/trunk/lib/fuzzer/FuzzerDriver.cpp
> compiler-rt/trunk/lib/fuzzer/FuzzerFlags.def
> compiler-rt/trunk/lib/fuzzer/FuzzerInternal.h
> compiler-rt/trunk/lib/fuzzer/FuzzerLoop.cpp
> compiler-rt/trunk/lib/fuzzer/FuzzerOptions.h
> compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.cpp
> compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.h
>
> Modified: compiler-rt/trunk/lib/fuzzer/FuzzerDriver.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerDriver.cpp?rev=337175&r1=337174&r2=337175&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/fuzzer/FuzzerDriver.cpp (original)
> +++ compiler-rt/trunk/lib/fuzzer/FuzzerDriver.cpp Mon Jul 16 07:54:23 2018
> @@ -102,14 +102,14 @@ static void PrintHelp() {
> Printf("%d\t%s\n", D.Default, D.Description);
> }
> Printf("\nFlags starting with '--' will be ignored and "
> - "will be passed verbatim to subprocesses.\n");
> + "will be passed verbatim to subprocesses.\n");
> }
>
> static const char *FlagValue(const char *Param, const char *Name) {
> size_t Len = strlen(Name);
> if (Param[0] == '-' && strstr(Param + 1, Name) == Param + 1 &&
> Param[Len + 1] == '=')
> - return &Param[Len + 2];
> + return &Param[Len + 2];
> return nullptr;
> }
>
> @@ -302,10 +302,10 @@ static std::string GetDedupTokenFromFile
> }
>
> int CleanseCrashInput(const Vector<std::string> &Args,
> - const FuzzingOptions &Options) {
> + const FuzzingOptions &Options) {
> if (Inputs->size() != 1 || !Flags.exact_artifact_path) {
> Printf("ERROR: -cleanse_crash should be given one input file and"
> - " -exact_artifact_path\n");
> + " -exact_artifact_path\n");
> exit(1);
> }
> std::string InputFilePath = Inputs->at(0);
> @@ -520,7 +520,7 @@ int AnalyzeDictionary(Fuzzer *F, const V
> for (size_t i = 0; i < Dict.size(); ++i) {
> // Dictionary units with positive score are treated as useful ones.
> if (Scores[i] > 0)
> - continue;
> + continue;
>
> Printf("\"");
> PrintASCII(Dict[i].data(), Dict[i].size(), "\"");
> @@ -617,6 +617,7 @@ int FuzzerDriver(int *argc, char ***argv
> Options.PrintFinalStats = Flags.print_final_stats;
> Options.PrintCorpusStats = Flags.print_corpus_stats;
> Options.PrintCoverage = Flags.print_coverage;
> + Options.PrintUnstableStats = Flags.print_unstable_stats;
> Options.DumpCoverage = Flags.dump_coverage;
> if (Flags.exit_on_src_pos)
> Options.ExitOnSrcPos = Flags.exit_on_src_pos;
>
> Modified: compiler-rt/trunk/lib/fuzzer/FuzzerFlags.def
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerFlags.def?rev=337175&r1=337174&r2=337175&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/fuzzer/FuzzerFlags.def (original)
> +++ compiler-rt/trunk/lib/fuzzer/FuzzerFlags.def Mon Jul 16 07:54:23 2018
> @@ -110,6 +110,8 @@ FUZZER_FLAG_INT(print_coverage, 0, "If 1
> FUZZER_FLAG_INT(dump_coverage, 0, "Deprecated."
> " If 1, dump coverage information as a"
> " .sancov file at exit.")
> +FUZZER_FLAG_INT(print_unstable_stats, 0, "Experimental."
> + " If 1, print unstable statistics at
> exit.")
> FUZZER_FLAG_INT(handle_segv, 1, "If 1, try to intercept SIGSEGV.")
> FUZZER_FLAG_INT(handle_bus, 1, "If 1, try to intercept SIGBUS.")
> FUZZER_FLAG_INT(handle_abrt, 1, "If 1, try to intercept SIGABRT.")
>
> Modified: compiler-rt/trunk/lib/fuzzer/FuzzerInternal.h
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerInternal.h?rev=337175&r1=337174&r2=337175&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/fuzzer/FuzzerInternal.h (original)
> +++ compiler-rt/trunk/lib/fuzzer/FuzzerInternal.h Mon Jul 16 07:54:23 2018
> @@ -67,6 +67,7 @@ public:
> static void StaticGracefulExitCallback();
>
> void ExecuteCallback(const uint8_t *Data, size_t Size);
> + void CheckForUnstableCounters(const uint8_t *Data, size_t Size);
> bool RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile =
> false,
> InputInfo *II = nullptr, bool *FoundUniqFeatures = nullptr);
>
>
> Modified: compiler-rt/trunk/lib/fuzzer/FuzzerLoop.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerLoop.cpp?rev=337175&r1=337174&r2=337175&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/fuzzer/FuzzerLoop.cpp (original)
> +++ compiler-rt/trunk/lib/fuzzer/FuzzerLoop.cpp Mon Jul 16 07:54:23 2018
> @@ -352,6 +352,8 @@ void Fuzzer::PrintStats(const char *Wher
> void Fuzzer::PrintFinalStats() {
> if (Options.PrintCoverage)
> TPC.PrintCoverage();
> + if (Options.PrintUnstableStats)
> + TPC.PrintUnstableStats();
> if (Options.DumpCoverage)
> TPC.DumpCoverage();
> if (Options.PrintCorpusStats)
> @@ -444,6 +446,29 @@ void Fuzzer::PrintPulseAndReportSlowInpu
> }
> }
>
> +void Fuzzer::CheckForUnstableCounters(const uint8_t *Data, size_t Size) {
> + auto CBSetupAndRun = [&]() {
> + ScopedEnableMsanInterceptorChecks S;
> + UnitStartTime = system_clock::now();
> + TPC.ResetMaps();
> + RunningCB = true;
> + CB(Data, Size);
> + RunningCB = false;
> + UnitStopTime = system_clock::now();
> + };
> +
> + // Copy original run counters into our unstable counters
> + TPC.InitializeUnstableCounters();
> +
> + // First Rerun
> + CBSetupAndRun();
> + TPC.UpdateUnstableCounters();
> +
> + // Second Rerun
> + CBSetupAndRun();
> + TPC.UpdateUnstableCounters();
> +}
> +
> bool Fuzzer::RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile,
> InputInfo *II, bool *FoundUniqFeatures) {
> if (!Size)
> @@ -466,6 +491,12 @@ bool Fuzzer::RunOne(const uint8_t *Data,
> *FoundUniqFeatures = FoundUniqFeaturesOfII;
> PrintPulseAndReportSlowInput(Data, Size);
> size_t NumNewFeatures = Corpus.NumFeatureUpdates() - NumUpdatesBefore;
> +
> + // If print_unstable_stats, execute the same input two more times to
> detect
> + // unstable edges.
> + if (NumNewFeatures && Options.PrintUnstableStats)
> + CheckForUnstableCounters(Data, Size);
> +
> if (NumNewFeatures) {
> TPC.UpdateObservedPCs();
> Corpus.AddToCorpus({Data, Data + Size}, NumNewFeatures, MayDeleteFile,
> @@ -669,7 +700,7 @@ void Fuzzer::MutateAndTestOne() {
> break; // We will mutate this input more in the next rounds.
> }
> if (Options.ReduceDepth && !FoundUniqFeatures)
> - break;
> + break;
> }
> }
>
>
> Modified: compiler-rt/trunk/lib/fuzzer/FuzzerOptions.h
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerOptions.h?rev=337175&r1=337174&r2=337175&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/fuzzer/FuzzerOptions.h (original)
> +++ compiler-rt/trunk/lib/fuzzer/FuzzerOptions.h Mon Jul 16 07:54:23 2018
> @@ -54,6 +54,7 @@ struct FuzzingOptions {
> bool PrintFinalStats = false;
> bool PrintCorpusStats = false;
> bool PrintCoverage = false;
> + bool PrintUnstableStats = false;
> bool DumpCoverage = false;
> bool DetectLeaks = true;
> int PurgeAllocatorIntervalSec = 1;
>
> Modified: compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.cpp?rev=337175&r1=337174&r2=337175&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.cpp (original)
> +++ compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.cpp Mon Jul 16 07:54:23 2018
> @@ -59,6 +59,37 @@ size_t TracePC::GetTotalPCCoverage() {
> return Res;
> }
>
> +// Initializes unstable counters by copying Inline8bitCounters to unstable
> +// counters.
> +void TracePC::InitializeUnstableCounters() {
> + if (NumInline8bitCounters && NumInline8bitCounters == NumPCsInPCTables)
> {
> + size_t UnstableIdx = 0;
> + for (size_t i = 0; i < NumModulesWithInline8bitCounters; i++) {
> + uint8_t *Beg = ModuleCounters[i].Start;
> + size_t Size = ModuleCounters[i].Stop - Beg;
> + assert(Size == (size_t)(ModulePCTable[i].Stop -
> ModulePCTable[i].Start));
> + for (size_t j = 0; j < Size; j++, UnstableIdx++)
> + if (UnstableCounters[UnstableIdx] != kUnstableCounter)
> + UnstableCounters[UnstableIdx] = Beg[j];
> + }
> + }
> +}
> +
> +// Compares the current counters with counters from previous runs
> +// and records differences as unstable edges.
> +void TracePC::UpdateUnstableCounters() {
> + if (NumInline8bitCounters && NumInline8bitCounters == NumPCsInPCTables)
> {
> + size_t UnstableIdx = 0;
> + for (size_t i = 0; i < NumModulesWithInline8bitCounters; i++) {
> + uint8_t *Beg = ModuleCounters[i].Start;
> + size_t Size = ModuleCounters[i].Stop - Beg;
> + assert(Size == (size_t)(ModulePCTable[i].Stop -
> ModulePCTable[i].Start));
> + for (size_t j = 0; j < Size; j++, UnstableIdx++)
> + if (Beg[j] != UnstableCounters[UnstableIdx])
> + UnstableCounters[UnstableIdx] = kUnstableCounter;
> + }
> + }
> +}
>
> void TracePC::HandleInline8bitCountersInit(uint8_t *Start, uint8_t *Stop)
> {
> if (Start == Stop) return;
> @@ -310,6 +341,15 @@ void TracePC::DumpCoverage() {
> }
> }
>
> +void TracePC::PrintUnstableStats() {
> + size_t count = 0;
> + for (size_t i = 0; i < NumInline8bitCounters; i++)
> + if (UnstableCounters[i] == kUnstableCounter)
> + count++;
> + Printf("stat::stability_rate: %.2f\n",
> + 100 - static_cast<float>(count * 100) / NumInline8bitCounters);
> +}
> +
> // Value profile.
> // We keep track of various values that affect control flow.
> // These values are inserted into a bit-set-based hash map.
> @@ -356,9 +396,9 @@ void TracePC::HandleCmp(uintptr_t PC, T
> uint64_t ArgDistance = __builtin_popcountll(ArgXor) + 1; // [1,65]
> uintptr_t Idx = ((PC & 4095) + 1) * ArgDistance;
> if (sizeof(T) == 4)
> - TORC4.Insert(ArgXor, Arg1, Arg2);
> + TORC4.Insert(ArgXor, Arg1, Arg2);
> else if (sizeof(T) == 8)
> - TORC8.Insert(ArgXor, Arg1, Arg2);
> + TORC8.Insert(ArgXor, Arg1, Arg2);
> // TODO: remove these flags and instead use all metrics at once.
> if (UseValueProfileMask & 1)
> ValueProfileMap.AddValue(Idx);
> @@ -589,7 +629,7 @@ void __sanitizer_weak_hook_strncmp(void
>
> ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY
> void __sanitizer_weak_hook_strcmp(void *caller_pc, const char *s1,
> - const char *s2, int result) {
> + const char *s2, int result) {
> if (fuzzer::ScopedDoingMyOwnMemOrStr::DoingMyOwnMemOrStr) return;
> if (result == 0) return; // No reason to mutate.
> size_t N = fuzzer::InternalStrnlen2(s1, s2);
>
> Modified: compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.h
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.h?rev=337175&r1=337174&r2=337175&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.h (original)
> +++ compiler-rt/trunk/lib/fuzzer/FuzzerTracePC.h Mon Jul 16 07:54:23 2018
> @@ -68,7 +68,7 @@ struct MemMemTable {
> };
>
> class TracePC {
> - public:
> +public:
> static const size_t kNumPCs = 1 << 21;
> // How many bits of PC are used from __sanitizer_cov_trace_pc.
> static const size_t kTracePcBits = 18;
> @@ -103,6 +103,7 @@ class TracePC {
>
> void PrintCoverage();
> void DumpCoverage();
> + void PrintUnstableStats();
>
> template<class CallBack>
> void IterateCoveredFunctions(CallBack CB);
> @@ -135,7 +136,17 @@ class TracePC {
> void SetFocusFunction(const std::string &FuncName);
> bool ObservedFocusFunction();
>
> + void InitializeUnstableCounters();
> + void UpdateUnstableCounters();
> +
> private:
> + // Value used to represent unstable edge.
> + static constexpr int16_t kUnstableCounter = -1;
> +
> + // Uses 16-bit signed type to be able to accommodate any possible value
> from
> + // uint8_t counter and -1 constant as well.
> + int16_t UnstableCounters[kNumPCs];
> +
> bool UseCounters = false;
> uint32_t UseValueProfileMask = false;
> bool DoPrintNewPCs = false;
> @@ -204,27 +215,27 @@ void ForEachNonZeroByte(const uint8_t *B
> // Given a non-zero Counter returns a number in the range [0,7].
> template<class T>
> unsigned CounterToFeature(T Counter) {
> - // Returns a feature number by placing Counters into buckets as
> illustrated
> - // below.
> - //
> - // Counter bucket: [1] [2] [3] [4-7] [8-15] [16-31] [32-127] [128+]
> - // Feature number: 0 1 2 3 4 5 6 7
> - //
> - // This is a heuristic taken from AFL (see
> - // http://lcamtuf.coredump.cx/afl/technical_details.txt).
> - //
> - // This implementation may change in the future so clients should
> - // not rely on it.
> - assert(Counter);
> - unsigned Bit = 0;
> - /**/ if (Counter >= 128) Bit = 7;
> - else if (Counter >= 32) Bit = 6;
> - else if (Counter >= 16) Bit = 5;
> - else if (Counter >= 8) Bit = 4;
> - else if (Counter >= 4) Bit = 3;
> - else if (Counter >= 3) Bit = 2;
> - else if (Counter >= 2) Bit = 1;
> - return Bit;
> + // Returns a feature number by placing Counters into buckets as
> illustrated
> + // below.
> + //
> + // Counter bucket: [1] [2] [3] [4-7] [8-15] [16-31] [32-127] [128+]
> + // Feature number: 0 1 2 3 4 5 6 7
> + //
> + // This is a heuristic taken from AFL (see
> + // http://lcamtuf.coredump.cx/afl/technical_details.txt).
> + //
> + // This implementation may change in the future so clients should
> + // not rely on it.
> + assert(Counter);
> + unsigned Bit = 0;
> + /**/ if (Counter >= 128) Bit = 7;
> + else if (Counter >= 32) Bit = 6;
> + else if (Counter >= 16) Bit = 5;
> + else if (Counter >= 8) Bit = 4;
> + else if (Counter >= 4) Bit = 3;
> + else if (Counter >= 3) Bit = 2;
> + else if (Counter >= 2) Bit = 1;
> + return Bit;
> }
>
> template <class Callback> // void Callback(size_t Feature)
>
> Added: compiler-rt/trunk/test/fuzzer/PrintUnstableStatsTest.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/fuzzer/PrintUnstableStatsTest.cpp?rev=337175&view=auto
>
> ==============================================================================
> --- compiler-rt/trunk/test/fuzzer/PrintUnstableStatsTest.cpp (added)
> +++ compiler-rt/trunk/test/fuzzer/PrintUnstableStatsTest.cpp Mon Jul 16
> 07:54:23 2018
> @@ -0,0 +1,69 @@
> +#include <assert.h>
> +#include <cstdint>
> +#include <cstdio>
> +#include <cstdlib>
> +
> +int x = 0;
> +bool skip0 = false;
> +bool skip1 = false;
> +bool skip2 = false;
> +
> +__attribute__((noinline)) void det0() { x++; }
> +__attribute__((noinline)) void det1() { x++; }
> +__attribute__((noinline)) void det2() { x++; }
> +__attribute__((noinline)) void det3() { x++; }
> +__attribute__((noinline)) void det4() { x++; }
> +
> +__attribute__((noinline)) void ini0() { x++; }
> +__attribute__((noinline)) void ini1() { x++; }
> +__attribute__((noinline)) void ini2() { x++; }
> +
> +__attribute__((noinline)) void t0() { x++; }
> +__attribute__((noinline)) void t1() { x++; }
> +__attribute__((noinline)) void t2() { x++; }
> +__attribute__((noinline)) void t3() { x++; }
> +__attribute__((noinline)) void t4() { x++; }
> +
> +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
> + if (Size == 1 && Data[0] == 'A' && !skip0) {
> + skip0 = true;
> + ini0();
> + }
> + if (Size == 1 && Data[0] == 'B' && !skip1) {
> + skip1 = true;
> + ini1();
> + }
> + if (Size == 1 && Data[0] == 'C' && !skip2) {
> + skip2 = true;
> + ini2();
> + }
> +
> + det0();
> + det1();
> + int a = rand();
> + det2();
> +
> + switch (a % 5) {
> + case 0:
> + t0();
> + break;
> + case 1:
> + t1();
> + break;
> + case 2:
> + t2();
> + break;
> + case 3:
> + t3();
> + break;
> + case 4:
> + t4();
> + break;
> + default:
> + assert(false);
> + }
> +
> + det3();
> + det4();
> + return 0;
> +}
>
> Added: compiler-rt/trunk/test/fuzzer/print_unstable_stats.test
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/fuzzer/print_unstable_stats.test?rev=337175&view=auto
>
> ==============================================================================
> --- compiler-rt/trunk/test/fuzzer/print_unstable_stats.test (added)
> +++ compiler-rt/trunk/test/fuzzer/print_unstable_stats.test Mon Jul 16
> 07:54:23 2018
> @@ -0,0 +1,3 @@
> +RUN: %cpp_compiler %S/PrintUnstableStatsTest.cpp -o
> %t-PrintUnstableStatsTest
> +RUN: %run %t-PrintUnstableStatsTest -print_unstable_stats=1 -runs=100000
> 2>&1 | FileCheck %s --check-prefix=LONG
> +LONG: stat::stability_rate: 27.59
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180716/d5c2e3cf/attachment.html>
More information about the llvm-commits
mailing list