mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-19 04:32:19 +00:00
[lib/Fuzzer] rename FuzzerDFSan.cpp to FuzzerTraceState.cpp; update comments. NFC expected
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@237050 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
f6548b86b6
commit
051ef86497
@ -4,7 +4,7 @@ set(CMAKE_CXX_FLAGS_RELEASE "${LIBFUZZER_FLAGS_BASE} -O2 -fno-sanitize=all")
|
||||
if( LLVM_USE_SANITIZE_COVERAGE )
|
||||
add_library(LLVMFuzzerNoMain OBJECT
|
||||
FuzzerCrossOver.cpp
|
||||
FuzzerDFSan.cpp
|
||||
FuzzerTraceState.cpp
|
||||
FuzzerDriver.cpp
|
||||
FuzzerIO.cpp
|
||||
FuzzerLoop.cpp
|
||||
|
@ -67,7 +67,7 @@ class Fuzzer {
|
||||
void AddToCorpus(const Unit &U) { Corpus.push_back(U); }
|
||||
void Loop(size_t NumIterations);
|
||||
void ShuffleAndMinimize();
|
||||
void InitializeDFSan();
|
||||
void InitializeTraceState();
|
||||
size_t CorpusSize() const { return Corpus.size(); }
|
||||
void ReadDir(const std::string &Path, long *Epoch) {
|
||||
ReadDirToVectorOfUnits(Path.c_str(), &Corpus, Epoch);
|
||||
|
@ -22,7 +22,7 @@ static Fuzzer *F;
|
||||
Fuzzer::Fuzzer(UserCallback Callback, FuzzingOptions Options)
|
||||
: Callback(Callback), Options(Options) {
|
||||
SetDeathCallback();
|
||||
InitializeDFSan();
|
||||
InitializeTraceState();
|
||||
assert(!F);
|
||||
F = this;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===- FuzzerDFSan.cpp - DFSan-based fuzzer mutator -----------------------===//
|
||||
//===- FuzzerTraceState.cpp - Trace-based fuzzer mutator ------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -6,25 +6,37 @@
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// This file implements a mutation algorithm based on instruction traces and
|
||||
// on taint analysis feedback from DFSan.
|
||||
//
|
||||
// Instruction traces are special hooks inserted by the compiler around
|
||||
// interesting instructions. Currently supported traces:
|
||||
// * __sanitizer_cov_trace_cmp -- inserted before every ICMP instruction,
|
||||
// receives the type, size and arguments of ICMP.
|
||||
//
|
||||
// Every time a traced event is intercepted we analyse the data involved
|
||||
// in the event and suggest a mutation for future executions.
|
||||
// For example if 4 bytes of data that derive from input bytes {4,5,6,7}
|
||||
// are compared with a constant 12345,
|
||||
// we try to insert 12345, 12344, 12346 into bytes
|
||||
// {4,5,6,7} of the next fuzzed inputs.
|
||||
//
|
||||
// The fuzzer can work only with the traces, or with both traces and DFSan.
|
||||
//
|
||||
// DataFlowSanitizer (DFSan) is a tool for
|
||||
// generalised dynamic data flow (taint) analysis:
|
||||
// http://clang.llvm.org/docs/DataFlowSanitizer.html .
|
||||
//
|
||||
// This file implements a mutation algorithm based on taint
|
||||
// analysis feedback from DFSan.
|
||||
//
|
||||
// The approach has some similarity to "Taint-based Directed Whitebox Fuzzing"
|
||||
// The approach with DFSan-based fuzzing has some similarity to
|
||||
// "Taint-based Directed Whitebox Fuzzing"
|
||||
// by Vijay Ganesh & Tim Leek & Martin Rinard:
|
||||
// http://dspace.mit.edu/openaccess-disseminate/1721.1/59320,
|
||||
// but it uses a full blown LLVM IR taint analysis and separate instrumentation
|
||||
// to analyze all of the "attack points" at once.
|
||||
//
|
||||
// Workflow:
|
||||
// Workflow with DFSan:
|
||||
// * lib/Fuzzer/Fuzzer*.cpp is compiled w/o any instrumentation.
|
||||
// * The code under test is compiled with DFSan *and* with special extra hooks
|
||||
// that are inserted before dfsan. Currently supported hooks:
|
||||
// - __sanitizer_cov_trace_cmp: inserted before every ICMP instruction,
|
||||
// receives the type, size and arguments of ICMP.
|
||||
// * The code under test is compiled with DFSan *and* with instruction traces.
|
||||
// * Every call to HOOK(a,b) is replaced by DFSan with
|
||||
// __dfsw_HOOK(a, b, label(a), label(b)) so that __dfsw_HOOK
|
||||
// gets all the taint labels for the arguments.
|
||||
@ -34,14 +46,10 @@
|
||||
// * The __dfsw_* functions (implemented in this file) record the
|
||||
// parameters (i.e. the application data and the corresponding taint labels)
|
||||
// in a global state.
|
||||
// * Fuzzer::MutateWithDFSan() tries to use the data recorded by __dfsw_*
|
||||
// hooks to guide the fuzzing towards new application states.
|
||||
// For example if 4 bytes of data that derive from input bytes {4,5,6,7}
|
||||
// are compared with a constant 12345 and the comparison always yields
|
||||
// the same result, we try to insert 12345, 12344, 12346 into bytes
|
||||
// {4,5,6,7} of the next fuzzed inputs.
|
||||
// * Fuzzer::ApplyTraceBasedMutation() tries to use the data recorded
|
||||
// by __dfsw_* hooks to guide the fuzzing towards new application states.
|
||||
//
|
||||
// This code does not function when DFSan is not linked in.
|
||||
// Parts of this code will not function when DFSan is not linked in.
|
||||
// Instead of using ifdefs and thus requiring a separate build of lib/Fuzzer
|
||||
// we redeclare the dfsan_* interface functions as weak and check if they
|
||||
// are nullptr before calling.
|
||||
@ -53,7 +61,7 @@
|
||||
// like test/dfsan/DFSanSimpleCmpTest.cpp.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/* Example of manual usage:
|
||||
/* Example of manual usage (-fsanitize=dataflow is optional):
|
||||
(
|
||||
cd $LLVM/lib/Fuzzer/
|
||||
clang -fPIC -c -g -O2 -std=c++11 Fuzzer*.cpp
|
||||
@ -168,9 +176,9 @@ struct TraceBasedMutation {
|
||||
uint64_t Data;
|
||||
};
|
||||
|
||||
class DFSanState {
|
||||
class TraceState {
|
||||
public:
|
||||
DFSanState(const Fuzzer::FuzzingOptions &Options, const Unit &CurrentUnit)
|
||||
TraceState(const Fuzzer::FuzzingOptions &Options, const Unit &CurrentUnit)
|
||||
: Options(Options), CurrentUnit(CurrentUnit) {}
|
||||
|
||||
LabelRange GetLabelRange(dfsan_label L);
|
||||
@ -208,7 +216,7 @@ class DFSanState {
|
||||
const Unit &CurrentUnit;
|
||||
};
|
||||
|
||||
LabelRange DFSanState::GetLabelRange(dfsan_label L) {
|
||||
LabelRange TraceState::GetLabelRange(dfsan_label L) {
|
||||
LabelRange &LR = LabelRanges[L];
|
||||
if (LR.Beg < LR.End || L == 0)
|
||||
return LR;
|
||||
@ -218,7 +226,7 @@ LabelRange DFSanState::GetLabelRange(dfsan_label L) {
|
||||
return LR = LabelRange::Singleton(LI);
|
||||
}
|
||||
|
||||
void DFSanState::ApplyTraceBasedMutation(size_t Idx, fuzzer::Unit *U) {
|
||||
void TraceState::ApplyTraceBasedMutation(size_t Idx, fuzzer::Unit *U) {
|
||||
assert(Idx < Mutations.size());
|
||||
auto &M = Mutations[Idx];
|
||||
if (Options.Verbosity >= 3)
|
||||
@ -227,7 +235,7 @@ void DFSanState::ApplyTraceBasedMutation(size_t Idx, fuzzer::Unit *U) {
|
||||
memcpy(U->data() + M.Pos, &M.Data, M.Size);
|
||||
}
|
||||
|
||||
void DFSanState::DFSanCmpCallback(uintptr_t PC, size_t CmpSize, size_t CmpType,
|
||||
void TraceState::DFSanCmpCallback(uintptr_t PC, size_t CmpSize, size_t CmpType,
|
||||
uint64_t Arg1, uint64_t Arg2, dfsan_label L1,
|
||||
dfsan_label L2) {
|
||||
assert(ReallyHaveDFSan());
|
||||
@ -263,7 +271,7 @@ void DFSanState::DFSanCmpCallback(uintptr_t PC, size_t CmpSize, size_t CmpType,
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
int DFSanState::TryToAddDesiredData(uint64_t PresentData, uint64_t DesiredData,
|
||||
int TraceState::TryToAddDesiredData(uint64_t PresentData, uint64_t DesiredData,
|
||||
size_t DataSize) {
|
||||
int Res = 0;
|
||||
const uint8_t *Beg = CurrentUnit.data();
|
||||
@ -284,7 +292,7 @@ int DFSanState::TryToAddDesiredData(uint64_t PresentData, uint64_t DesiredData,
|
||||
return Res;
|
||||
}
|
||||
|
||||
void DFSanState::TraceCmpCallback(size_t CmpSize, size_t CmpType, uint64_t Arg1,
|
||||
void TraceState::TraceCmpCallback(size_t CmpSize, size_t CmpType, uint64_t Arg1,
|
||||
uint64_t Arg2) {
|
||||
if (!Options.UseTraces) return;
|
||||
int Added = 0;
|
||||
@ -298,29 +306,29 @@ void DFSanState::TraceCmpCallback(size_t CmpSize, size_t CmpType, uint64_t Arg1,
|
||||
}
|
||||
}
|
||||
|
||||
static DFSanState *DFSan;
|
||||
static TraceState *TS;
|
||||
|
||||
void Fuzzer::StartTraceRecording() {
|
||||
if (!DFSan) return;
|
||||
DFSan->StartTraceRecording();
|
||||
if (!TS) return;
|
||||
TS->StartTraceRecording();
|
||||
}
|
||||
|
||||
size_t Fuzzer::StopTraceRecording() {
|
||||
if (!DFSan) return 0;
|
||||
return DFSan->StopTraceRecording();
|
||||
if (!TS) return 0;
|
||||
return TS->StopTraceRecording();
|
||||
}
|
||||
|
||||
void Fuzzer::ApplyTraceBasedMutation(size_t Idx, Unit *U) {
|
||||
assert(DFSan);
|
||||
DFSan->ApplyTraceBasedMutation(Idx, U);
|
||||
assert(TS);
|
||||
TS->ApplyTraceBasedMutation(Idx, U);
|
||||
}
|
||||
|
||||
void Fuzzer::InitializeDFSan() {
|
||||
if (!Options.UseDFSan) return;
|
||||
DFSan = new DFSanState(Options, CurrentUnit);
|
||||
void Fuzzer::InitializeTraceState() {
|
||||
if (!Options.UseTraces && !Options.UseDFSan) return;
|
||||
TS = new TraceState(Options, CurrentUnit);
|
||||
CurrentUnit.resize(Options.MaxLen);
|
||||
// The rest really requires DFSan.
|
||||
if (!ReallyHaveDFSan()) return;
|
||||
if (!ReallyHaveDFSan() || !Options.UseDFSan) return;
|
||||
for (size_t i = 0; i < static_cast<size_t>(Options.MaxLen); i++) {
|
||||
dfsan_label L = dfsan_create_label("input", (void*)(i + 1));
|
||||
// We assume that no one else has called dfsan_create_label before.
|
||||
@ -331,22 +339,24 @@ void Fuzzer::InitializeDFSan() {
|
||||
|
||||
} // namespace fuzzer
|
||||
|
||||
using fuzzer::DFSan;
|
||||
using fuzzer::TS;
|
||||
|
||||
extern "C" {
|
||||
void __dfsw___sanitizer_cov_trace_cmp(uint64_t SizeAndType, uint64_t Arg1,
|
||||
uint64_t Arg2, dfsan_label L0,
|
||||
dfsan_label L1, dfsan_label L2) {
|
||||
assert(TS);
|
||||
assert(L0 == 0);
|
||||
uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
|
||||
uint64_t CmpSize = (SizeAndType >> 32) / 8;
|
||||
uint64_t Type = (SizeAndType << 32) >> 32;
|
||||
DFSan->DFSanCmpCallback(PC, CmpSize, Type, Arg1, Arg2, L1, L2);
|
||||
TS->DFSanCmpCallback(PC, CmpSize, Type, Arg1, Arg2, L1, L2);
|
||||
}
|
||||
|
||||
void dfsan_weak_hook_memcmp(void *caller_pc, const void *s1, const void *s2,
|
||||
size_t n, dfsan_label s1_label,
|
||||
dfsan_label s2_label, dfsan_label n_label) {
|
||||
assert(TS);
|
||||
uintptr_t PC = reinterpret_cast<uintptr_t>(caller_pc);
|
||||
uint64_t S1 = 0, S2 = 0;
|
||||
// Simplification: handle only first 8 bytes.
|
||||
@ -354,15 +364,15 @@ void dfsan_weak_hook_memcmp(void *caller_pc, const void *s1, const void *s2,
|
||||
memcpy(&S2, s2, std::min(n, sizeof(S2)));
|
||||
dfsan_label L1 = dfsan_read_label(s1, n);
|
||||
dfsan_label L2 = dfsan_read_label(s2, n);
|
||||
DFSan->DFSanCmpCallback(PC, n, fuzzer::ICMP_EQ, S1, S2, L1, L2);
|
||||
TS->DFSanCmpCallback(PC, n, fuzzer::ICMP_EQ, S1, S2, L1, L2);
|
||||
}
|
||||
|
||||
void __sanitizer_cov_trace_cmp(uint64_t SizeAndType, uint64_t Arg1,
|
||||
uint64_t Arg2) {
|
||||
if (!DFSan) return;
|
||||
if (!TS) return;
|
||||
uint64_t CmpSize = (SizeAndType >> 32) / 8;
|
||||
uint64_t Type = (SizeAndType << 32) >> 32;
|
||||
DFSan->TraceCmpCallback(CmpSize, Type, Arg1, Arg2);
|
||||
TS->TraceCmpCallback(CmpSize, Type, Arg1, Arg2);
|
||||
}
|
||||
|
||||
} // extern "C"
|
Loading…
x
Reference in New Issue
Block a user