1
0
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:
Kostya Serebryany 2016-02-13 03:37:24 +00:00
parent b9687a1cc3
commit cca951bf4c
2 changed files with 114 additions and 136 deletions

View File

@ -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 {

View File

@ -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