[llvm] r282121 - [libFuzzer] add stats to the corpus; more refactoring
Kostya Serebryany via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 21 15:42:17 PDT 2016
Author: kcc
Date: Wed Sep 21 17:42:17 2016
New Revision: 282121
URL: http://llvm.org/viewvc/llvm-project?rev=282121&view=rev
Log:
[libFuzzer] add stats to the corpus; more refactoring
Modified:
llvm/trunk/lib/Fuzzer/FuzzerCorpus.h
llvm/trunk/lib/Fuzzer/FuzzerDefs.h
llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp
llvm/trunk/lib/Fuzzer/FuzzerFlags.def
llvm/trunk/lib/Fuzzer/FuzzerInternal.h
llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp
llvm/trunk/lib/Fuzzer/FuzzerMutate.cpp
llvm/trunk/lib/Fuzzer/FuzzerOptions.h
llvm/trunk/lib/Fuzzer/FuzzerUtil.cpp
llvm/trunk/lib/Fuzzer/test/FuzzerUnittest.cpp
Modified: llvm/trunk/lib/Fuzzer/FuzzerCorpus.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerCorpus.h?rev=282121&r1=282120&r2=282121&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerCorpus.h (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerCorpus.h Wed Sep 21 17:42:17 2016
@@ -13,6 +13,7 @@
#define LLVM_FUZZER_CORPUS
#include <random>
+#include <unordered_set>
#include "FuzzerDefs.h"
#include "FuzzerRandom.h"
@@ -22,6 +23,9 @@ namespace fuzzer {
struct InputInfo {
Unit U; // The actual input data.
uint8_t Sha1[kSHA1NumBytes]; // Checksum.
+ // Stats.
+ uintptr_t NumExecutedMutations = 0;
+ uintptr_t NumSuccessfullMutations = 0;
};
class InputCorpus {
@@ -32,11 +36,7 @@ class InputCorpus {
size_t size() const { return Inputs.size(); }
bool empty() const { return Inputs.empty(); }
const Unit &operator[] (size_t Idx) const { return Inputs[Idx].U; }
- void Append(const std::vector<Unit> &V) {
- for (auto &U : V)
- push_back(U);
- }
- void push_back(const Unit &U) {
+ void AddToCorpus(const Unit &U) {
auto H = Hash(U);
if (!Hashes.insert(H).second) return;
InputInfo II;
@@ -51,7 +51,7 @@ class InputCorpus {
ConstIter end() const { return Inputs.end(); }
bool HasUnit(const Unit &U) { return Hashes.count(Hash(U)); }
- const InputInfo &ChooseUnitToMutate(Random &Rand) {
+ InputInfo &ChooseUnitToMutate(Random &Rand) {
return Inputs[ChooseUnitIdxToMutate(Rand)];
};
@@ -59,12 +59,20 @@ class InputCorpus {
// Hypothesis: units added to the corpus last are more likely to be
// interesting. This function gives more weight to the more recent units.
size_t ChooseUnitIdxToMutate(Random &Rand) {
- size_t Idx =
- static_cast<size_t>(CorpusDistribution(Rand.Get_mt19937()));
+ size_t Idx = static_cast<size_t>(CorpusDistribution(Rand.Get_mt19937()));
assert(Idx < Inputs.size());
return Idx;
}
+ void PrintStats() {
+ for (size_t i = 0; i < Inputs.size(); i++) {
+ const auto &II = Inputs[i];
+ Printf(" [%zd %s]\tsz: %zd\truns: %zd\tsucc: %zd\n", i,
+ Sha1ToString(II.Sha1).c_str(), II.U.size(),
+ II.NumExecutedMutations, II.NumSuccessfullMutations);
+ }
+ }
+
private:
// Updates the probability distribution for the units in the corpus.
Modified: llvm/trunk/lib/Fuzzer/FuzzerDefs.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerDefs.h?rev=282121&r1=282120&r2=282121&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerDefs.h (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerDefs.h Wed Sep 21 17:42:17 2016
@@ -43,6 +43,7 @@ class DictionaryEntry;
class MutationDispatcher;
struct FuzzingOptions;
class InputCorpus;
+struct InputInfo;
struct ExternalFunctions;
// Global interface to functions that may or may not be available.
@@ -92,7 +93,7 @@ size_t GetPeakRSSMb();
static const int kSHA1NumBytes = 20;
// Computes SHA1 hash of 'Len' bytes in 'Data', writes kSHA1NumBytes to 'Out'.
void ComputeSHA1(const uint8_t *Data, size_t Len, uint8_t *Out);
-std::string Sha1ToString(uint8_t Sha1[kSHA1NumBytes]);
+std::string Sha1ToString(const uint8_t Sha1[kSHA1NumBytes]);
// Changes U to contain only ASCII (isprint+isspace) characters.
// Returns true iff U has been changed.
Modified: llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp?rev=282121&r1=282120&r2=282121&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp Wed Sep 21 17:42:17 2016
@@ -9,6 +9,7 @@
// FuzzerDriver and flag parsing.
//===----------------------------------------------------------------------===//
+#include "FuzzerCorpus.h"
#include "FuzzerInterface.h"
#include "FuzzerInternal.h"
#include "FuzzerMutate.h"
@@ -335,7 +336,7 @@ int MinimizeCrashInput(const std::vector
return 0;
}
-int MinimizeCrashInputInternalStep(Fuzzer *F) {
+int MinimizeCrashInputInternalStep(Fuzzer *F, InputCorpus *Corpus) {
assert(Inputs->size() == 1);
std::string InputFilePath = Inputs->at(0);
Unit U = FileToVector(InputFilePath);
@@ -345,7 +346,7 @@ int MinimizeCrashInputInternalStep(Fuzze
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);
- F->AddToCorpus(X);
+ Corpus->AddToCorpus(X);
}
F->SetMaxLen(U.size() - 1);
F->Loop();
@@ -427,6 +428,7 @@ int FuzzerDriver(int *argc, char ***argv
!DoPlainRun || Flags.minimize_crash_internal_step;
Options.PrintNewCovPcs = Flags.print_pcs;
Options.PrintFinalStats = Flags.print_final_stats;
+ Options.PrintCorpusStats = Flags.print_corpus_stats;
Options.PrintCoverage = Flags.print_coverage;
Options.PruneCorpus = Flags.prune_corpus;
@@ -443,7 +445,8 @@ int FuzzerDriver(int *argc, char ***argv
Random Rand(Seed);
MutationDispatcher MD(Rand, Options);
- Fuzzer F(Callback, MD, Options);
+ InputCorpus Corpus;
+ Fuzzer F(Callback, Corpus, MD, Options);
for (auto &U: Dictionary)
if (U.size() <= Word::GetMaxSize())
@@ -463,7 +466,7 @@ int FuzzerDriver(int *argc, char ***argv
if (Flags.handle_term) SetSigTermHandler();
if (Flags.minimize_crash_internal_step)
- return MinimizeCrashInputInternalStep(&F);
+ return MinimizeCrashInputInternalStep(&F, &Corpus);
if (DoPlainRun) {
Options.SaveArtifacts = false;
Modified: llvm/trunk/lib/Fuzzer/FuzzerFlags.def
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerFlags.def?rev=282121&r1=282120&r2=282121&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerFlags.def (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerFlags.def Wed Sep 21 17:42:17 2016
@@ -74,6 +74,8 @@ FUZZER_FLAG_STRING(exact_artifact_path,
FUZZER_FLAG_INT(output_csv, 0, "Enable pulse output in CSV format.")
FUZZER_FLAG_INT(print_pcs, 0, "If 1, print out newly covered PCs.")
FUZZER_FLAG_INT(print_final_stats, 0, "If 1, print statistics at exit.")
+FUZZER_FLAG_INT(print_corpus_stats, 0,
+ "If 1, print statistics on corpus elements at exit.")
FUZZER_FLAG_INT(print_coverage, 0, "If 1, print coverage information at exit."
" Experimental, only with trace-pc-guard")
FUZZER_FLAG_INT(handle_segv, 1, "If 1, try to intercept SIGSEGV.")
Modified: llvm/trunk/lib/Fuzzer/FuzzerInternal.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerInternal.h?rev=282121&r1=282120&r2=282121&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerInternal.h (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerInternal.h Wed Sep 21 17:42:17 2016
@@ -18,14 +18,12 @@
#include <climits>
#include <cstdlib>
#include <string.h>
-#include <unordered_set>
#include "FuzzerDefs.h"
#include "FuzzerExtFunctions.h"
#include "FuzzerInterface.h"
#include "FuzzerOptions.h"
#include "FuzzerValueBitMap.h"
-#include "FuzzerCorpus.h"
namespace fuzzer {
@@ -64,15 +62,13 @@ public:
size_t VPMapBits;
};
- Fuzzer(UserCallback CB, MutationDispatcher &MD, FuzzingOptions Options);
+ Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD,
+ FuzzingOptions Options);
~Fuzzer();
- void AddToCorpus(const Unit &U) { Corpus.push_back(U); }
void Loop();
void ShuffleAndMinimize(UnitVector *V);
void InitializeTraceState();
void AssignTaintLabels(uint8_t *Data, size_t Size);
- size_t CorpusSize() const { return Corpus.size(); }
- void ReadDir(const std::string &Path, long *Epoch, size_t MaxSize);
void RereadOutputCorpus(size_t MaxSize);
size_t secondsSinceProcessStartUp() {
@@ -113,11 +109,10 @@ private:
void CrashCallback();
void InterruptCallback();
void MutateAndTestOne();
- void ReportNewCoverage(const Unit &U);
+ void ReportNewCoverage(InputInfo *II, const Unit &U);
void PrintNewPCs();
void PrintOneNewPC(uintptr_t PC);
bool RunOne(const Unit &U) { return RunOne(U.data(), U.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");
@@ -158,11 +153,11 @@ private:
bool HasMoreMallocsThanFrees = false;
size_t NumberOfLeakDetectionAttempts = 0;
- InputCorpus Corpus;
-
UserCallback CB;
+ InputCorpus &Corpus;
MutationDispatcher &MD;
FuzzingOptions Options;
+
system_clock::time_point ProcessStartTime = system_clock::now();
system_clock::time_point UnitStartTime;
long TimeOfLongestUnitInSeconds = 0;
Modified: llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp?rev=282121&r1=282120&r2=282121&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp Wed Sep 21 17:42:17 2016
@@ -10,6 +10,7 @@
//===----------------------------------------------------------------------===//
#include "FuzzerInternal.h"
+#include "FuzzerCorpus.h"
#include "FuzzerMutate.h"
#include "FuzzerTracePC.h"
#include "FuzzerRandom.h"
@@ -157,8 +158,9 @@ void FreeHook(const volatile void *ptr)
AllocTracer.Frees++;
}
-Fuzzer::Fuzzer(UserCallback CB, MutationDispatcher &MD, FuzzingOptions Options)
- : CB(CB), MD(MD), Options(Options) {
+Fuzzer::Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD,
+ FuzzingOptions Options)
+ : CB(CB), Corpus(Corpus), MD(MD), Options(Options) {
SetDeathCallback();
InitializeTraceState();
assert(!F);
@@ -337,6 +339,8 @@ void Fuzzer::PrintStats(const char *Wher
void Fuzzer::PrintFinalStats() {
if (Options.PrintCoverage)
TPC.PrintCoverage();
+ if (Options.PrintCorpusStats)
+ Corpus.PrintStats();
if (!Options.PrintFinalStats) return;
size_t ExecPerSec = execPerSec();
Printf("stat::number_of_executed_units: %zd\n", TotalNumberOfRuns);
@@ -353,14 +357,6 @@ void Fuzzer::SetMaxLen(size_t MaxLen) {
Printf("INFO: -max_len is not provided, using %zd\n", Options.MaxLen);
}
-void Fuzzer::ReadDir(const std::string &Path, long *Epoch, size_t MaxSize) {
- Printf("Loading corpus: %s\n", Path.c_str());
- std::vector<Unit> V;
- ReadDirToVectorOfUnits(Path.c_str(), &V, Epoch, MaxSize);
- for (auto &U : V)
- Corpus.push_back(U);
-}
-
void Fuzzer::RereadOutputCorpus(size_t MaxSize) {
if (Options.OutputCorpus.empty() || !Options.Reload) return;
std::vector<Unit> AdditionalCorpus;
@@ -373,7 +369,7 @@ void Fuzzer::RereadOutputCorpus(size_t M
X.resize(MaxSize);
if (!Corpus.HasUnit(X)) {
if (RunOne(X)) {
- Corpus.push_back(X);
+ Corpus.AddToCorpus(X);
PrintStats("RELOAD");
}
}
@@ -396,7 +392,7 @@ void Fuzzer::ShuffleAndMinimize(UnitVect
for (const auto &U : *InitialCorpus) {
bool NewCoverage = RunOne(U);
if (!Options.PruneCorpus || NewCoverage) {
- Corpus.push_back(U);
+ Corpus.AddToCorpus(U);
if (Options.Verbosity >= 2)
Printf("NEW0: %zd L %zd\n", MaxCoverage.BlockCoverage, U.size());
}
@@ -439,13 +435,6 @@ bool Fuzzer::RunOne(const uint8_t *Data,
return Res;
}
-void Fuzzer::RunOneAndUpdateCorpus(const uint8_t *Data, size_t Size) {
- if (TotalNumberOfRuns >= Options.MaxNumberOfRuns)
- return;
- if (RunOne(Data, Size))
- ReportNewCoverage({Data, Data + Size});
-}
-
size_t Fuzzer::GetCurrentUnitInFuzzingThead(const uint8_t **Data) const {
assert(InFuzzingThread());
*Data = CurrentUnitData;
@@ -539,8 +528,9 @@ void Fuzzer::PrintNewPCs() {
PrintOneNewPC(PCs[i]);
}
-void Fuzzer::ReportNewCoverage(const Unit &U) {
- Corpus.push_back(U);
+void Fuzzer::ReportNewCoverage(InputInfo *II, const Unit &U) {
+ II->NumSuccessfullMutations++;
+ Corpus.AddToCorpus(U);
MD.RecordSuccessfulMutationSequence();
PrintStatusForNewUnit(U);
WriteToOutputCorpus(U);
@@ -653,7 +643,7 @@ void Fuzzer::MutateAndTestOne() {
LazyAllocateCurrentUnitData();
MD.StartMutationSequence();
- const auto &II = Corpus.ChooseUnitToMutate(MD.GetRand());
+ auto &II = Corpus.ChooseUnitToMutate(MD.GetRand());
const auto &U = II.U;
memcpy(BaseSha1, II.Sha1, sizeof(BaseSha1));
assert(CurrentUnitData);
@@ -662,6 +652,8 @@ void Fuzzer::MutateAndTestOne() {
memcpy(CurrentUnitData, U.data(), Size);
for (int i = 0; i < Options.MutateDepth; i++) {
+ if (TotalNumberOfRuns >= Options.MaxNumberOfRuns)
+ break;
size_t NewSize = 0;
NewSize = MD.Mutate(CurrentUnitData, Size, Options.MaxLen);
assert(NewSize > 0 && "Mutator returned empty unit");
@@ -669,7 +661,9 @@ void Fuzzer::MutateAndTestOne() {
Size = NewSize;
if (i == 0)
StartTraceRecording();
- RunOneAndUpdateCorpus(CurrentUnitData, Size);
+ II.NumExecutedMutations++;
+ if (RunOne(CurrentUnitData, Size))
+ ReportNewCoverage(&II, {CurrentUnitData, CurrentUnitData + Size});
StopTraceRecording();
TryDetectingAMemoryLeak(CurrentUnitData, Size,
/*DuringInitialCorpusExecution*/ false);
Modified: llvm/trunk/lib/Fuzzer/FuzzerMutate.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerMutate.cpp?rev=282121&r1=282120&r2=282121&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerMutate.cpp (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerMutate.cpp Wed Sep 21 17:42:17 2016
@@ -10,7 +10,6 @@
//===----------------------------------------------------------------------===//
#include <cstring>
-#include <unordered_set>
#include "FuzzerCorpus.h"
#include "FuzzerDefs.h"
Modified: llvm/trunk/lib/Fuzzer/FuzzerOptions.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerOptions.h?rev=282121&r1=282120&r2=282121&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerOptions.h (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerOptions.h Wed Sep 21 17:42:17 2016
@@ -45,6 +45,7 @@ struct FuzzingOptions {
bool OutputCSV = false;
bool PrintNewCovPcs = false;
bool PrintFinalStats = false;
+ bool PrintCorpusStats = false;
bool PrintCoverage = false;
bool DetectLeaks = true;
bool PruneCorpus = true;
Modified: llvm/trunk/lib/Fuzzer/FuzzerUtil.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerUtil.cpp?rev=282121&r1=282120&r2=282121&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerUtil.cpp (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerUtil.cpp Wed Sep 21 17:42:17 2016
@@ -59,7 +59,7 @@ void PrintASCII(const Unit &U, const cha
PrintASCII(U.data(), U.size(), PrintAfter);
}
-std::string Sha1ToString(uint8_t Sha1[kSHA1NumBytes]) {
+std::string Sha1ToString(const uint8_t Sha1[kSHA1NumBytes]) {
std::stringstream SS;
for (int i = 0; i < kSHA1NumBytes; i++)
SS << std::hex << std::setfill('0') << std::setw(2) << (unsigned)Sha1[i];
Modified: llvm/trunk/lib/Fuzzer/test/FuzzerUnittest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/test/FuzzerUnittest.cpp?rev=282121&r1=282120&r2=282121&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/test/FuzzerUnittest.cpp (original)
+++ llvm/trunk/lib/Fuzzer/test/FuzzerUnittest.cpp Wed Sep 21 17:42:17 2016
@@ -5,6 +5,7 @@
// with ASan) involving C++ standard library types when using libcxx.
#define _LIBCPP_HAS_NO_ASAN
+#include "FuzzerCorpus.h"
#include "FuzzerInternal.h"
#include "FuzzerDictionary.h"
#include "FuzzerMutate.h"
@@ -582,7 +583,7 @@ TEST(Corpus, Distribution) {
size_t N = 10;
size_t TriesPerUnit = 1<<20;
for (size_t i = 0; i < N; i++)
- C.push_back(Unit{ static_cast<uint8_t>(i) });
+ C.AddToCorpus(Unit{ static_cast<uint8_t>(i) });
std::vector<size_t> Hist(N);
for (size_t i = 0; i < N * TriesPerUnit; i++) {
More information about the llvm-commits
mailing list