From 00e638e64268d62ec4fc209de03ecd5d2e2a586c Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Sat, 17 Dec 2016 02:03:34 +0000 Subject: [PATCH] [libFuzzer] when tracing switch statements, handle only one case at a time (to make things faster). Also ensure that the signals from value profile do not intersect with the regular coverage llvm-svn: 290031 --- llvm/lib/Fuzzer/FuzzerTracePC.cpp | 16 +++++++++++++--- llvm/lib/Fuzzer/FuzzerTracePC.h | 2 +- llvm/lib/Fuzzer/test/SwitchTest.cpp | 4 ++-- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Fuzzer/FuzzerTracePC.cpp b/llvm/lib/Fuzzer/FuzzerTracePC.cpp index 6cb1c66e2054..74eb854ef76e 100644 --- a/llvm/lib/Fuzzer/FuzzerTracePC.cpp +++ b/llvm/lib/Fuzzer/FuzzerTracePC.cpp @@ -290,12 +290,22 @@ void __sanitizer_cov_trace_cmp1(uint8_t Arg1, uint8_t Arg2) { __attribute__((visibility("default"))) void __sanitizer_cov_trace_switch(uint64_t Val, uint64_t *Cases) { + // Updates the value profile based on the relative position of Val and Cases. + // We want to handle one random case at every call (handling all is slow). + // Since none of the arguments contain any random bits we use a thread-local + // counter to choose the random case to handle. + static thread_local size_t Counter; + Counter++; uint64_t N = Cases[0]; uint64_t *Vals = Cases + 2; char *PC = (char*)__builtin_return_address(0); - for (size_t i = 0; i < N; i++) - if (Val != Vals[i]) - fuzzer::TPC.HandleCmp(PC + i, Val, Vals[i]); + size_t Idx = Counter % N; + uint64_t TwoIn32 = 1ULL << 32; + if ((Val | Vals[Idx]) < TwoIn32) + fuzzer::TPC.HandleCmp(PC + Idx, static_cast(Val), + static_cast(Vals[Idx])); + else + fuzzer::TPC.HandleCmp(PC + Idx, Val, Vals[Idx]); } __attribute__((visibility("default"))) diff --git a/llvm/lib/Fuzzer/FuzzerTracePC.h b/llvm/lib/Fuzzer/FuzzerTracePC.h index e3f6f10a36f6..9d4162833012 100644 --- a/llvm/lib/Fuzzer/FuzzerTracePC.h +++ b/llvm/lib/Fuzzer/FuzzerTracePC.h @@ -144,7 +144,7 @@ size_t TracePC::CollectFeatures(Callback CB) { } if (UseValueProfile) ValueProfileMap.ForEach([&](size_t Idx) { - if (CB(NumGuards + Idx)) + if (CB(NumGuards * 8 + Idx)) Res++; }); return Res; diff --git a/llvm/lib/Fuzzer/test/SwitchTest.cpp b/llvm/lib/Fuzzer/test/SwitchTest.cpp index 3dc051ff7b5b..74e86c06cb41 100644 --- a/llvm/lib/Fuzzer/test/SwitchTest.cpp +++ b/llvm/lib/Fuzzer/test/SwitchTest.cpp @@ -20,8 +20,8 @@ bool Switch(const uint8_t *Data, size_t Size) { case 101: Sink = __LINE__; break; case 1001: Sink = __LINE__; break; case 10001: Sink = __LINE__; break; - case 100001: Sink = __LINE__; break; - case 1000001: Sink = __LINE__; break; +// case 100001: Sink = __LINE__; break; +// case 1000001: Sink = __LINE__; break; case 10000001: Sink = __LINE__; break; case 100000001: return true; }