From be0ed59cdc9b765869b0a2355b185809507a02db Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Thu, 22 Sep 2016 23:16:36 +0000 Subject: [PATCH] [libFuzzer] simplify the crash minimizer; split MaxLen into two: MaxInputLen and MaxMutationLen, allow MaxMutationLen to be less than MaxInputLen llvm-svn: 282211 --- llvm/lib/Fuzzer/FuzzerDriver.cpp | 14 +++++-------- llvm/lib/Fuzzer/FuzzerInternal.h | 8 ++++++-- llvm/lib/Fuzzer/FuzzerLoop.cpp | 43 +++++++++++++++++++++++----------------- 3 files changed, 36 insertions(+), 29 deletions(-) diff --git a/llvm/lib/Fuzzer/FuzzerDriver.cpp b/llvm/lib/Fuzzer/FuzzerDriver.cpp index f7896eb..24f2bed 100644 --- a/llvm/lib/Fuzzer/FuzzerDriver.cpp +++ b/llvm/lib/Fuzzer/FuzzerDriver.cpp @@ -342,13 +342,9 @@ int MinimizeCrashInputInternalStep(Fuzzer *F, InputCorpus *Corpus) { Unit U = FileToVector(InputFilePath); assert(U.size() > 2); Printf("INFO: Starting MinimizeCrashInputInternalStep: %zd\n", U.size()); - Unit X(U.size() - 1); - for (size_t I = 0; I < U.size(); I++) { - std::copy(U.begin(), U.begin() + I, X.begin()); - std::copy(U.begin() + I + 1, U.end(), X.begin() + I); - Corpus->AddToCorpus(X, nullptr, 0); - } - F->SetMaxLen(U.size() - 1); + Corpus->AddToCorpus(U, nullptr, 0); + F->SetMaxInputLen(U.size()); + F->SetMaxMutationLen(U.size() - 1); F->Loop(); Printf("INFO: Done MinimizeCrashInputInternalStep, no crashes found\n"); exit(0); @@ -492,7 +488,7 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) { if (Flags.merge) { if (Options.MaxLen == 0) - F.SetMaxLen(kMaxSaneLen); + F.SetMaxInputLen(kMaxSaneLen); F.Merge(*Inputs); exit(0); } @@ -509,7 +505,7 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) { size_t MaxLen = 0; for (auto &U : InitialCorpus) MaxLen = std::max(U.size(), MaxLen); - F.SetMaxLen(std::min(std::max(kMinDefaultLen, MaxLen), kMaxSaneLen)); + F.SetMaxInputLen(std::min(std::max(kMinDefaultLen, MaxLen), kMaxSaneLen)); } if (InitialCorpus.empty()) { diff --git a/llvm/lib/Fuzzer/FuzzerInternal.h b/llvm/lib/Fuzzer/FuzzerInternal.h index ccb583c..7c92ac8 100644 --- a/llvm/lib/Fuzzer/FuzzerInternal.h +++ b/llvm/lib/Fuzzer/FuzzerInternal.h @@ -95,7 +95,8 @@ public: UnitVector FindExtraUnits(const UnitVector &Initial, const UnitVector &Extra); MutationDispatcher &GetMD() { return MD; } void PrintFinalStats(); - void SetMaxLen(size_t MaxLen); + void SetMaxInputLen(size_t MaxInputLen); + void SetMaxMutationLen(size_t MaxMutationLen); void RssLimitCallback(); // Public for tests. @@ -142,7 +143,7 @@ private: void PrepareCounters(Fuzzer::Coverage *C); bool RecordMaxCoverage(Fuzzer::Coverage *C); - void LazyAllocateCurrentUnitData(); + void AllocateCurrentUnitData(); uint8_t *CurrentUnitData = nullptr; std::atomic CurrentUnitSize; uint8_t BaseSha1[kSHA1NumBytes]; // Checksum of the base unit. @@ -166,6 +167,9 @@ private: // Maximum recorded coverage. Coverage MaxCoverage; + size_t MaxInputLen = 0; + size_t MaxMutationLen = 0; + // For -print_pcs uintptr_t* PcBuffer = nullptr; size_t PcBufferLen = 0; diff --git a/llvm/lib/Fuzzer/FuzzerLoop.cpp b/llvm/lib/Fuzzer/FuzzerLoop.cpp index 0955254..2e2d38c 100644 --- a/llvm/lib/Fuzzer/FuzzerLoop.cpp +++ b/llvm/lib/Fuzzer/FuzzerLoop.cpp @@ -179,13 +179,15 @@ Fuzzer::Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD, TPC.PrintModuleInfo(); if (!Options.OutputCorpus.empty() && Options.Reload) EpochOfLastReadOfOutputCorpus = GetEpoch(Options.OutputCorpus); + MaxInputLen = MaxMutationLen = Options.MaxLen; + AllocateCurrentUnitData(); } Fuzzer::~Fuzzer() { } -void Fuzzer::LazyAllocateCurrentUnitData() { - if (CurrentUnitData || Options.MaxLen == 0) return; - CurrentUnitData = new uint8_t[Options.MaxLen]; +void Fuzzer::AllocateCurrentUnitData() { + if (CurrentUnitData || MaxInputLen == 0) return; + CurrentUnitData = new uint8_t[MaxInputLen]; } void Fuzzer::SetDeathCallback() { @@ -349,11 +351,18 @@ void Fuzzer::PrintFinalStats() { Printf("stat::peak_rss_mb: %zd\n", GetPeakRSSMb()); } -void Fuzzer::SetMaxLen(size_t MaxLen) { - assert(Options.MaxLen == 0); // Can only reset MaxLen from 0 to non-0. - assert(MaxLen); - Options.MaxLen = MaxLen; - Printf("INFO: -max_len is not provided, using %zd\n", Options.MaxLen); +void Fuzzer::SetMaxInputLen(size_t MaxInputLen) { + assert(this->MaxInputLen == 0); // Can only reset MaxInputLen from 0 to non-0. + assert(MaxInputLen); + this->MaxInputLen = MaxInputLen; + this->MaxMutationLen = MaxInputLen; + AllocateCurrentUnitData(); + Printf("INFO: -max_len is not provided, using %zd\n", MaxInputLen); +} + +void Fuzzer::SetMaxMutationLen(size_t MaxMutationLen) { + assert(MaxMutationLen && MaxMutationLen <= MaxInputLen); + this->MaxMutationLen = MaxMutationLen; } void Fuzzer::RereadOutputCorpus(size_t MaxSize) { @@ -445,7 +454,6 @@ size_t Fuzzer::GetCurrentUnitInFuzzingThead(const uint8_t **Data) const { void Fuzzer::ExecuteCallback(const uint8_t *Data, size_t Size) { assert(InFuzzingThread()); - LazyAllocateCurrentUnitData(); // We copy the contents of Unit into a separate heap buffer // so that we reliably find buffer overflows in it. uint8_t *DataCopy = new uint8_t[Size]; @@ -587,11 +595,11 @@ void Fuzzer::Merge(const std::vector &Corpora) { InMergeMode = true; std::vector ExtraCorpora(Corpora.begin() + 1, Corpora.end()); - assert(Options.MaxLen > 0); + assert(MaxInputLen > 0); UnitVector Initial, Extra; - ReadDirToVectorOfUnits(Corpora[0].c_str(), &Initial, nullptr, Options.MaxLen); + ReadDirToVectorOfUnits(Corpora[0].c_str(), &Initial, nullptr, MaxInputLen); for (auto &C : ExtraCorpora) - ReadDirToVectorOfUnits(C.c_str(), &Extra, nullptr, Options.MaxLen); + ReadDirToVectorOfUnits(C.c_str(), &Extra, nullptr, MaxInputLen); if (!Initial.empty()) { Printf("=== Minimizing the initial corpus of %zd units\n", Initial.size()); @@ -645,7 +653,6 @@ void Fuzzer::TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size, } void Fuzzer::MutateAndTestOne() { - LazyAllocateCurrentUnitData(); MD.StartMutationSequence(); auto &II = Corpus.ChooseUnitToMutate(MD.GetRand()); @@ -653,18 +660,18 @@ void Fuzzer::MutateAndTestOne() { memcpy(BaseSha1, II.Sha1, sizeof(BaseSha1)); assert(CurrentUnitData); size_t Size = U.size(); - assert(Size <= Options.MaxLen && "Oversized Unit"); + assert(Size <= MaxInputLen && "Oversized Unit"); memcpy(CurrentUnitData, U.data(), Size); - size_t MaxLen = Options.MaxLen; + assert(MaxMutationLen > 0); for (int i = 0; i < Options.MutateDepth; i++) { if (TotalNumberOfRuns >= Options.MaxNumberOfRuns) break; size_t NewSize = 0; - NewSize = MD.Mutate(CurrentUnitData, Size, MaxLen); + NewSize = MD.Mutate(CurrentUnitData, Size, MaxMutationLen); assert(NewSize > 0 && "Mutator returned empty unit"); - assert(NewSize <= MaxLen && "Mutator return overisized unit"); + assert(NewSize <= MaxMutationLen && "Mutator return overisized unit"); Size = NewSize; if (i == 0) StartTraceRecording(); @@ -691,7 +698,7 @@ void Fuzzer::Loop() { while (true) { auto Now = system_clock::now(); if (duration_cast(Now - LastCorpusReload).count()) { - RereadOutputCorpus(Options.MaxLen); + RereadOutputCorpus(MaxInputLen); LastCorpusReload = Now; } if (TotalNumberOfRuns >= Options.MaxNumberOfRuns) -- 2.7.4