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 N = Cases[0];
|
||||||
uint64_t ValSizeInBits = Cases[1];
|
uint64_t ValSizeInBits = Cases[1];
|
||||||
uint64_t *Vals = Cases + 2;
|
uint64_t *Vals = Cases + 2;
|
||||||
// Skip the most common and the most boring case.
|
// Skip the most common and the most boring case: all switch values are small.
|
||||||
if (Vals[N - 1] < 256 && Val < 256)
|
// 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;
|
return;
|
||||||
uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC());
|
uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC());
|
||||||
size_t i;
|
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++) {
|
for (i = 0; i < N; i++) {
|
||||||
Token = Val ^ Vals[i];
|
if (Val < Vals[i]) {
|
||||||
if (Val < Vals[i])
|
Larger = Vals[i];
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
if (Val > Vals[i]) Smaller = Vals[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ValSizeInBits == 16)
|
// Apply HandleCmp to {Val,Smaller} and {Val, Larger},
|
||||||
fuzzer::TPC.HandleCmp(PC + i, static_cast<uint16_t>(Token), (uint16_t)(0));
|
// use i as the PC modifier for HandleCmp.
|
||||||
else if (ValSizeInBits == 32)
|
if (ValSizeInBits == 16) {
|
||||||
fuzzer::TPC.HandleCmp(PC + i, static_cast<uint32_t>(Token), (uint32_t)(0));
|
fuzzer::TPC.HandleCmp(PC + 2 * i, static_cast<uint16_t>(Val),
|
||||||
else
|
(uint16_t)(Smaller));
|
||||||
fuzzer::TPC.HandleCmp(PC + i, Token, (uint64_t)(0));
|
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
|
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
|
CHECK: BINGO
|
||||||
RUN: %cpp_compiler %S/SwitchTest.cpp -o %t-SwitchTest
|
RUN: %cpp_compiler %S/SwitchTest.cpp -o %t-SwitchTest
|
||||||
RUN: %cpp_compiler %S/Switch2Test.cpp -o %t-Switch2Test
|
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-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-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