From 34fca4b9ec7705a0e789be0e35dd0661622d6f59 Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Thu, 26 May 2016 20:03:02 +0000 Subject: [PATCH] [libFuzzer] reimplement the way we do -only_ascii to allow more 'const' in function declarations. Add a test for -only_ascii. NFC intended git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@270900 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Fuzzer/FuzzerInternal.h | 7 ++++--- lib/Fuzzer/FuzzerLoop.cpp | 11 ++++++----- lib/Fuzzer/FuzzerTraceState.cpp | 4 ++-- lib/Fuzzer/FuzzerUtil.cpp | 8 +++++--- lib/Fuzzer/test/fuzzer.test | 3 +++ 5 files changed, 20 insertions(+), 13 deletions(-) diff --git a/lib/Fuzzer/FuzzerInternal.h b/lib/Fuzzer/FuzzerInternal.h index 8066b8a84a8..7d8247327f6 100644 --- a/lib/Fuzzer/FuzzerInternal.h +++ b/lib/Fuzzer/FuzzerInternal.h @@ -122,6 +122,7 @@ void ComputeSHA1(const uint8_t *Data, size_t Len, uint8_t *Out); // Returns true iff U has been changed. bool ToASCII(uint8_t *Data, size_t Size); bool IsASCII(const Unit &U); +bool IsASCII(const uint8_t *Data, size_t Size); int NumberOfCpuCores(); int GetPid(); @@ -408,13 +409,13 @@ private: void MutateAndTestOne(); void ReportNewCoverage(const Unit &U); bool RunOne(const Unit &U) { return RunOne(U.data(), U.size()); } - void RunOneAndUpdateCorpus(uint8_t *Data, size_t Size); + void RunOneAndUpdateCorpus(const uint8_t *Data, size_t Size); void WriteToOutputCorpus(const Unit &U); void WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix); void PrintStats(const char *Where, const char *End = "\n"); void PrintStatusForNewUnit(const Unit &U); void ShuffleCorpus(UnitVector *V); - void TryDetectingAMemoryLeak(uint8_t *Data, size_t Size); + void TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size); void CheckForMemoryLeaks(); // Updates the probability distribution for the units in the corpus. @@ -437,7 +438,7 @@ private: void DumpCurrentUnit(const char *Prefix); void DeathCallback(); - uint8_t *CurrentUnitData = nullptr; + const uint8_t *CurrentUnitData = nullptr; size_t CurrentUnitSize = 0; bool InOOMState = false; diff --git a/lib/Fuzzer/FuzzerLoop.cpp b/lib/Fuzzer/FuzzerLoop.cpp index ccd1c4e11c4..f91f1281ee0 100644 --- a/lib/Fuzzer/FuzzerLoop.cpp +++ b/lib/Fuzzer/FuzzerLoop.cpp @@ -457,11 +457,9 @@ bool Fuzzer::RunOne(const uint8_t *Data, size_t Size) { return Res; } -void Fuzzer::RunOneAndUpdateCorpus(uint8_t *Data, size_t Size) { +void Fuzzer::RunOneAndUpdateCorpus(const uint8_t *Data, size_t Size) { if (TotalNumberOfRuns >= Options.MaxNumberOfRuns) return; - if (Options.OnlyASCII) - ToASCII(Data, Size); if (RunOne(Data, Size)) ReportNewCoverage({Data, Data + Size}); } @@ -525,13 +523,14 @@ std::string Fuzzer::Coverage::DebugString() const { } void Fuzzer::WriteToOutputCorpus(const Unit &U) { + if (Options.OnlyASCII) + assert(IsASCII(U)); if (Options.OutputCorpus.empty()) return; std::string Path = DirPlusFile(Options.OutputCorpus, Hash(U)); WriteToFile(U, Path); if (Options.Verbosity >= 2) Printf("Written to %s\n", Path.c_str()); - assert(!Options.OnlyASCII || IsASCII(U)); } void Fuzzer::WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix) { @@ -659,7 +658,7 @@ void Fuzzer::CheckForMemoryLeaks() { // Tries detecting a memory leak on the particular input that we have just // executed before calling this function. -void Fuzzer::TryDetectingAMemoryLeak(uint8_t *Data, size_t Size) { +void Fuzzer::TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size) { if (!HasMoreMallocsThanFrees) return; // mallocs==frees, a leak is unlikely. if (!Options.DetectLeaks) return; if (!&__lsan_enable || !&__lsan_disable || !__lsan_do_recoverable_leak_check) @@ -710,6 +709,8 @@ void Fuzzer::MutateAndTestOne() { assert(NewSize <= Options.MaxLen && "Mutator return overisized unit"); Size = NewSize; + if (Options.OnlyASCII) + ToASCII(MutateInPlaceHere.data(), Size); if (i == 0) StartTraceRecording(); RunOneAndUpdateCorpus(MutateInPlaceHere.data(), Size); diff --git a/lib/Fuzzer/FuzzerTraceState.cpp b/lib/Fuzzer/FuzzerTraceState.cpp index 8123407e98c..d994481ff38 100644 --- a/lib/Fuzzer/FuzzerTraceState.cpp +++ b/lib/Fuzzer/FuzzerTraceState.cpp @@ -175,7 +175,7 @@ static bool RecordingMemcmp = false; class TraceState { public: TraceState(MutationDispatcher &MD, const Fuzzer::FuzzingOptions &Options, - uint8_t **CurrentUnitData, size_t *CurrentUnitSize) + const uint8_t **CurrentUnitData, size_t *CurrentUnitSize) : MD(MD), Options(Options), CurrentUnitData(CurrentUnitData), CurrentUnitSize(CurrentUnitSize) { // Current trace collection is not thread-friendly and it probably @@ -293,7 +293,7 @@ class TraceState { size_t LastDfsanLabel = 0; MutationDispatcher &MD; const Fuzzer::FuzzingOptions &Options; - uint8_t **CurrentUnitData; + const uint8_t **CurrentUnitData; size_t *CurrentUnitSize; std::map AutoDictUnitCounts; size_t AutoDictAdds = 0; diff --git a/lib/Fuzzer/FuzzerUtil.cpp b/lib/Fuzzer/FuzzerUtil.cpp index ec592e03f23..420f05d05c4 100644 --- a/lib/Fuzzer/FuzzerUtil.cpp +++ b/lib/Fuzzer/FuzzerUtil.cpp @@ -164,9 +164,11 @@ bool ToASCII(uint8_t *Data, size_t Size) { return Changed; } -bool IsASCII(const Unit &U) { - for (auto X : U) - if (!(isprint(X) || isspace(X))) return false; +bool IsASCII(const Unit &U) { return IsASCII(U.data(), U.size()); } + +bool IsASCII(const uint8_t *Data, size_t Size) { + for (size_t i = 0; i < Size; i++) + if (!(isprint(Data[i]) || isspace(Data[i]))) return false; return true; } diff --git a/lib/Fuzzer/test/fuzzer.test b/lib/Fuzzer/test/fuzzer.test index 8c5d148c725..cff7d6f74bc 100644 --- a/lib/Fuzzer/test/fuzzer.test +++ b/lib/Fuzzer/test/fuzzer.test @@ -5,6 +5,9 @@ RUN: LLVMFuzzer-SimpleTest 2>&1 | FileCheck %s RUN: not LLVMFuzzer-NullDerefTest %S/hi.txt 2>&1 | FileCheck %s --check-prefix=SingleInput SingleInput-NOT: Test unit written to ./crash- +# only_ascii mode. Will perform some minimal self-validation. +RUN: LLVMFuzzer-SimpleTest -only_ascii=1 2>&1 + RUN: LLVMFuzzer-SimpleCmpTest -max_total_time=1 2>&1 | FileCheck %s --check-prefix=MaxTotalTime MaxTotalTime: Done {{.*}} runs in {{.}} second(s) -- 2.11.0