forked from OSchip/llvm-project
[libFuzzer] more agressive value profiling and CMP tracing for switch statements
llvm-svn: 352107
This commit is contained in:
parent
b432369f6b
commit
360bf5ff58
|
@ -536,24 +536,44 @@ void __sanitizer_cov_trace_switch(uint64_t Val, uint64_t *Cases) {
|
|||
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)
|
||||
// Skip the most common and the most boring case: all switch values are small.
|
||||
// We may want to skip this at compile-time, but it will make the
|
||||
// instrumentation less general.
|
||||
if (Vals[N - 1] < 256)
|
||||
return;
|
||||
// Also skip small inputs values, they won't give good signal.
|
||||
if (Val < 256)
|
||||
return;
|
||||
uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC());
|
||||
size_t i;
|
||||
uint64_t Token = 0;
|
||||
uint64_t Smaller = 0;
|
||||
uint64_t Larger = ~(uint64_t)0;
|
||||
// Find two switch values such that Smaller < Val < Larger.
|
||||
// Use 0 and 0xfff..f as the defaults.
|
||||
for (i = 0; i < N; i++) {
|
||||
Token = Val ^ Vals[i];
|
||||
if (Val < Vals[i])
|
||||
if (Val < Vals[i]) {
|
||||
Larger = Vals[i];
|
||||
break;
|
||||
}
|
||||
if (Val > Vals[i]) Smaller = Vals[i];
|
||||
}
|
||||
|
||||
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 + i, Token, (uint64_t)(0));
|
||||
// Apply HandleCmp to {Val,Smaller} and {Val, Larger},
|
||||
// use i as the PC modifier for HandleCmp.
|
||||
if (ValSizeInBits == 16) {
|
||||
fuzzer::TPC.HandleCmp(PC + 2 * i, static_cast<uint16_t>(Val),
|
||||
(uint16_t)(Smaller));
|
||||
fuzzer::TPC.HandleCmp(PC + 2 * i + 1, static_cast<uint16_t>(Val),
|
||||
(uint16_t)(Larger));
|
||||
} else if (ValSizeInBits == 32) {
|
||||
fuzzer::TPC.HandleCmp(PC + 2 * i, static_cast<uint32_t>(Val),
|
||||
(uint32_t)(Smaller));
|
||||
fuzzer::TPC.HandleCmp(PC + 2 * i + 1, static_cast<uint32_t>(Val),
|
||||
(uint32_t)(Larger));
|
||||
} else {
|
||||
fuzzer::TPC.HandleCmp(PC + 2*i, Val, Smaller);
|
||||
fuzzer::TPC.HandleCmp(PC + 2*i + 1, Val, Larger);
|
||||
}
|
||||
}
|
||||
|
||||
ATTRIBUTE_INTERFACE
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
// 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 interesting switch value.
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
static volatile int Sink;
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
uint32_t v;
|
||||
if (Size < 100) return 0;
|
||||
memcpy(&v, Data + Size / 2, sizeof(v));
|
||||
switch(v) {
|
||||
case 0x47524159: abort();
|
||||
case 0x52474220: abort();
|
||||
default:;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2,5 +2,7 @@ UNSUPPORTED: ios
|
|||
CHECK: BINGO
|
||||
RUN: %cpp_compiler %S/SwitchTest.cpp -o %t-SwitchTest
|
||||
RUN: %cpp_compiler %S/Switch2Test.cpp -o %t-Switch2Test
|
||||
RUN: %cpp_compiler %S/Switch3Test.cpp -o %t-Switch3Test
|
||||
RUN: not %run %t-SwitchTest -use_cmp=0 -use_value_profile=1 -runs=100000000 -seed=1 2>&1 | FileCheck %s
|
||||
RUN: not %run %t-Switch2Test -use_cmp=0 -use_value_profile=1 -runs=100000000 -seed=1 2>&1 | FileCheck %s
|
||||
RUN: not %run %t-Switch3Test -use_cmp=0 -use_value_profile=1 -runs=100000000 -seed=1 2>&1
|
||||
|
|
Loading…
Reference in New Issue