1
0
mirror of https://github.com/RPCSX/llvm.git synced 2025-04-03 16:51:42 +00:00

[libFuzzer] get rid of UserSuppliedFuzzer; NFC

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@260798 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Kostya Serebryany 2016-02-13 03:25:16 +00:00
parent 728ca1266f
commit efb0cc7640
9 changed files with 41 additions and 97 deletions

@ -315,12 +315,12 @@ int FuzzerDriver(const std::vector<std::string> &Args, UserCallback Callback) {
Printf("Seed: %u\n", Seed);
Random Rand(Seed);
SimpleUserSuppliedFuzzer USF(&Rand, Callback);
Fuzzer F(USF, Options);
MutationDispatcher MD(Rand);
Fuzzer F(Callback, MD, Options);
for (auto &U: Dictionary)
if (U.size() <= Word::GetMaxSize())
USF.GetMD().AddWordToManualDictionary(Word(U.data(), U.size()));
MD.AddWordToManualDictionary(Word(U.data(), U.size()));
// Timer
if (Flags.timeout > 0)

@ -16,30 +16,5 @@
namespace fuzzer {
UserSuppliedFuzzer::UserSuppliedFuzzer(Random *Rand)
: Rand(Rand), MD(new MutationDispatcher(*Rand)) {}
UserSuppliedFuzzer::~UserSuppliedFuzzer() {
if (OwnRand)
delete Rand;
delete MD;
}
size_t UserSuppliedFuzzer::Mutate(uint8_t *Data, size_t Size, size_t MaxSize) {
return GetMD().Mutate(Data, Size, MaxSize);
}
size_t UserSuppliedFuzzer::CrossOver(const uint8_t *Data1, size_t Size1,
const uint8_t *Data2, size_t Size2,
uint8_t *Out, size_t MaxOutSize) {
return GetMD().CrossOver(Data1, Size1, Data2, Size2, Out, MaxOutSize);
}
size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize, unsigned int Seed) {
Random R(Seed);
MutationDispatcher MD(R);
return MD.Mutate(Data, Size, MaxSize);
}
} // namespace fuzzer.

@ -104,6 +104,7 @@ class Random {
size_t Rand() { return R(); }
size_t RandBool() { return Rand() % 2; }
size_t operator()(size_t n) { return n ? Rand() % n : 0; }
std::mt19937 &Get_mt19937() { return R; }
private:
std::mt19937 R;
};
@ -173,37 +174,14 @@ public:
void SetCorpus(const std::vector<Unit> *Corpus);
Random &GetRand() { return Rand; }
private:
Random &Rand;
struct Impl;
Impl *MDImpl;
};
class UserSuppliedFuzzer {
public:
UserSuppliedFuzzer(Random *Rand);
/// Executes the target function on 'Size' bytes of 'Data'.
virtual int TargetFunction(const uint8_t *Data, size_t Size) = 0;
/// Mutates 'Size' bytes of data in 'Data' inplace into up to 'MaxSize' bytes,
/// returns the new size of the data, which should be positive.
virtual size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize);
/// Crosses 'Data1' and 'Data2', writes up to 'MaxOutSize' bytes into Out,
/// returns the number of bytes written, which should be positive.
virtual size_t CrossOver(const uint8_t *Data1, size_t Size1,
const uint8_t *Data2, size_t Size2,
uint8_t *Out, size_t MaxOutSize);
virtual ~UserSuppliedFuzzer();
Random &GetRand() { return *Rand; }
MutationDispatcher &GetMD() { return *MD; }
private:
bool OwnRand = false;
Random *Rand;
MutationDispatcher *MD;
};
class Fuzzer {
public:
struct FuzzingOptions {
@ -237,7 +215,7 @@ public:
bool OutputCSV = false;
bool PrintNewCovPcs = false;
};
Fuzzer(UserSuppliedFuzzer &USF, FuzzingOptions Options);
Fuzzer(UserCallback CB, MutationDispatcher &MD, FuzzingOptions Options);
void AddToCorpus(const Unit &U) {
Corpus.push_back(U);
UpdateCorpusDistribution();
@ -324,14 +302,9 @@ private:
return Res;
}
// TODO(krasin): remove GetRand from UserSuppliedFuzzer,
// and fully rely on the generator and the seed.
// The user supplied fuzzer will have a way to access the
// generator for its own purposes (like seeding the custom
// PRNG).
std::mt19937 Generator;
std::piecewise_constant_distribution<double> CorpusDistribution;
UserSuppliedFuzzer &USF;
UserCallback CB;
MutationDispatcher &MD;
FuzzingOptions Options;
system_clock::time_point ProcessStartTime = system_clock::now();
system_clock::time_point LastExternalSync = system_clock::now();
@ -343,19 +316,6 @@ private:
size_t LastCoveragePcBufferLen = 0;
};
class SimpleUserSuppliedFuzzer : public UserSuppliedFuzzer {
public:
SimpleUserSuppliedFuzzer(Random *Rand, UserCallback Callback)
: UserSuppliedFuzzer(Rand), Callback(Callback) {}
virtual int TargetFunction(const uint8_t *Data, size_t Size) override {
return Callback(Data, Size);
}
private:
UserCallback Callback = nullptr;
};
}; // namespace fuzzer
#endif // LLVM_FUZZER_INTERNAL_H

@ -60,8 +60,8 @@ static void MissingWeakApiFunction(const char *FnName) {
// Only one Fuzzer per process.
static Fuzzer *F;
Fuzzer::Fuzzer(UserSuppliedFuzzer &USF, FuzzingOptions Options)
: Generator(USF.GetRand().Rand()), USF(USF), Options(Options) {
Fuzzer::Fuzzer(UserCallback CB, MutationDispatcher &MD, FuzzingOptions Options)
: CB(CB), MD(MD), Options(Options) {
SetDeathCallback();
InitializeTraceState();
assert(!F);
@ -184,13 +184,13 @@ void Fuzzer::RereadOutputCorpus() {
void Fuzzer::ShuffleAndMinimize() {
bool PreferSmall = (Options.PreferSmallDuringInitialShuffle == 1 ||
(Options.PreferSmallDuringInitialShuffle == -1 &&
USF.GetRand().RandBool()));
MD.GetRand().RandBool()));
if (Options.Verbosity)
Printf("PreferSmall: %d\n", PreferSmall);
PrintStats("READ ");
std::vector<Unit> NewCorpus;
if (Options.ShuffleAtStartUp) {
std::random_shuffle(Corpus.begin(), Corpus.end(), USF.GetRand());
std::random_shuffle(Corpus.begin(), Corpus.end(), MD.GetRand());
if (PreferSmall)
std::stable_sort(
Corpus.begin(), Corpus.end(),
@ -258,7 +258,7 @@ void Fuzzer::ExecuteCallback(const Unit &U) {
AssignTaintLabels(Data.get(), U.size());
CurrentUnitData = Data.get();
CurrentUnitSize = U.size();
int Res = USF.TargetFunction(Data.get(), U.size());
int Res = CB(Data.get(), U.size());
(void)Res;
assert(Res == 0);
CurrentUnitData = nullptr;
@ -355,7 +355,7 @@ void Fuzzer::PrintStatusForNewUnit(const Unit &U) {
PrintStats("NEW ", "");
if (Options.Verbosity) {
Printf(" L: %zd ", U.size());
USF.GetMD().PrintMutationSequence();
MD.PrintMutationSequence();
Printf("\n");
}
}
@ -364,7 +364,7 @@ void Fuzzer::ReportNewCoverage(const Unit &U) {
Corpus.push_back(U);
UpdateCorpusDistribution();
UnitHashesAddedToCorpus.insert(Hash(U));
USF.GetMD().RecordSuccessfulMutationSequence();
MD.RecordSuccessfulMutationSequence();
PrintStatusForNewUnit(U);
WriteToOutputCorpus(U);
if (Options.ExitOnFirst)
@ -404,7 +404,7 @@ void Fuzzer::Merge(const std::vector<std::string> &Corpora) {
}
void Fuzzer::MutateAndTestOne() {
USF.GetMD().StartMutationSequence();
MD.StartMutationSequence();
auto U = ChooseUnitToMutate();
@ -414,9 +414,9 @@ void Fuzzer::MutateAndTestOne() {
size_t NewSize = 0;
if (LLVMFuzzerCustomMutator)
NewSize = LLVMFuzzerCustomMutator(U.data(), Size, U.size(),
USF.GetRand().Rand());
MD.GetRand().Rand());
else
NewSize = USF.Mutate(U.data(), Size, U.size());
NewSize = MD.Mutate(U.data(), Size, U.size());
assert(NewSize > 0 && "Mutator returned empty unit");
assert(NewSize <= (size_t)Options.MaxLen &&
"Mutator return overisized unit");
@ -432,7 +432,8 @@ void Fuzzer::MutateAndTestOne() {
// 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 Fuzzer::ChooseUnitIdxToMutate() {
size_t Idx = static_cast<size_t>(CorpusDistribution(Generator));
size_t Idx =
static_cast<size_t>(CorpusDistribution(MD.GetRand().Get_mt19937()));
assert(Idx < Corpus.size());
return Idx;
}
@ -489,7 +490,7 @@ void Fuzzer::Drill() {
void Fuzzer::Loop() {
system_clock::time_point LastCorpusReload = system_clock::now();
if (Options.DoCrossOver)
USF.GetMD().SetCorpus(&Corpus);
MD.SetCorpus(&Corpus);
while (true) {
SyncCorpus();
auto Now = system_clock::now();
@ -508,7 +509,7 @@ void Fuzzer::Loop() {
}
PrintStats("DONE ", "\n");
USF.GetMD().PrintRecommendedDictionary();
MD.PrintRecommendedDictionary();
}
void Fuzzer::SyncCorpus() {

@ -76,6 +76,7 @@ private:
const size_t Dictionary::kMaxDictSize;
struct MutationDispatcher::Impl {
// Dictionary provided by the user via -dict=DICT_FILE.
Dictionary ManualDictionary;
@ -113,6 +114,12 @@ struct MutationDispatcher::Impl {
size_t MaxSize);
};
size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize, unsigned int Seed) {
Random R(Seed);
MutationDispatcher MD(R);
return MD.Mutate(Data, Size, MaxSize);
}
static char FlipRandomBit(char X, Random &Rand) {
int Bit = Rand(8);
char Mask = 1 << Bit;

@ -174,9 +174,9 @@ static bool RecordingMemcmp = false;
class TraceState {
public:
TraceState(UserSuppliedFuzzer &USF, const Fuzzer::FuzzingOptions &Options,
TraceState(MutationDispatcher &MD, const Fuzzer::FuzzingOptions &Options,
uint8_t **CurrentUnitData, size_t *CurrentUnitSize)
: USF(USF), Options(Options), CurrentUnitData(CurrentUnitData),
: MD(MD), Options(Options), CurrentUnitData(CurrentUnitData),
CurrentUnitSize(CurrentUnitSize) {
// Current trace collection is not thread-friendly and it probably
// does not have to be such, but at least we should not crash in presence
@ -210,7 +210,7 @@ class TraceState {
RecordingTraces = Options.UseTraces;
RecordingMemcmp = Options.UseMemcmp;
NumMutations = 0;
USF.GetMD().ClearAutoDictionary();
MD.ClearAutoDictionary();
}
void StopTraceRecording() {
@ -237,7 +237,7 @@ class TraceState {
}
}
}
USF.GetMD().AddWordToAutoDictionary(M.W, M.Pos);
MD.AddWordToAutoDictionary(M.W, M.Pos);
}
}
@ -271,7 +271,7 @@ class TraceState {
size_t Diff = NumMutations - FirstN;
size_t DiffLog = sizeof(long) * 8 - __builtin_clzl((long)Diff);
assert(DiffLog > 0 && DiffLog < 64);
bool WantThisOne = USF.GetRand()(1 << DiffLog) == 0; // 1 out of DiffLog.
bool WantThisOne = MD.GetRand()(1 << DiffLog) == 0; // 1 out of DiffLog.
return WantThisOne;
}
@ -279,7 +279,7 @@ class TraceState {
size_t NumMutations;
TraceBasedMutation Mutations[kMaxMutations];
LabelRange LabelRanges[1 << (sizeof(dfsan_label) * 8)];
UserSuppliedFuzzer &USF;
MutationDispatcher &MD;
const Fuzzer::FuzzingOptions &Options;
uint8_t **CurrentUnitData;
size_t *CurrentUnitSize;
@ -486,7 +486,7 @@ void Fuzzer::AssignTaintLabels(uint8_t *Data, size_t Size) {
void Fuzzer::InitializeTraceState() {
if (!Options.UseTraces && !Options.UseMemcmp) return;
TS = new TraceState(USF, Options, &CurrentUnitData, &CurrentUnitSize);
TS = new TraceState(MD, Options, &CurrentUnitData, &CurrentUnitSize);
if (ReallyHaveDFSan()) {
for (size_t i = 0; i < static_cast<size_t>(Options.MaxLen); i++) {
dfsan_label L = dfsan_create_label("input", (void *)(i + 1));

@ -403,9 +403,9 @@ TEST(FuzzerUtil, Base64) {
TEST(Corpus, Distribution) {
Random Rand(0);
SimpleUserSuppliedFuzzer USF(&Rand, LLVMFuzzerTestOneInput);
MutationDispatcher MD(Rand);
Fuzzer::FuzzingOptions Options;
Fuzzer Fuzz(USF, Options);
Fuzzer Fuzz(LLVMFuzzerTestOneInput, MD, Options);
size_t N = 10;
size_t TriesPerUnit = 1<<20;
for (size_t i = 0; i < N; i++) {

@ -7,7 +7,7 @@ CHECK_DFSanCmpCallback: DFSanCmpCallback: PC
CHECK_DFSanSwitchCallback: DFSanSwitchCallback: PC
CHECK_DFSanMemcmpCallback: DFSanMemcmpCallback: Pos
RUN: not LLVMFuzzer-SimpleCmpTest-DFSan -use_traces=1 -seed=1 -runs=1000000 -timeout=5 2>&1 | FileCheck %s --check-prefix=CHECK1
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

@ -59,6 +59,7 @@ RUN: not LLVMFuzzer-LeakTest -runs=10 2>&1 | FileCheck %s --check-prefix=LEAK
LEAK: ERROR: LeakSanitizer: detected memory leaks
LEAK-NOT: DEATH:
RUN: mkdir -p %t
RUN: echo abcd > %t/NthRunCrashTest.in
RUN: LLVMFuzzer-NthRunCrashTest %t/NthRunCrashTest.in
RUN: LLVMFuzzer-NthRunCrashTest %t/NthRunCrashTest.in -runs=10