[libfuzzer] hiding custom mutator handling in MutationDispatcher.

Summary: Refactoring, no functional changes.

Differential Revision: http://reviews.llvm.org/D20975

llvm-svn: 271740
This commit is contained in:
Mike Aizatsky 2016-06-03 21:34:29 +00:00
parent 0670f91a65
commit e89c6e8b16
3 changed files with 60 additions and 29 deletions

View File

@ -205,7 +205,7 @@ private:
class MutationDispatcher {
public:
MutationDispatcher(Random &Rand) : Rand(Rand) {}
MutationDispatcher(Random &Rand);
~MutationDispatcher() {}
/// Indicate that we are about to start a new sequence of mutations.
void StartMutationSequence();
@ -213,6 +213,8 @@ public:
void PrintMutationSequence();
/// Indicate that the current sequence of mutations was successfull.
void RecordSuccessfulMutationSequence();
/// Mutates data by invoking user-provided mutator.
size_t Mutate_Custom(uint8_t *Data, size_t Size, size_t MaxSize);
/// Mutates data by shuffling bytes.
size_t Mutate_ShuffleBytes(uint8_t *Data, size_t Size, size_t MaxSize);
/// Mutates data by erasing a byte.
@ -242,9 +244,12 @@ public:
/// 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.
/// Applies one of the configured 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);
/// Applies one of the default mutations. Provided as a service
/// to mutation authors.
size_t DefaultMutate(uint8_t *Data, size_t Size, size_t MaxSize);
/// Creates a cross-over of two pieces of Data, returns its size.
size_t CrossOver(const uint8_t *Data1, size_t Size1, const uint8_t *Data2,
@ -269,6 +274,11 @@ private:
size_t AddWordFromDictionary(Dictionary &D, uint8_t *Data, size_t Size,
size_t MaxSize);
size_t MutateImpl(uint8_t *Data, size_t Size, size_t MaxSize,
const std::vector<Mutator> &Mutators);
// Interface to functions that may or may not be available.
const ExternalFunctions EF;
Random &Rand;
// Dictionary provided by the user via -dict=DICT_FILE.
@ -284,7 +294,8 @@ private:
const std::vector<Unit> *Corpus = nullptr;
std::vector<uint8_t> MutateInPlaceHere;
static Mutator Mutators[];
std::vector<Mutator> Mutators;
std::vector<Mutator> DefaultMutators;
};
class Fuzzer {
@ -471,7 +482,8 @@ private:
static thread_local bool IsMyThread;
// Interface to functions that may or may not be available.
ExternalFunctions EF;
// For future use, currently not used.
const ExternalFunctions EF;
};
}; // namespace fuzzer

View File

@ -692,11 +692,7 @@ void Fuzzer::MutateAndTestOne() {
for (int i = 0; i < Options.MutateDepth; i++) {
size_t NewSize = 0;
if (EF.LLVMFuzzerCustomMutator)
NewSize = EF.LLVMFuzzerCustomMutator(CurrentUnitData, Size,
Options.MaxLen, MD.GetRand().Rand());
else
NewSize = MD.Mutate(CurrentUnitData, Size, Options.MaxLen);
NewSize = MD.Mutate(CurrentUnitData, Size, Options.MaxLen);
assert(NewSize > 0 && "Mutator returned empty unit");
assert(NewSize <= Options.MaxLen &&
"Mutator return overisized unit");
@ -816,6 +812,6 @@ extern "C" {
size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize) {
assert(fuzzer::F);
return fuzzer::F->GetMD().Mutate(Data, Size, MaxSize);
return fuzzer::F->GetMD().DefaultMutate(Data, Size, MaxSize);
}
} // extern "C"

View File

@ -18,21 +18,30 @@ namespace fuzzer {
const size_t Dictionary::kMaxDictSize;
MutationDispatcher::Mutator MutationDispatcher::Mutators[] = {
{&MutationDispatcher::Mutate_EraseByte, "EraseByte"},
{&MutationDispatcher::Mutate_InsertByte, "InsertByte"},
{&MutationDispatcher::Mutate_ChangeByte, "ChangeByte"},
{&MutationDispatcher::Mutate_ChangeBit, "ChangeBit"},
{&MutationDispatcher::Mutate_ShuffleBytes, "ShuffleBytes"},
{&MutationDispatcher::Mutate_ChangeASCIIInteger, "ChangeASCIIInt"},
{&MutationDispatcher::Mutate_CrossOver, "CrossOver"},
{&MutationDispatcher::Mutate_AddWordFromManualDictionary,
"AddFromManualDict"},
{&MutationDispatcher::Mutate_AddWordFromTemporaryAutoDictionary,
"AddFromTempAutoDict"},
{&MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary,
"AddFromPersAutoDict"},
};
MutationDispatcher::MutationDispatcher(Random &Rand) : Rand(Rand) {
DefaultMutators.insert(
DefaultMutators.begin(),
{
{&MutationDispatcher::Mutate_EraseByte, "EraseByte"},
{&MutationDispatcher::Mutate_InsertByte, "InsertByte"},
{&MutationDispatcher::Mutate_ChangeByte, "ChangeByte"},
{&MutationDispatcher::Mutate_ChangeBit, "ChangeBit"},
{&MutationDispatcher::Mutate_ShuffleBytes, "ShuffleBytes"},
{&MutationDispatcher::Mutate_ChangeASCIIInteger, "ChangeASCIIInt"},
{&MutationDispatcher::Mutate_CrossOver, "CrossOver"},
{&MutationDispatcher::Mutate_AddWordFromManualDictionary,
"AddFromManualDict"},
{&MutationDispatcher::Mutate_AddWordFromTemporaryAutoDictionary,
"AddFromTempAutoDict"},
{&MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary,
"AddFromPersAutoDict"},
});
if (EF.LLVMFuzzerCustomMutator)
Mutators.push_back({&MutationDispatcher::Mutate_Custom, "Custom"});
else
Mutators = DefaultMutators;
}
static char FlipRandomBit(char X, Random &Rand) {
int Bit = Rand(8);
@ -52,6 +61,11 @@ static char RandCh(Random &Rand) {
return Special[Rand(sizeof(Special) - 1)];
}
size_t MutationDispatcher::Mutate_Custom(uint8_t *Data, size_t Size,
size_t MaxSize) {
return EF.LLVMFuzzerCustomMutator(Data, Size, MaxSize, Rand.Rand());
}
size_t MutationDispatcher::Mutate_ShuffleBytes(uint8_t *Data, size_t Size,
size_t MaxSize) {
assert(Size);
@ -230,8 +244,19 @@ void MutationDispatcher::PrintMutationSequence() {
}
}
// Mutates Data in place, returns new size.
size_t MutationDispatcher::Mutate(uint8_t *Data, size_t Size, size_t MaxSize) {
return MutateImpl(Data, Size, MaxSize, Mutators);
}
size_t MutationDispatcher::DefaultMutate(uint8_t *Data, size_t Size,
size_t MaxSize) {
return MutateImpl(Data, Size, MaxSize, DefaultMutators);
}
// Mutates Data in place, returns new size.
size_t MutationDispatcher::MutateImpl(uint8_t *Data, size_t Size,
size_t MaxSize,
const std::vector<Mutator> &Mutators) {
assert(MaxSize > 0);
assert(Size <= MaxSize);
if (Size == 0) {
@ -244,9 +269,7 @@ 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 NumMutators = sizeof(Mutators) / sizeof(Mutators[0]);
size_t MutatorIdx = Rand(NumMutators);
auto M = Mutators[MutatorIdx];
auto M = Mutators[Rand(Mutators.size())];
size_t NewSize = (this->*(M.Fn))(Data, Size, MaxSize);
if (NewSize) {
CurrentMutatorSequence.push_back(M);