From 2156d885e0cffd767ec955c607b94ad774c6474c Mon Sep 17 00:00:00 2001 From: Max Moroz Date: Mon, 16 Jul 2018 14:54:23 +0000 Subject: [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 llvm-svn: 337175 --- compiler-rt/lib/fuzzer/FuzzerTracePC.cpp | 46 +++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) (limited to 'compiler-rt/lib/fuzzer/FuzzerTracePC.cpp') diff --git a/compiler-rt/lib/fuzzer/FuzzerTracePC.cpp b/compiler-rt/lib/fuzzer/FuzzerTracePC.cpp index 4e0ff149df6..e12e6c55cf0 100644 --- a/compiler-rt/lib/fuzzer/FuzzerTracePC.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerTracePC.cpp @@ -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(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 Arg1, T Arg2) { 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 *caller_pc, const char *s1, 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); -- cgit v1.2.3