From f7aa7e6f4989c7361a74baf3aadaa7f8f1e1c111 Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Fri, 31 Jul 2015 20:58:55 +0000 Subject: [PATCH 1/1] [libFuzzer] make sure that 2-byte arguments of switch() are handled properly git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@243781 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Fuzzer/FuzzerTraceState.cpp | 40 ++++++++++++++++++++++++--------- lib/Fuzzer/test/SwitchTest.cpp | 23 +++++++++++++++++-- lib/Fuzzer/test/fuzzer.test | 2 +- 3 files changed, 52 insertions(+), 13 deletions(-) diff --git a/lib/Fuzzer/FuzzerTraceState.cpp b/lib/Fuzzer/FuzzerTraceState.cpp index 5eae2ec8882..f0537c00580 100644 --- a/lib/Fuzzer/FuzzerTraceState.cpp +++ b/lib/Fuzzer/FuzzerTraceState.cpp @@ -233,7 +233,7 @@ class TraceState { size_t StopTraceRecording(FuzzerRandomBase &Rand) { RecordingTraces = false; std::random_shuffle(Mutations.begin(), Mutations.end(), Rand); - return Mutations.size(); + return std::min(Mutations.size(), 128UL); } void ApplyTraceBasedMutation(size_t Idx, fuzzer::Unit *U); @@ -307,16 +307,23 @@ void TraceState::DFSanSwitchCallback(uint64_t PC, size_t ValSizeInBits, if (!L) return; // Not actionable. LabelRange LR = GetLabelRange(L); size_t ValSize = ValSizeInBits / 8; - for (size_t Pos = LR.Beg; Pos + ValSize <= LR.End; Pos++) { - for (size_t i = 0; i < NumCases; i++) { + bool TryShort = IsTwoByteData(Val); + for (size_t i = 0; i < NumCases; i++) + TryShort &= IsTwoByteData(Cases[i]); + + for (size_t Pos = LR.Beg; Pos + ValSize <= LR.End; Pos++) + for (size_t i = 0; i < NumCases; i++) Mutations.push_back({Pos, ValSize, Cases[i]}); - Mutations.push_back({Pos, ValSize, Cases[i] + 1}); - Mutations.push_back({Pos, ValSize, Cases[i] - 1}); - } - } + + if (TryShort) + for (size_t Pos = LR.Beg; Pos + 2 <= LR.End; Pos++) + for (size_t i = 0; i < NumCases; i++) + Mutations.push_back({Pos, 2, Cases[i]}); + if (Options.Verbosity >= 3) - Printf("DFSanSwitchCallback: PC %lx Val %zd # %zd L %d\n", PC, Val, - NumCases, L); + Printf("DFSanSwitchCallback: PC %lx Val %zd SZ %zd # %zd L %d: {%d, %d} " + "TryShort %d\n", + PC, Val, ValSize, NumCases, L, LR.Beg, LR.End, TryShort); } int TraceState::TryToAddDesiredData(uint64_t PresentData, uint64_t DesiredData, @@ -365,8 +372,21 @@ void TraceState::TraceSwitchCallback(uintptr_t PC, size_t ValSizeInBits, uint64_t Val, size_t NumCases, uint64_t *Cases) { if (!RecordingTraces) return; + size_t ValSize = ValSizeInBits / 8; + bool TryShort = IsTwoByteData(Val); for (size_t i = 0; i < NumCases; i++) - TryToAddDesiredData(Val, Cases[i], ValSizeInBits / 8); + TryShort &= IsTwoByteData(Cases[i]); + + if (Options.Verbosity >= 3) + Printf("TraceSwitch: %p %zd # %zd; TryShort %d\n", PC, Val, NumCases, + TryShort); + + for (size_t i = 0; i < NumCases; i++) { + TryToAddDesiredData(Val, Cases[i], ValSize); + if (TryShort) + TryToAddDesiredData(Val, Cases[i], 2); + } + } static TraceState *TS; diff --git a/lib/Fuzzer/test/SwitchTest.cpp b/lib/Fuzzer/test/SwitchTest.cpp index 0f2319b2cc9..9f921fb6098 100644 --- a/lib/Fuzzer/test/SwitchTest.cpp +++ b/lib/Fuzzer/test/SwitchTest.cpp @@ -25,9 +25,28 @@ bool Switch(const uint8_t *Data, size_t Size) { return false; } +bool ShortSwitch(const uint8_t *Data, size_t Size) { + short X; + if (Size < sizeof(short)) return false; + memcpy(&X, Data, sizeof(short)); + switch(X) { + case 42: Sink = __LINE__; break; + case 402: Sink = __LINE__; break; + case 4002: Sink = __LINE__; break; + case 5002: Sink = __LINE__; break; + case 7002: Sink = __LINE__; break; + case 9002: Sink = __LINE__; break; + case 14002: Sink = __LINE__; break; + case 21402: return true; + } + return false; +} + extern "C" void LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { - if (Switch(Data, Size) && Size >= 12 && - Switch(Data + 4, Size - 4)) { + if (Size >= 4 && Switch(Data, Size) && + Size >= 12 && Switch(Data + 4, Size - 4) && + Size >= 14 && ShortSwitch(Data + 12, 2) + ) { fprintf(stderr, "BINGO; Found the target, exiting\n"); exit(1); } diff --git a/lib/Fuzzer/test/fuzzer.test b/lib/Fuzzer/test/fuzzer.test index 63cb9573efa..bfb5849bba8 100644 --- a/lib/Fuzzer/test/fuzzer.test +++ b/lib/Fuzzer/test/fuzzer.test @@ -32,5 +32,5 @@ Done1000000: Done 1000000 runs in RUN: not LLVMFuzzer-StrncmpTest -use_traces=1 -seed=1 -runs=10000 2>&1 | FileCheck %s RUN: LLVMFuzzer-StrncmpTest -seed=1 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000 -RUN: not LLVMFuzzer-SwitchTest -use_traces=1 -seed=1 -runs=100000 2>&1 | FileCheck %s +RUN: not LLVMFuzzer-SwitchTest -use_traces=1 -seed=1 -runs=1000000 2>&1 | FileCheck %s RUN: LLVMFuzzer-SwitchTest -seed=1 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000 -- 2.34.1