diff options
| author | Kostya Serebryany <kcc@google.com> | 2016-12-29 02:50:35 +0000 |
|---|---|---|
| committer | Kostya Serebryany <kcc@google.com> | 2016-12-29 02:50:35 +0000 |
| commit | d723804fa250a66d593678e7331c0bbb1ecaec79 (patch) | |
| tree | 4d4897670f1be96983247e42bfa7953455ddf25e /llvm/lib/Fuzzer | |
| parent | b57a84daceb5df70fcfc192740e6dbf449e767ff (diff) | |
| download | bcm5719-llvm-d723804fa250a66d593678e7331c0bbb1ecaec79.tar.gz bcm5719-llvm-d723804fa250a66d593678e7331c0bbb1ecaec79.zip | |
[libFuzzer] make __sanitizer_cov_trace_switch more predictable
llvm-svn: 290703
Diffstat (limited to 'llvm/lib/Fuzzer')
| -rw-r--r-- | llvm/lib/Fuzzer/FuzzerTracePC.cpp | 39 | ||||
| -rw-r--r-- | llvm/lib/Fuzzer/test/SwitchTest.cpp | 4 |
2 files changed, 19 insertions, 24 deletions
diff --git a/llvm/lib/Fuzzer/FuzzerTracePC.cpp b/llvm/lib/Fuzzer/FuzzerTracePC.cpp index 81c084b5899..ad5f9f09d1e 100644 --- a/llvm/lib/Fuzzer/FuzzerTracePC.cpp +++ b/llvm/lib/Fuzzer/FuzzerTracePC.cpp @@ -295,32 +295,27 @@ 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 ValSizeInBits = Cases[1]; uint64_t *Vals = Cases + 2; + // Skip the most common and the most boring case. + if (Vals[N - 1] < 256 && Val < 256) + return; char *PC = (char*)__builtin_return_address(0); - // We need a random number < N using Counter as a seed. But w/o DIV. - // * find a power of two >= N - // * mask Counter with this power of two. - // * maybe subtract N. - size_t Nlog = sizeof(long) * 8 - __builtin_clzl((long)N); - size_t PowerOfTwoGeN = 1U << Nlog; - assert(PowerOfTwoGeN >= N); - size_t Idx = Counter & (PowerOfTwoGeN - 1); - if (Idx >= N) - Idx -= N; - assert(Idx < N); - uint64_t TwoIn32 = 1ULL << 32; - if ((Val | Vals[Idx]) < TwoIn32) - fuzzer::TPC.HandleCmp(PC + Idx, static_cast<uint32_t>(Val), - static_cast<uint32_t>(Vals[Idx])); + size_t i; + uint64_t Token = 0; + for (i = 0; i < N; i++) { + Token = Val ^ Vals[i]; + if (Val < Vals[i]) + break; + } + + if (ValSizeInBits == 16) + fuzzer::TPC.HandleCmp(PC + i, static_cast<uint16_t>(Token), (uint16_t)(0)); + else if (ValSizeInBits == 32) + fuzzer::TPC.HandleCmp(PC + i, static_cast<uint32_t>(Token), (uint32_t)(0)); else - fuzzer::TPC.HandleCmp(PC + Idx, Val, Vals[Idx]); + fuzzer::TPC.HandleCmp(PC + i, Token, (uint64_t)(0)); } __attribute__((visibility("default"))) diff --git a/llvm/lib/Fuzzer/test/SwitchTest.cpp b/llvm/lib/Fuzzer/test/SwitchTest.cpp index 74e86c06cb4..3dc051ff7b5 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; } |

