From: Kostya Serebryany Date: Fri, 9 Sep 2016 01:17:03 +0000 (+0000) Subject: [libFuzzer] remove use_traces=1 since use_value_profile seems to be strictly better X-Git-Tag: llvmorg-4.0.0-rc1~10264 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5c04bd250e84ed67624896550b65236a9170efcc;p=platform%2Fupstream%2Fllvm.git [libFuzzer] remove use_traces=1 since use_value_profile seems to be strictly better llvm-svn: 281007 --- diff --git a/llvm/docs/LibFuzzer.rst b/llvm/docs/LibFuzzer.rst index 9074cd8..6991908 100644 --- a/llvm/docs/LibFuzzer.rst +++ b/llvm/docs/LibFuzzer.rst @@ -240,7 +240,7 @@ The most important command line options are: directory. Defaults to 0. This flag can be used to minimize a corpus. ``-minimize_crash`` If 1, minimizes the provided crash input. - Use with -runs=N or -max_total_time=N to limit the number attempts. + Use with -runs=N or -max_total_time=N to limit the number of attempts. ``-reload`` If set to 1 (the default), the corpus directory is re-read periodically to check for new inputs; this allows detection of new inputs that were discovered @@ -261,8 +261,6 @@ The most important command line options are: blocks are hit; defaults to 1. ``-use_value_profile`` Use `value profile`_ to guide corpus expansion; defaults to 0. -``-use_traces`` - Use instruction traces (experimental, defaults to 0); see `Data-flow-guided fuzzing`_. ``-only_ascii`` If 1, generate only ASCII (``isprint``+``isspace``) inputs. Defaults to 0. ``-artifact_prefix`` @@ -619,19 +617,6 @@ but there are two downsides. First, the extra instrumentation may bring up to 2x additional slowdown. Second, the corpus may grow by several times. - -Data-flow-guided fuzzing ------------------------- - -*EXPERIMENTAL*. -With an additional compiler flag ``-fsanitize-coverage=trace-cmp`` (see SanitizerCoverageTraceDataFlow_) -and extra run-time flag ``-use_traces=1`` the fuzzer will try to apply *data-flow-guided fuzzing*. -That is, the fuzzer will record the inputs to comparison instructions, switch statements, -and several libc functions (``memcmp``, ``strcmp``, ``strncmp``, etc). -It will later use those recorded inputs during mutations. - -This mode can be combined with DataFlowSanitizer_ to achieve better sensitivity. - Fuzzer-friendly build mode --------------------------- Sometimes the code under test is not fuzzing-friendly. Examples: @@ -922,7 +907,6 @@ Trophies .. _AFL: http://lcamtuf.coredump.cx/afl/ .. _SanitizerCoverage: http://clang.llvm.org/docs/SanitizerCoverage.html .. _SanitizerCoverageTraceDataFlow: http://clang.llvm.org/docs/SanitizerCoverage.html#tracing-data-flow -.. _DataFlowSanitizer: http://clang.llvm.org/docs/DataFlowSanitizer.html .. _AddressSanitizer: http://clang.llvm.org/docs/AddressSanitizer.html .. _LeakSanitizer: http://clang.llvm.org/docs/LeakSanitizer.html .. _Heartbleed: http://en.wikipedia.org/wiki/Heartbleed diff --git a/llvm/lib/Fuzzer/FuzzerDriver.cpp b/llvm/lib/Fuzzer/FuzzerDriver.cpp index 5d0c5a5..94045d5 100644 --- a/llvm/lib/Fuzzer/FuzzerDriver.cpp +++ b/llvm/lib/Fuzzer/FuzzerDriver.cpp @@ -395,7 +395,6 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) { Options.MutateDepth = Flags.mutate_depth; Options.UseCounters = Flags.use_counters; Options.UseIndirCalls = Flags.use_indir_calls; - Options.UseTraces = Flags.use_traces; Options.UseMemcmp = Flags.use_memcmp; Options.UseMemmem = Flags.use_memmem; Options.ShuffleAtStartUp = Flags.shuffle; diff --git a/llvm/lib/Fuzzer/FuzzerFlags.def b/llvm/lib/Fuzzer/FuzzerFlags.def index bae00ff..e2e490e 100644 --- a/llvm/lib/Fuzzer/FuzzerFlags.def +++ b/llvm/lib/Fuzzer/FuzzerFlags.def @@ -43,7 +43,6 @@ FUZZER_FLAG_INT(minimize_crash, 0, "If 1, minimizes the provided" FUZZER_FLAG_INT(minimize_crash_internal_step, 0, "internal flag") FUZZER_FLAG_INT(use_counters, 1, "Use coverage counters") FUZZER_FLAG_INT(use_indir_calls, 1, "Use indirect caller-callee counters") -FUZZER_FLAG_INT(use_traces, 0, "Experimental: use instruction traces") FUZZER_FLAG_INT(use_memcmp, 1, "Use hints from intercepting memcmp, strcmp, etc") FUZZER_FLAG_INT(use_memmem, 1, diff --git a/llvm/lib/Fuzzer/FuzzerInternal.h b/llvm/lib/Fuzzer/FuzzerInternal.h index bac83cf..e2a5b1f 100644 --- a/llvm/lib/Fuzzer/FuzzerInternal.h +++ b/llvm/lib/Fuzzer/FuzzerInternal.h @@ -229,7 +229,6 @@ struct FuzzingOptions { int MutateDepth = 5; bool UseCounters = false; bool UseIndirCalls = true; - bool UseTraces = false; bool UseMemcmp = true; bool UseMemmem = true; bool UseFullCoverageSet = false; diff --git a/llvm/lib/Fuzzer/FuzzerTraceState.cpp b/llvm/lib/Fuzzer/FuzzerTraceState.cpp index 63dd5a6..77946ef 100644 --- a/llvm/lib/Fuzzer/FuzzerTraceState.cpp +++ b/llvm/lib/Fuzzer/FuzzerTraceState.cpp @@ -170,7 +170,6 @@ struct TraceBasedMutation { }; // Declared as static globals for faster checks inside the hooks. -static bool RecordingTraces = false; static bool RecordingMemcmp = false; static bool RecordingMemmem = false; static bool RecordingValueProfile = false; @@ -209,9 +208,8 @@ public: const uint8_t *DesiredData, size_t DataSize); void StartTraceRecording() { - if (!Options.UseTraces && !Options.UseMemcmp) + if (!Options.UseMemcmp) return; - RecordingTraces = Options.UseTraces; RecordingMemcmp = Options.UseMemcmp; RecordingMemmem = Options.UseMemmem; NumMutations = 0; @@ -220,9 +218,8 @@ public: } void StopTraceRecording() { - if (!RecordingTraces && !RecordingMemcmp) + if (!RecordingMemcmp) return; - RecordingTraces = false; RecordingMemcmp = false; for (size_t i = 0; i < NumMutations; i++) { auto &M = Mutations[i]; @@ -332,7 +329,7 @@ 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()); - if (!RecordingTraces || !F->InFuzzingThread()) return; + if (!F->InFuzzingThread()) return; if (L1 == 0 && L2 == 0) return; // Not actionable. if (L1 != 0 && L2 != 0) @@ -381,7 +378,7 @@ void TraceState::DFSanSwitchCallback(uint64_t PC, size_t ValSizeInBits, uint64_t Val, size_t NumCases, uint64_t *Cases, dfsan_label L) { assert(ReallyHaveDFSan()); - if (!RecordingTraces || !F->InFuzzingThread()) return; + if (!F->InFuzzingThread()) return; if (!L) return; // Not actionable. LabelRange LR = GetLabelRange(L); size_t ValSize = ValSizeInBits / 8; @@ -451,7 +448,7 @@ int TraceState::TryToAddDesiredData(const uint8_t *PresentData, void TraceState::TraceCmpCallback(uintptr_t PC, size_t CmpSize, size_t CmpType, uint64_t Arg1, uint64_t Arg2) { - if (!RecordingTraces || !F->InFuzzingThread()) return; + if (!F->InFuzzingThread()) return; if ((CmpType == ICMP_EQ || CmpType == ICMP_NE) && Arg1 == Arg2) return; // No reason to mutate. int Added = 0; @@ -482,7 +479,7 @@ void TraceState::TraceMemcmpCallback(size_t CmpSize, const uint8_t *Data1, void TraceState::TraceSwitchCallback(uintptr_t PC, size_t ValSizeInBits, uint64_t Val, size_t NumCases, uint64_t *Cases) { - if (!RecordingTraces || !F->InFuzzingThread()) return; + if (F->InFuzzingThread()) return; size_t ValSize = ValSizeInBits / 8; bool TryShort = IsTwoByteData(Val); for (size_t i = 0; i < NumCases; i++) @@ -512,7 +509,7 @@ void Fuzzer::StopTraceRecording() { } void Fuzzer::AssignTaintLabels(uint8_t *Data, size_t Size) { - if (!Options.UseTraces && !Options.UseMemcmp) return; + if (!Options.UseMemcmp) return; if (!ReallyHaveDFSan()) return; TS->EnsureDfsanLabels(Size); for (size_t i = 0; i < Size; i++) @@ -520,7 +517,7 @@ void Fuzzer::AssignTaintLabels(uint8_t *Data, size_t Size) { } void Fuzzer::InitializeTraceState() { - if (!Options.UseTraces && !Options.UseMemcmp) return; + if (!Options.UseMemcmp) return; TS = new TraceState(MD, Options, this); } @@ -603,7 +600,6 @@ static void AddValueForSingleVal(void *PCptr, uintptr_t Val) { } // namespace fuzzer using fuzzer::TS; -using fuzzer::RecordingTraces; using fuzzer::RecordingMemcmp; using fuzzer::RecordingValueProfile; @@ -611,21 +607,11 @@ 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) { - if (!RecordingTraces) return; - assert(L0 == 0); - uintptr_t PC = reinterpret_cast(__builtin_return_address(0)); - uint64_t CmpSize = (SizeAndType >> 32) / 8; - uint64_t Type = (SizeAndType << 32) >> 32; - TS->DFSanCmpCallback(PC, CmpSize, Type, Arg1, Arg2, L1, L2); } #define DFSAN_CMP_CALLBACK(N) \ void __dfsw___sanitizer_cov_trace_cmp##N(uint64_t Arg1, uint64_t Arg2, \ dfsan_label L1, dfsan_label L2) { \ - if (RecordingTraces) \ - TS->DFSanCmpCallback( \ - reinterpret_cast(__builtin_return_address(0)), N, \ - fuzzer::ICMP_EQ, Arg1, Arg2, L1, L2); \ } DFSAN_CMP_CALLBACK(1) @@ -636,9 +622,6 @@ DFSAN_CMP_CALLBACK(8) void __dfsw___sanitizer_cov_trace_switch(uint64_t Val, uint64_t *Cases, dfsan_label L1, dfsan_label L2) { - if (!RecordingTraces) return; - uintptr_t PC = reinterpret_cast(__builtin_return_address(0)); - TS->DFSanSwitchCallback(PC, Cases[1], Val, Cases[0], Cases+2, L1); } void dfsan_weak_hook_memcmp(void *caller_pc, const void *s1, const void *s2, @@ -750,50 +733,30 @@ void __sanitizer_weak_hook_memmem(void *called_pc, const void *s1, size_t len1, __attribute__((visibility("default"))) void __sanitizer_cov_trace_cmp(uint64_t SizeAndType, uint64_t Arg1, uint64_t Arg2) { - if (RecordingTraces) { - uintptr_t PC = reinterpret_cast(__builtin_return_address(0)); - uint64_t CmpSize = (SizeAndType >> 32) / 8; - uint64_t Type = (SizeAndType << 32) >> 32; - TS->TraceCmpCallback(PC, CmpSize, Type, Arg1, Arg2); - } if (RecordingValueProfile) fuzzer::AddValueForCmp(__builtin_return_address(0), Arg1, Arg2); } -// Adding if(RecordingTraces){...} slows down the VP callbacks. -// Once we prove that VP is as strong as traces, delete this. -#define MAYBE_RECORD_TRACE(N) \ - if (RecordingTraces) { \ - uintptr_t PC = reinterpret_cast(__builtin_return_address(0)); \ - TS->TraceCmpCallback(PC, N, fuzzer::ICMP_EQ, Arg1, Arg2); \ - } - __attribute__((visibility("default"))) void __sanitizer_cov_trace_cmp8(uint64_t Arg1, int64_t Arg2) { fuzzer::AddValueForCmp(__builtin_return_address(0), Arg1, Arg2); - MAYBE_RECORD_TRACE(8); } __attribute__((visibility("default"))) void __sanitizer_cov_trace_cmp4(uint32_t Arg1, int32_t Arg2) { fuzzer::AddValueForCmp(__builtin_return_address(0), Arg1, Arg2); - MAYBE_RECORD_TRACE(4); } __attribute__((visibility("default"))) void __sanitizer_cov_trace_cmp2(uint16_t Arg1, int16_t Arg2) { fuzzer::AddValueForCmp(__builtin_return_address(0), Arg1, Arg2); - MAYBE_RECORD_TRACE(2); } __attribute__((visibility("default"))) void __sanitizer_cov_trace_cmp1(uint8_t Arg1, int8_t Arg2) { fuzzer::AddValueForCmp(__builtin_return_address(0), Arg1, Arg2); - MAYBE_RECORD_TRACE(1); } __attribute__((visibility("default"))) void __sanitizer_cov_trace_switch(uint64_t Val, uint64_t *Cases) { - if (!RecordingTraces) return; - uintptr_t PC = reinterpret_cast(__builtin_return_address(0)); - TS->TraceSwitchCallback(PC, Cases[1], Val, Cases[0], Cases + 2); + // TODO(kcc): support value profile here. } __attribute__((visibility("default"))) diff --git a/llvm/lib/Fuzzer/test/fuzzer-dfsan.test b/llvm/lib/Fuzzer/test/fuzzer-dfsan.test index 5bd5c0f..a1a2248 100644 --- a/llvm/lib/Fuzzer/test/fuzzer-dfsan.test +++ b/llvm/lib/Fuzzer/test/fuzzer-dfsan.test @@ -4,13 +4,8 @@ CHECK2: BINGO CHECK3: BINGO CHECK4: BINGO -CHECK_DFSanCmpCallback: DFSanCmpCallback: PC -CHECK_DFSanSwitchCallback: DFSanSwitchCallback: PC CHECK_DFSanMemcmpCallback: DFSanMemcmpCallback: Pos -RUN: not LLVMFuzzer-SimpleCmpTest-DFSan -use_traces=1 -seed=1 -runs=10000000 -timeout=5 2>&1 | FileCheck %s --check-prefix=CHECK1 -RUN: LLVMFuzzer-SimpleCmpTest-DFSan -use_traces=1 -seed=1 -runs=100 -timeout=5 -verbosity=3 2>&1 | FileCheck %s -check-prefix=CHECK_DFSanCmpCallback - RUN: not LLVMFuzzer-MemcmpTest-DFSan -use_traces=1 -seed=1 -runs=100000 -timeout=5 2>&1 | FileCheck %s --check-prefix=CHECK2 RUN: LLVMFuzzer-MemcmpTest-DFSan -use_traces=1 -seed=1 -runs=2 -timeout=5 -verbosity=3 2>&1 | FileCheck %s -check-prefix=CHECK_DFSanMemcmpCallback @@ -19,6 +14,3 @@ RUN: LLVMFuzzer-StrncmpTest-DFSan -use_traces=1 -seed=1 -runs=2 -timeout=5 -verb RUN: not LLVMFuzzer-StrcmpTest-DFSan -use_traces=1 -seed=1 -runs=10000 -timeout=5 2>&1 | FileCheck %s --check-prefix=CHECK3 RUN: LLVMFuzzer-StrcmpTest-DFSan -use_traces=1 -seed=1 -runs=2 -timeout=5 -verbosity=3 2>&1 | FileCheck %s -check-prefix=CHECK_DFSanMemcmpCallback - -RUN: not LLVMFuzzer-SwitchTest-DFSan -use_traces=1 -seed=1 -runs=100000 -timeout=5 2>&1 | FileCheck %s --check-prefix=CHECK4 -RUN: LLVMFuzzer-SwitchTest-DFSan -use_traces=1 -seed=1 -runs=2 -timeout=5 -verbosity=3 2>&1 | FileCheck %s -check-prefix=CHECK_DFSanSwitchCallback diff --git a/llvm/lib/Fuzzer/test/fuzzer-traces.test b/llvm/lib/Fuzzer/test/fuzzer-traces.test deleted file mode 100644 index 13f82ca..0000000 --- a/llvm/lib/Fuzzer/test/fuzzer-traces.test +++ /dev/null @@ -1,10 +0,0 @@ -CHECK: BINGO -Done1000000: Done 1000000 runs in -Done2000000: Done 2000000 runs in -RUN: not LLVMFuzzer-SimpleCmpTest -use_traces=1 -seed=1 -runs=10000001 2>&1 | FileCheck %s - -RUN: not LLVMFuzzer-SwitchTest -use_traces=1 -seed=6 -runs=1000002 2>&1 | FileCheck %s -RUN: LLVMFuzzer-SwitchTest -seed=7 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000 - -RUN: not LLVMFuzzer-SimpleHashTest -use_traces=1 -seed=8 -runs=2000000 -max_len=16 2>&1 | FileCheck %s -RUN: LLVMFuzzer-SimpleHashTest -seed=9 -runs=2000000 -max_len=16 2>&1 | FileCheck %s --check-prefix=Done2000000