mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
[libFuzzer] get rid of MutationDispatcher::Impl (simplify the code; NFC)
llvm-svn: 260799
This commit is contained in:
parent
b9687a1cc3
commit
cca951bf4c
@ -12,6 +12,7 @@
|
||||
#ifndef LLVM_FUZZER_INTERNAL_H
|
||||
#define LLVM_FUZZER_INTERNAL_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <chrono>
|
||||
#include <climits>
|
||||
@ -119,10 +120,62 @@ bool ParseOneDictionaryEntry(const std::string &Str, Unit *U);
|
||||
// were parsed succesfully.
|
||||
bool ParseDictionaryFile(const std::string &Text, std::vector<Unit> *Units);
|
||||
|
||||
class DictionaryEntry {
|
||||
public:
|
||||
DictionaryEntry() {}
|
||||
DictionaryEntry(Word W) : W(W) {}
|
||||
DictionaryEntry(Word W, size_t PositionHint) : W(W), PositionHint(PositionHint) {}
|
||||
const Word &GetW() const { return W; }
|
||||
|
||||
bool HasPositionHint() const { return PositionHint != std::numeric_limits<size_t>::max(); }
|
||||
size_t GetPositionHint() const {
|
||||
assert(HasPositionHint());
|
||||
return PositionHint;
|
||||
}
|
||||
void IncUseCount() { UseCount++; }
|
||||
void IncSuccessCount() { SuccessCount++; }
|
||||
size_t GetUseCount() const { return UseCount; }
|
||||
size_t GetSuccessCount() const {return SuccessCount; }
|
||||
|
||||
private:
|
||||
Word W;
|
||||
size_t PositionHint = std::numeric_limits<size_t>::max();
|
||||
size_t UseCount = 0;
|
||||
size_t SuccessCount = 0;
|
||||
};
|
||||
|
||||
class Dictionary {
|
||||
public:
|
||||
static const size_t kMaxDictSize = 1 << 14;
|
||||
|
||||
bool ContainsWord(const Word &W) const {
|
||||
return std::any_of(begin(), end(), [&](const DictionaryEntry &DE) {
|
||||
return DE.GetW() == W;
|
||||
});
|
||||
}
|
||||
const DictionaryEntry *begin() const { return &DE[0]; }
|
||||
const DictionaryEntry *end() const { return begin() + Size; }
|
||||
DictionaryEntry & operator[] (size_t Idx) {
|
||||
assert(Idx < Size);
|
||||
return DE[Idx];
|
||||
}
|
||||
void push_back(DictionaryEntry DE) {
|
||||
if (Size < kMaxDictSize)
|
||||
this->DE[Size++] = DE;
|
||||
}
|
||||
void clear() { Size = 0; }
|
||||
bool empty() const { return Size == 0; }
|
||||
size_t size() const { return Size; }
|
||||
|
||||
private:
|
||||
DictionaryEntry DE[kMaxDictSize];
|
||||
size_t Size = 0;
|
||||
};
|
||||
|
||||
class MutationDispatcher {
|
||||
public:
|
||||
MutationDispatcher(Random &Rand);
|
||||
~MutationDispatcher();
|
||||
~MutationDispatcher() {}
|
||||
/// Indicate that we are about to start a new sequence of mutations.
|
||||
void StartMutationSequence();
|
||||
/// Print the current sequence of mutations.
|
||||
@ -172,14 +225,34 @@ public:
|
||||
void ClearAutoDictionary();
|
||||
void PrintRecommendedDictionary();
|
||||
|
||||
void SetCorpus(const std::vector<Unit> *Corpus);
|
||||
void SetCorpus(const std::vector<Unit> *Corpus) { this->Corpus = Corpus; }
|
||||
|
||||
Random &GetRand() { return Rand; }
|
||||
|
||||
private:
|
||||
|
||||
struct Mutator {
|
||||
size_t (MutationDispatcher::*Fn)(uint8_t *Data, size_t Size, size_t Max);
|
||||
const char *Name;
|
||||
};
|
||||
|
||||
void Add(Mutator M) { Mutators.push_back(M); }
|
||||
size_t AddWordFromDictionary(Dictionary &D, uint8_t *Data, size_t Size,
|
||||
size_t MaxSize);
|
||||
|
||||
Random &Rand;
|
||||
struct Impl;
|
||||
Impl *MDImpl;
|
||||
// Dictionary provided by the user via -dict=DICT_FILE.
|
||||
Dictionary ManualDictionary;
|
||||
// Temporary dictionary modified by the fuzzer itself,
|
||||
// recreated periodically.
|
||||
Dictionary TempAutoDictionary;
|
||||
// Persistent dictionary modified by the fuzzer, consists of
|
||||
// entries that led to successfull discoveries in the past mutations.
|
||||
Dictionary PersistentAutoDictionary;
|
||||
std::vector<Mutator> Mutators;
|
||||
std::vector<Mutator> CurrentMutatorSequence;
|
||||
std::vector<DictionaryEntry *> CurrentDictionaryEntrySequence;
|
||||
const std::vector<Unit> *Corpus = nullptr;
|
||||
};
|
||||
|
||||
class Fuzzer {
|
||||
|
@ -13,107 +13,11 @@
|
||||
|
||||
#include "FuzzerInternal.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace fuzzer {
|
||||
|
||||
struct Mutator {
|
||||
size_t (MutationDispatcher::*Fn)(uint8_t *Data, size_t Size, size_t Max);
|
||||
const char *Name;
|
||||
};
|
||||
|
||||
class DictionaryEntry {
|
||||
public:
|
||||
DictionaryEntry() {}
|
||||
DictionaryEntry(Word W) : W(W) {}
|
||||
DictionaryEntry(Word W, size_t PositionHint) : W(W), PositionHint(PositionHint) {}
|
||||
const Word &GetW() const { return W; }
|
||||
|
||||
bool HasPositionHint() const { return PositionHint != std::numeric_limits<size_t>::max(); }
|
||||
size_t GetPositionHint() const {
|
||||
assert(HasPositionHint());
|
||||
return PositionHint;
|
||||
}
|
||||
void IncUseCount() { UseCount++; }
|
||||
void IncSuccessCount() { SuccessCount++; }
|
||||
size_t GetUseCount() const { return UseCount; }
|
||||
size_t GetSuccessCount() const {return SuccessCount; }
|
||||
|
||||
private:
|
||||
Word W;
|
||||
size_t PositionHint = std::numeric_limits<size_t>::max();
|
||||
size_t UseCount = 0;
|
||||
size_t SuccessCount = 0;
|
||||
};
|
||||
|
||||
class Dictionary {
|
||||
public:
|
||||
static const size_t kMaxDictSize = 1 << 14;
|
||||
|
||||
bool ContainsWord(const Word &W) const {
|
||||
return std::any_of(begin(), end(), [&](const DictionaryEntry &DE) {
|
||||
return DE.GetW() == W;
|
||||
});
|
||||
}
|
||||
const DictionaryEntry *begin() const { return &DE[0]; }
|
||||
const DictionaryEntry *end() const { return begin() + Size; }
|
||||
DictionaryEntry & operator[] (size_t Idx) {
|
||||
assert(Idx < Size);
|
||||
return DE[Idx];
|
||||
}
|
||||
void push_back(DictionaryEntry DE) {
|
||||
if (Size < kMaxDictSize)
|
||||
this->DE[Size++] = DE;
|
||||
}
|
||||
void clear() { Size = 0; }
|
||||
bool empty() const { return Size == 0; }
|
||||
size_t size() const { return Size; }
|
||||
|
||||
private:
|
||||
DictionaryEntry DE[kMaxDictSize];
|
||||
size_t Size = 0;
|
||||
};
|
||||
|
||||
const size_t Dictionary::kMaxDictSize;
|
||||
|
||||
|
||||
struct MutationDispatcher::Impl {
|
||||
// Dictionary provided by the user via -dict=DICT_FILE.
|
||||
Dictionary ManualDictionary;
|
||||
// Temporary dictionary modified by the fuzzer itself,
|
||||
// recreated periodically.
|
||||
Dictionary TempAutoDictionary;
|
||||
// Persistent dictionary modified by the fuzzer, consists of
|
||||
// entries that led to successfull discoveries in the past mutations.
|
||||
Dictionary PersistentAutoDictionary;
|
||||
|
||||
std::vector<Mutator> Mutators;
|
||||
std::vector<Mutator> CurrentMutatorSequence;
|
||||
std::vector<DictionaryEntry *> CurrentDictionaryEntrySequence;
|
||||
const std::vector<Unit> *Corpus = nullptr;
|
||||
Random &Rand;
|
||||
|
||||
void Add(Mutator M) { Mutators.push_back(M); }
|
||||
Impl(Random &Rand) : Rand(Rand) {
|
||||
Add({&MutationDispatcher::Mutate_EraseByte, "EraseByte"});
|
||||
Add({&MutationDispatcher::Mutate_InsertByte, "InsertByte"});
|
||||
Add({&MutationDispatcher::Mutate_ChangeByte, "ChangeByte"});
|
||||
Add({&MutationDispatcher::Mutate_ChangeBit, "ChangeBit"});
|
||||
Add({&MutationDispatcher::Mutate_ShuffleBytes, "ShuffleBytes"});
|
||||
Add({&MutationDispatcher::Mutate_ChangeASCIIInteger, "ChangeASCIIInt"});
|
||||
Add({&MutationDispatcher::Mutate_CrossOver, "CrossOver"});
|
||||
Add({&MutationDispatcher::Mutate_AddWordFromManualDictionary,
|
||||
"AddFromManualDict"});
|
||||
Add({&MutationDispatcher::Mutate_AddWordFromTemporaryAutoDictionary,
|
||||
"AddFromTempAutoDict"});
|
||||
Add({&MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary,
|
||||
"AddFromPersAutoDict"});
|
||||
}
|
||||
void SetCorpus(const std::vector<Unit> *Corpus) { this->Corpus = Corpus; }
|
||||
size_t AddWordFromDictionary(Dictionary &D, uint8_t *Data, size_t Size,
|
||||
size_t MaxSize);
|
||||
};
|
||||
|
||||
size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize, unsigned int Seed) {
|
||||
Random R(Seed);
|
||||
MutationDispatcher MD(R);
|
||||
@ -187,26 +91,21 @@ size_t MutationDispatcher::Mutate_ChangeBit(uint8_t *Data, size_t Size,
|
||||
size_t MutationDispatcher::Mutate_AddWordFromManualDictionary(uint8_t *Data,
|
||||
size_t Size,
|
||||
size_t MaxSize) {
|
||||
return MDImpl->AddWordFromDictionary(MDImpl->ManualDictionary, Data, Size,
|
||||
MaxSize);
|
||||
return AddWordFromDictionary(ManualDictionary, Data, Size, MaxSize);
|
||||
}
|
||||
|
||||
size_t MutationDispatcher::Mutate_AddWordFromTemporaryAutoDictionary(
|
||||
uint8_t *Data, size_t Size, size_t MaxSize) {
|
||||
return MDImpl->AddWordFromDictionary(MDImpl->TempAutoDictionary, Data, Size,
|
||||
MaxSize);
|
||||
return AddWordFromDictionary(TempAutoDictionary, Data, Size, MaxSize);
|
||||
}
|
||||
|
||||
size_t MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary(
|
||||
uint8_t *Data, size_t Size, size_t MaxSize) {
|
||||
return MDImpl->AddWordFromDictionary(MDImpl->PersistentAutoDictionary, Data, Size,
|
||||
MaxSize);
|
||||
return AddWordFromDictionary(PersistentAutoDictionary, Data, Size, MaxSize);
|
||||
}
|
||||
|
||||
size_t MutationDispatcher::Impl::AddWordFromDictionary(Dictionary &D,
|
||||
uint8_t *Data,
|
||||
size_t Size,
|
||||
size_t MaxSize) {
|
||||
size_t MutationDispatcher::AddWordFromDictionary(Dictionary &D, uint8_t *Data,
|
||||
size_t Size, size_t MaxSize) {
|
||||
if (D.empty()) return 0;
|
||||
DictionaryEntry &DE = D[Rand(D.size())];
|
||||
const Word &W = DE.GetW();
|
||||
@ -263,7 +162,6 @@ size_t MutationDispatcher::Mutate_ChangeASCIIInteger(uint8_t *Data, size_t 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];
|
||||
@ -278,25 +176,25 @@ size_t MutationDispatcher::Mutate_CrossOver(uint8_t *Data, size_t Size,
|
||||
}
|
||||
|
||||
void MutationDispatcher::StartMutationSequence() {
|
||||
MDImpl->CurrentMutatorSequence.clear();
|
||||
MDImpl->CurrentDictionaryEntrySequence.clear();
|
||||
CurrentMutatorSequence.clear();
|
||||
CurrentDictionaryEntrySequence.clear();
|
||||
}
|
||||
|
||||
// Copy successful dictionary entries to PersistentAutoDictionary.
|
||||
void MutationDispatcher::RecordSuccessfulMutationSequence() {
|
||||
for (auto DE : MDImpl->CurrentDictionaryEntrySequence) {
|
||||
// MDImpl->PersistentAutoDictionary.AddWithSuccessCountOne(DE);
|
||||
for (auto DE : CurrentDictionaryEntrySequence) {
|
||||
// PersistentAutoDictionary.AddWithSuccessCountOne(DE);
|
||||
DE->IncSuccessCount();
|
||||
// Linear search is fine here as this happens seldom.
|
||||
if (!MDImpl->PersistentAutoDictionary.ContainsWord(DE->GetW()))
|
||||
MDImpl->PersistentAutoDictionary.push_back({DE->GetW(), 1});
|
||||
if (!PersistentAutoDictionary.ContainsWord(DE->GetW()))
|
||||
PersistentAutoDictionary.push_back({DE->GetW(), 1});
|
||||
}
|
||||
}
|
||||
|
||||
void MutationDispatcher::PrintRecommendedDictionary() {
|
||||
std::vector<DictionaryEntry> V;
|
||||
for (auto &DE : MDImpl->PersistentAutoDictionary)
|
||||
if (!MDImpl->ManualDictionary.ContainsWord(DE.GetW()))
|
||||
for (auto &DE : PersistentAutoDictionary)
|
||||
if (!ManualDictionary.ContainsWord(DE.GetW()))
|
||||
V.push_back(DE);
|
||||
if (V.empty()) return;
|
||||
Printf("###### Recommended dictionary. ######\n");
|
||||
@ -309,12 +207,12 @@ void MutationDispatcher::PrintRecommendedDictionary() {
|
||||
}
|
||||
|
||||
void MutationDispatcher::PrintMutationSequence() {
|
||||
Printf("MS: %zd ", MDImpl->CurrentMutatorSequence.size());
|
||||
for (auto M : MDImpl->CurrentMutatorSequence)
|
||||
Printf("MS: %zd ", CurrentMutatorSequence.size());
|
||||
for (auto M : CurrentMutatorSequence)
|
||||
Printf("%s-", M.Name);
|
||||
if (!MDImpl->CurrentDictionaryEntrySequence.empty()) {
|
||||
if (!CurrentDictionaryEntrySequence.empty()) {
|
||||
Printf(" DE: ");
|
||||
for (auto DE : MDImpl->CurrentDictionaryEntrySequence) {
|
||||
for (auto DE : CurrentDictionaryEntrySequence) {
|
||||
Printf("\"");
|
||||
PrintASCII(DE->GetW(), "\"-");
|
||||
}
|
||||
@ -335,41 +233,48 @@ size_t MutationDispatcher::Mutate(uint8_t *Data, size_t Size, size_t MaxSize) {
|
||||
// in which case they will return 0.
|
||||
// Try several times before returning un-mutated data.
|
||||
for (int Iter = 0; Iter < 10; Iter++) {
|
||||
size_t MutatorIdx = Rand(MDImpl->Mutators.size());
|
||||
auto M = MDImpl->Mutators[MutatorIdx];
|
||||
size_t MutatorIdx = Rand(Mutators.size());
|
||||
auto M = Mutators[MutatorIdx];
|
||||
size_t NewSize = (this->*(M.Fn))(Data, Size, MaxSize);
|
||||
if (NewSize) {
|
||||
MDImpl->CurrentMutatorSequence.push_back(M);
|
||||
CurrentMutatorSequence.push_back(M);
|
||||
return NewSize;
|
||||
}
|
||||
}
|
||||
return Size;
|
||||
}
|
||||
|
||||
void MutationDispatcher::SetCorpus(const std::vector<Unit> *Corpus) {
|
||||
MDImpl->SetCorpus(Corpus);
|
||||
}
|
||||
|
||||
void MutationDispatcher::AddWordToManualDictionary(const Word &W) {
|
||||
MDImpl->ManualDictionary.push_back(
|
||||
ManualDictionary.push_back(
|
||||
{W, std::numeric_limits<size_t>::max()});
|
||||
}
|
||||
|
||||
void MutationDispatcher::AddWordToAutoDictionary(const Word &W,
|
||||
size_t PositionHint) {
|
||||
static const size_t kMaxAutoDictSize = 1 << 14;
|
||||
if (MDImpl->TempAutoDictionary.size() >= kMaxAutoDictSize) return;
|
||||
MDImpl->TempAutoDictionary.push_back({W, PositionHint});
|
||||
if (TempAutoDictionary.size() >= kMaxAutoDictSize) return;
|
||||
TempAutoDictionary.push_back({W, PositionHint});
|
||||
}
|
||||
|
||||
void MutationDispatcher::ClearAutoDictionary() {
|
||||
MDImpl->TempAutoDictionary.clear();
|
||||
TempAutoDictionary.clear();
|
||||
}
|
||||
|
||||
MutationDispatcher::MutationDispatcher(Random &Rand) : Rand(Rand) {
|
||||
MDImpl = new Impl(Rand);
|
||||
Add({&MutationDispatcher::Mutate_EraseByte, "EraseByte"});
|
||||
Add({&MutationDispatcher::Mutate_InsertByte, "InsertByte"});
|
||||
Add({&MutationDispatcher::Mutate_ChangeByte, "ChangeByte"});
|
||||
Add({&MutationDispatcher::Mutate_ChangeBit, "ChangeBit"});
|
||||
Add({&MutationDispatcher::Mutate_ShuffleBytes, "ShuffleBytes"});
|
||||
Add({&MutationDispatcher::Mutate_ChangeASCIIInteger, "ChangeASCIIInt"});
|
||||
Add({&MutationDispatcher::Mutate_CrossOver, "CrossOver"});
|
||||
Add({&MutationDispatcher::Mutate_AddWordFromManualDictionary,
|
||||
"AddFromManualDict"});
|
||||
Add({&MutationDispatcher::Mutate_AddWordFromTemporaryAutoDictionary,
|
||||
"AddFromTempAutoDict"});
|
||||
Add({&MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary,
|
||||
"AddFromPersAutoDict"});
|
||||
}
|
||||
|
||||
MutationDispatcher::~MutationDispatcher() { delete MDImpl; }
|
||||
|
||||
} // namespace fuzzer
|
||||
|
Loading…
Reference in New Issue
Block a user