mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
[libFuzzer] make CrossOver just one of the other mutations
llvm-svn: 256081
This commit is contained in:
parent
95ac2d26ea
commit
ab36ca708c
@ -22,6 +22,7 @@
|
||||
#include <string>
|
||||
|
||||
namespace fuzzer {
|
||||
typedef std::vector<uint8_t> Unit;
|
||||
|
||||
/// Returns an int 0. Values other than zero are reserved for future.
|
||||
typedef int (*UserCallback)(const uint8_t *Data, size_t Size);
|
||||
@ -89,8 +90,12 @@ class MutationDispatcher {
|
||||
size_t Mutate_AddWordFromDictionary(uint8_t *Data, size_t Size,
|
||||
size_t MaxSize);
|
||||
|
||||
/// Tries to find an ASCII integer in Data, changes it to another ASCII int.
|
||||
size_t Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size, size_t MaxSize);
|
||||
|
||||
/// CrossOver Data with some other element of the corpus.
|
||||
size_t Mutate_CrossOver(uint8_t *Data, size_t Size, size_t MaxSize);
|
||||
|
||||
/// Applies one of the above mutations.
|
||||
/// Returns the new size of data which could be up to MaxSize.
|
||||
size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize);
|
||||
@ -100,6 +105,7 @@ class MutationDispatcher {
|
||||
size_t Size2, uint8_t *Out, size_t MaxOutSize);
|
||||
|
||||
void AddWordToDictionary(const uint8_t *Word, size_t Size);
|
||||
void SetCorpus(const std::vector<Unit> *Corpus);
|
||||
|
||||
private:
|
||||
FuzzerRandomBase &Rand;
|
||||
@ -144,6 +150,9 @@ class UserSuppliedFuzzer {
|
||||
virtual int TargetFunction(const uint8_t *Data, size_t Size) = 0;
|
||||
virtual void StartMutationSequence() { MD.StartMutationSequence(); }
|
||||
virtual void PrintMutationSequence() { MD.PrintMutationSequence(); }
|
||||
virtual void SetCorpus(const std::vector<Unit> *Corpus) {
|
||||
MD.SetCorpus(Corpus);
|
||||
}
|
||||
/// 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) {
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include "FuzzerInterface.h"
|
||||
|
||||
namespace fuzzer {
|
||||
typedef std::vector<uint8_t> Unit;
|
||||
using namespace std::chrono;
|
||||
|
||||
std::string FileToString(const std::string &Path);
|
||||
@ -132,7 +131,7 @@ class Fuzzer {
|
||||
|
||||
private:
|
||||
void AlarmCallback();
|
||||
void MutateAndTestOne(Unit *U);
|
||||
void MutateAndTestOne();
|
||||
void ReportNewCoverage(const Unit &U);
|
||||
bool RunOne(const Unit &U);
|
||||
void RunOneAndUpdateCorpus(Unit &U);
|
||||
|
@ -367,29 +367,34 @@ void Fuzzer::Merge(const std::vector<std::string> &Corpora) {
|
||||
Printf("Merge: written %zd out of %zd units\n", NumMerged, NumTried);
|
||||
}
|
||||
|
||||
void Fuzzer::MutateAndTestOne(Unit *U) {
|
||||
void Fuzzer::MutateAndTestOne() {
|
||||
auto &U = CurrentUnit;
|
||||
USF.StartMutationSequence();
|
||||
|
||||
U = ChooseUnitToMutate();
|
||||
|
||||
for (int i = 0; i < Options.MutateDepth; i++) {
|
||||
StartTraceRecording();
|
||||
size_t Size = U->size();
|
||||
U->resize(Options.MaxLen);
|
||||
size_t NewSize = USF.Mutate(U->data(), Size, U->size());
|
||||
size_t Size = U.size();
|
||||
U.resize(Options.MaxLen);
|
||||
size_t NewSize = USF.Mutate(U.data(), Size, U.size());
|
||||
assert(NewSize > 0 && "Mutator returned empty unit");
|
||||
assert(NewSize <= (size_t)Options.MaxLen &&
|
||||
"Mutator return overisized unit");
|
||||
U->resize(NewSize);
|
||||
RunOneAndUpdateCorpus(*U);
|
||||
U.resize(NewSize);
|
||||
RunOneAndUpdateCorpus(U);
|
||||
size_t NumTraceBasedMutations = StopTraceRecording();
|
||||
size_t TBMWidth =
|
||||
std::min((size_t)Options.TBMWidth, NumTraceBasedMutations);
|
||||
size_t TBMDepth =
|
||||
std::min((size_t)Options.TBMDepth, NumTraceBasedMutations);
|
||||
Unit BackUp = *U;
|
||||
Unit BackUp = U;
|
||||
for (size_t w = 0; w < TBMWidth; w++) {
|
||||
*U = BackUp;
|
||||
U = BackUp;
|
||||
for (size_t d = 0; d < TBMDepth; d++) {
|
||||
TotalNumberOfExecutedTraceBasedMutations++;
|
||||
ApplyTraceBasedMutation(USF.GetRand()(NumTraceBasedMutations), U);
|
||||
RunOneAndUpdateCorpus(*U);
|
||||
ApplyTraceBasedMutation(USF.GetRand()(NumTraceBasedMutations), &U);
|
||||
RunOneAndUpdateCorpus(U);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -465,8 +470,9 @@ void Fuzzer::Drill() {
|
||||
|
||||
void Fuzzer::Loop() {
|
||||
system_clock::time_point LastCorpusReload = system_clock::now();
|
||||
if (Options.DoCrossOver)
|
||||
USF.SetCorpus(&Corpus);
|
||||
while (true) {
|
||||
size_t J1 = ChooseUnitIdxToMutate();;
|
||||
SyncCorpus();
|
||||
auto Now = system_clock::now();
|
||||
if (duration_cast<seconds>(Now - LastCorpusReload).count()) {
|
||||
@ -479,25 +485,8 @@ void Fuzzer::Loop() {
|
||||
secondsSinceProcessStartUp() >
|
||||
static_cast<size_t>(Options.MaxTotalTimeSec))
|
||||
break;
|
||||
USF.StartMutationSequence();
|
||||
CurrentUnit = Corpus[J1];
|
||||
// Optionally, cross with another unit.
|
||||
if (Options.DoCrossOver && USF.GetRand().RandBool()) {
|
||||
size_t J2 = ChooseUnitIdxToMutate();
|
||||
if (!Corpus[J1].empty() && !Corpus[J2].empty()) {
|
||||
assert(!Corpus[J2].empty());
|
||||
CurrentUnit.resize(Options.MaxLen);
|
||||
size_t NewSize = USF.CrossOver(
|
||||
Corpus[J1].data(), Corpus[J1].size(), Corpus[J2].data(),
|
||||
Corpus[J2].size(), CurrentUnit.data(), CurrentUnit.size());
|
||||
assert(NewSize > 0 && "CrossOver returned empty unit");
|
||||
assert(NewSize <= (size_t)Options.MaxLen &&
|
||||
"CrossOver returned overisized unit");
|
||||
CurrentUnit.resize(NewSize);
|
||||
}
|
||||
}
|
||||
// Perform several mutations and runs.
|
||||
MutateAndTestOne(&CurrentUnit);
|
||||
MutateAndTestOne();
|
||||
}
|
||||
|
||||
PrintStats("DONE ", "\n");
|
||||
|
@ -26,6 +26,7 @@ struct MutationDispatcher::Impl {
|
||||
std::vector<Unit> Dictionary;
|
||||
std::vector<Mutator> Mutators;
|
||||
std::vector<Mutator> CurrentMutatorSequence;
|
||||
const std::vector<Unit> *Corpus = nullptr;
|
||||
|
||||
void Add(Mutator M) { Mutators.push_back(M); }
|
||||
Impl() {
|
||||
@ -35,6 +36,7 @@ struct MutationDispatcher::Impl {
|
||||
Add({&MutationDispatcher::Mutate_ChangeBit, "ChangeBit"});
|
||||
Add({&MutationDispatcher::Mutate_ShuffleBytes, "ShuffleBytes"});
|
||||
Add({&MutationDispatcher::Mutate_ChangeASCIIInteger, "ChangeASCIIInt"});
|
||||
Add({&MutationDispatcher::Mutate_CrossOver, "CrossOver"});
|
||||
}
|
||||
void AddWordToDictionary(const uint8_t *Word, size_t Size) {
|
||||
if (Dictionary.empty()) {
|
||||
@ -42,6 +44,7 @@ struct MutationDispatcher::Impl {
|
||||
}
|
||||
Dictionary.push_back(Unit(Word, Word + Size));
|
||||
}
|
||||
void SetCorpus(const std::vector<Unit> *Corpus) { this->Corpus = Corpus; }
|
||||
};
|
||||
|
||||
static char FlipRandomBit(char X, FuzzerRandomBase &Rand) {
|
||||
@ -154,6 +157,22 @@ size_t MutationDispatcher::Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size,
|
||||
return Size;
|
||||
}
|
||||
|
||||
size_t MutationDispatcher::Mutate_CrossOver(uint8_t *Data, size_t Size,
|
||||
size_t MaxSize) {
|
||||
auto Corpus = MDImpl->Corpus;
|
||||
if (!Corpus || Corpus->size() < 2 || Size == 0) return 0;
|
||||
size_t Idx = Rand(Corpus->size());
|
||||
const Unit &Other = (*Corpus)[Idx];
|
||||
if (Other.empty()) return 0;
|
||||
Unit U(MaxSize);
|
||||
size_t NewSize =
|
||||
CrossOver(Data, Size, Other.data(), Other.size(), U.data(), U.size());
|
||||
assert(NewSize > 0 && "CrossOver returned empty unit");
|
||||
assert(NewSize <= MaxSize && "CrossOver returned overisized unit");
|
||||
memcpy(Data, U.data(), NewSize);
|
||||
return NewSize;
|
||||
}
|
||||
|
||||
void MutationDispatcher::StartMutationSequence() {
|
||||
MDImpl->CurrentMutatorSequence.clear();
|
||||
}
|
||||
@ -189,6 +208,10 @@ size_t MutationDispatcher::Mutate(uint8_t *Data, size_t Size, size_t MaxSize) {
|
||||
return Size;
|
||||
}
|
||||
|
||||
void MutationDispatcher::SetCorpus(const std::vector<Unit> *Corpus) {
|
||||
MDImpl->SetCorpus(Corpus);
|
||||
}
|
||||
|
||||
void MutationDispatcher::AddWordToDictionary(const uint8_t *Word, size_t Size) {
|
||||
MDImpl->AddWordToDictionary(Word, Size);
|
||||
}
|
||||
|
@ -239,7 +239,7 @@ TEST(FuzzerMutate, ShuffleBytes1) {
|
||||
TestShuffleBytes(&MutationDispatcher::Mutate_ShuffleBytes, 1 << 15);
|
||||
}
|
||||
TEST(FuzzerMutate, ShuffleBytes2) {
|
||||
TestShuffleBytes(&MutationDispatcher::Mutate, 1 << 16);
|
||||
TestShuffleBytes(&MutationDispatcher::Mutate, 1 << 19);
|
||||
}
|
||||
|
||||
void TestAddWordFromDictionary(Mutator M, int NumIter) {
|
||||
|
@ -41,10 +41,10 @@ RUN: rm -rf FourIndependentBranchesTestCORPUS
|
||||
|
||||
RUN: not LLVMFuzzer-CounterTest -use_counters=1 -max_len=6 -seed=1 -timeout=15 2>&1 | FileCheck %s
|
||||
|
||||
RUN: not LLVMFuzzer-CallerCalleeTest -max_len=6 -seed=1 -timeout=15 2>&1 | FileCheck %s
|
||||
RUN: LLVMFuzzer-CallerCalleeTest -use_indir_calls=0 -max_len=6 -seed=1 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000
|
||||
RUN: not LLVMFuzzer-CallerCalleeTest -cross_over=0 -max_len=6 -seed=1 -timeout=15 2>&1 | FileCheck %s
|
||||
RUN: LLVMFuzzer-CallerCalleeTest -use_indir_calls=0 -cross_over=0 -max_len=6 -seed=1 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000
|
||||
|
||||
RUN: not LLVMFuzzer-SimpleCmpTest -use_traces=1 -seed=1 -runs=1000000 -timeout=5 2>&1 | FileCheck %s
|
||||
RUN: not LLVMFuzzer-SimpleCmpTest -use_traces=1 -seed=1 -runs=1000001 -timeout=5 2>&1 | FileCheck %s
|
||||
|
||||
RUN: not LLVMFuzzer-UserSuppliedFuzzerTest -seed=1 -timeout=15 2>&1 | FileCheck %s
|
||||
|
||||
@ -55,13 +55,13 @@ Done1000000: Done 1000000 runs in
|
||||
RUN: not LLVMFuzzer-StrncmpTest -use_traces=1 -seed=1 -runs=100000 2>&1 | FileCheck %s
|
||||
RUN: LLVMFuzzer-StrncmpTest -seed=1 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000
|
||||
|
||||
RUN: not LLVMFuzzer-StrcmpTest -use_traces=1 -seed=1 -runs=100000 2>&1 | FileCheck %s
|
||||
RUN: not LLVMFuzzer-StrcmpTest -use_traces=1 -seed=1 -runs=200000 2>&1 | FileCheck %s
|
||||
RUN: LLVMFuzzer-StrcmpTest -seed=1 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000
|
||||
|
||||
RUN: not LLVMFuzzer-SwitchTest -use_traces=1 -seed=1 -runs=1000000 2>&1 | FileCheck %s
|
||||
RUN: not LLVMFuzzer-SwitchTest -use_traces=1 -seed=1 -runs=1000002 2>&1 | FileCheck %s
|
||||
RUN: LLVMFuzzer-SwitchTest -seed=1 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000
|
||||
|
||||
RUN: not LLVMFuzzer-SimpleDictionaryTest -dict=%S/dict1.txt -seed=1 -runs=1000000 2>&1 | FileCheck %s
|
||||
RUN: not LLVMFuzzer-SimpleDictionaryTest -dict=%S/dict1.txt -seed=1 -runs=1000003 2>&1 | FileCheck %s
|
||||
RUN: LLVMFuzzer-SimpleDictionaryTest -seed=1 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000
|
||||
|
||||
RUN: not LLVMFuzzer-SimpleHashTest -use_traces=1 -seed=1 -runs=100000 2>&1 | FileCheck %s
|
||||
|
Loading…
Reference in New Issue
Block a user