class MutationDispatcher {
public:
- MutationDispatcher(FuzzerRandomBase &Rand) : Rand(Rand) {}
+ MutationDispatcher(FuzzerRandomBase &Rand);
+ ~MutationDispatcher();
/// Mutates data by shuffling bytes.
size_t Mutate_ShuffleBytes(uint8_t *Data, size_t Size, size_t MaxSize);
/// Mutates data by erasing a byte.
/// Mutates data by chanding one bit.
size_t Mutate_ChangeBit(uint8_t *Data, size_t Size, size_t MaxSize);
+ /// Mutates data by adding a word from the dictionary.
+ size_t Mutate_AddWordFromDictionary(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);
size_t CrossOver(const uint8_t *Data1, size_t Size1, const uint8_t *Data2,
size_t Size2, uint8_t *Out, size_t MaxOutSize);
+ void AddWordToDictionary(const uint8_t *Word, size_t Size);
+
private:
FuzzerRandomBase &Rand;
+ struct Impl;
+ Impl *MDImpl;
};
// For backward compatibility only, deprecated.
FuzzerRandomBase &GetRand() { return *Rand; }
+ MutationDispatcher &GetMD() { return MD; }
+
private:
bool OwnRand = false;
FuzzerRandomBase *Rand;
namespace fuzzer {
+typedef size_t (MutationDispatcher::*Mutator)(uint8_t *Data, size_t Size,
+ size_t Max);
+
+struct MutationDispatcher::Impl {
+ std::vector<Unit> Dictionary;
+ std::vector<Mutator> Mutators;
+ Impl() {
+ Mutators.push_back(&MutationDispatcher::Mutate_EraseByte);
+ Mutators.push_back(&MutationDispatcher::Mutate_InsertByte);
+ Mutators.push_back(&MutationDispatcher::Mutate_ChangeByte);
+ Mutators.push_back(&MutationDispatcher::Mutate_ChangeBit);
+ Mutators.push_back(&MutationDispatcher::Mutate_ShuffleBytes);
+ }
+ void AddWordToDictionary(const uint8_t *Word, size_t Size) {
+ if (Dictionary.empty()) {
+ Mutators.push_back(&MutationDispatcher::Mutate_AddWordFromDictionary);
+ }
+ Dictionary.push_back(Unit(Word, Word + Size));
+ }
+};
+
+
static char FlipRandomBit(char X, FuzzerRandomBase &Rand) {
int Bit = Rand(8);
char Mask = 1 << Bit;
return Size;
}
+size_t MutationDispatcher::Mutate_AddWordFromDictionary(uint8_t *Data,
+ size_t Size,
+ size_t MaxSize) {
+ auto &D = MDImpl->Dictionary;
+ if (D.empty()) return Size; // FIXME: indicate failure.
+ const Unit &Word = D[Rand(D.size())];
+ if (Size + Word.size() > MaxSize) return Size;
+ size_t Idx = Rand(Size + 1);
+ memmove(Data + Idx + Word.size(), Data + Idx, Size - Idx);
+ memcpy(Data + Idx, Word.data(), Word.size());
+ return Size + Word.size();
+}
+
// Mutates Data in place, returns new size.
size_t MutationDispatcher::Mutate(uint8_t *Data, size_t Size, size_t MaxSize) {
assert(MaxSize > 0);
return MaxSize;
}
assert(Size > 0);
- switch (Rand(5)) {
- case 0: Size = Mutate_EraseByte(Data, Size, MaxSize); break;
- case 1: Size = Mutate_InsertByte(Data, Size, MaxSize); break;
- case 2: Size = Mutate_ChangeByte(Data, Size, MaxSize); break;
- case 3: Size = Mutate_ChangeBit(Data, Size, MaxSize); break;
- case 4: Size = Mutate_ShuffleBytes(Data, Size, MaxSize); break;
- }
+ size_t MutatorIdx = Rand(MDImpl->Mutators.size());
+ Size = (this->*(MDImpl->Mutators[MutatorIdx]))(Data, Size, MaxSize);
assert(Size > 0);
return Size;
}
+void MutationDispatcher::AddWordToDictionary(const uint8_t *Word, size_t Size) {
+ MDImpl->AddWordToDictionary(Word, Size);
+}
+
+MutationDispatcher::MutationDispatcher(FuzzerRandomBase &Rand) : Rand(Rand) {
+ MDImpl = new Impl;
+}
+
+MutationDispatcher::~MutationDispatcher() { delete MDImpl; }
+
} // namespace fuzzer
EXPECT_EQ(FoundMask, 255);
}
-TEST(FuzzerMutate, EraseByte1) { TestEraseByte(&MutationDispatcher::Mutate_EraseByte, 100); }
-TEST(FuzzerMutate, EraseByte2) { TestEraseByte(&MutationDispatcher::Mutate, 1000); }
+TEST(FuzzerMutate, EraseByte1) {
+ TestEraseByte(&MutationDispatcher::Mutate_EraseByte, 100);
+}
+TEST(FuzzerMutate, EraseByte2) {
+ TestEraseByte(&MutationDispatcher::Mutate, 1000);
+}
void TestInsertByte(Mutator M, int NumIter) {
FuzzerRandomLibc Rand(0);
EXPECT_EQ(FoundMask, 255);
}
-TEST(FuzzerMutate, InsertByte1) { TestInsertByte(&MutationDispatcher::Mutate_InsertByte, 1 << 15); }
-TEST(FuzzerMutate, InsertByte2) { TestInsertByte(&MutationDispatcher::Mutate, 1 << 17); }
+TEST(FuzzerMutate, InsertByte1) {
+ TestInsertByte(&MutationDispatcher::Mutate_InsertByte, 1 << 15);
+}
+TEST(FuzzerMutate, InsertByte2) {
+ TestInsertByte(&MutationDispatcher::Mutate, 1 << 17);
+}
void TestChangeByte(Mutator M, int NumIter) {
FuzzerRandomLibc Rand(0);
EXPECT_EQ(FoundMask, 255);
}
-TEST(FuzzerMutate, ChangeByte1) { TestChangeByte(&MutationDispatcher::Mutate_ChangeByte, 1 << 15); }
-TEST(FuzzerMutate, ChangeByte2) { TestChangeByte(&MutationDispatcher::Mutate, 1 << 17); }
+TEST(FuzzerMutate, ChangeByte1) {
+ TestChangeByte(&MutationDispatcher::Mutate_ChangeByte, 1 << 15);
+}
+TEST(FuzzerMutate, ChangeByte2) {
+ TestChangeByte(&MutationDispatcher::Mutate, 1 << 17);
+}
void TestChangeBit(Mutator M, int NumIter) {
FuzzerRandomLibc Rand(0);
EXPECT_EQ(FoundMask, 255);
}
-TEST(FuzzerMutate, ChangeBit1) { TestChangeBit(&MutationDispatcher::Mutate_ChangeBit, 1 << 16); }
-TEST(FuzzerMutate, ChangeBit2) { TestChangeBit(&MutationDispatcher::Mutate, 1 << 18); }
+TEST(FuzzerMutate, ChangeBit1) {
+ TestChangeBit(&MutationDispatcher::Mutate_ChangeBit, 1 << 16);
+}
+TEST(FuzzerMutate, ChangeBit2) {
+ TestChangeBit(&MutationDispatcher::Mutate, 1 << 18);
+}
void TestShuffleBytes(Mutator M, int NumIter) {
FuzzerRandomLibc Rand(0);
EXPECT_EQ(FoundMask, 31);
}
-TEST(FuzzerMutate, ShuffleBytes1) { TestShuffleBytes(&MutationDispatcher::Mutate_ShuffleBytes, 1 << 15); }
-TEST(FuzzerMutate, ShuffleBytes2) { TestShuffleBytes(&MutationDispatcher::Mutate, 1 << 16); }
+TEST(FuzzerMutate, ShuffleBytes1) {
+ TestShuffleBytes(&MutationDispatcher::Mutate_ShuffleBytes, 1 << 15);
+}
+TEST(FuzzerMutate, ShuffleBytes2) {
+ TestShuffleBytes(&MutationDispatcher::Mutate, 1 << 16);
+}
+
+void TestAddWordFromDictionary(Mutator M, int NumIter) {
+ FuzzerRandomLibc Rand(0);
+ MutationDispatcher MD(Rand);
+ uint8_t Word1[4] = {0xAA, 0xBB, 0xCC, 0xDD};
+ uint8_t Word2[3] = {0xFF, 0xEE, 0xEF};
+ MD.AddWordToDictionary(Word1, sizeof(Word1));
+ MD.AddWordToDictionary(Word2, sizeof(Word2));
+ int FoundMask = 0;
+ uint8_t CH0[7] = {0x00, 0x11, 0x22, 0xAA, 0xBB, 0xCC, 0xDD};
+ uint8_t CH1[7] = {0x00, 0x11, 0xAA, 0xBB, 0xCC, 0xDD, 0x22};
+ uint8_t CH2[7] = {0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0x11, 0x22};
+ uint8_t CH3[7] = {0xAA, 0xBB, 0xCC, 0xDD, 0x00, 0x11, 0x22};
+ uint8_t CH4[6] = {0x00, 0x11, 0x22, 0xFF, 0xEE, 0xEF};
+ uint8_t CH5[6] = {0x00, 0x11, 0xFF, 0xEE, 0xEF, 0x22};
+ uint8_t CH6[6] = {0x00, 0xFF, 0xEE, 0xEF, 0x11, 0x22};
+ uint8_t CH7[6] = {0xFF, 0xEE, 0xEF, 0x00, 0x11, 0x22};
+ for (int i = 0; i < NumIter; i++) {
+ uint8_t T[7] = {0x00, 0x11, 0x22};
+ size_t NewSize = (MD.*M)(T, 3, 7);
+ if (NewSize == 7 && !memcmp(CH0, T, 7)) FoundMask |= 1 << 0;
+ if (NewSize == 7 && !memcmp(CH1, T, 7)) FoundMask |= 1 << 1;
+ if (NewSize == 7 && !memcmp(CH2, T, 7)) FoundMask |= 1 << 2;
+ if (NewSize == 7 && !memcmp(CH3, T, 7)) FoundMask |= 1 << 3;
+ if (NewSize == 6 && !memcmp(CH4, T, 6)) FoundMask |= 1 << 4;
+ if (NewSize == 6 && !memcmp(CH5, T, 6)) FoundMask |= 1 << 5;
+ if (NewSize == 6 && !memcmp(CH6, T, 6)) FoundMask |= 1 << 6;
+ if (NewSize == 6 && !memcmp(CH7, T, 6)) FoundMask |= 1 << 7;
+ }
+ EXPECT_EQ(FoundMask, 255);
+}
+
+TEST(FuzzerMutate, AddWordFromDictionary1) {
+ TestAddWordFromDictionary(&MutationDispatcher::Mutate_AddWordFromDictionary,
+ 1 << 15);
+}
+
+TEST(FuzzerMutate, AddWordFromDictionary2) {
+ TestAddWordFromDictionary(&MutationDispatcher::Mutate, 1 << 15);
+}
TEST(FuzzerDictionary, ParseOneDictionaryEntry) {
Unit U;