X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;ds=sidebyside;f=lib%2FFuzzer%2FFuzzerMutate.cpp;h=9b2015be8691227f2cbc912473f92854a0702bbc;hb=c18fae603d1cd7059695b48de45f7a875f84d7ff;hp=2db8fac9bc69ff05adc734b68d4e5ee0fa02608b;hpb=94879c0134b8488ebf30770d96436c4e9072d484;p=oota-llvm.git diff --git a/lib/Fuzzer/FuzzerMutate.cpp b/lib/Fuzzer/FuzzerMutate.cpp index 2db8fac9bc6..9b2015be869 100644 --- a/lib/Fuzzer/FuzzerMutate.cpp +++ b/lib/Fuzzer/FuzzerMutate.cpp @@ -9,12 +9,38 @@ // Mutate a test input. //===----------------------------------------------------------------------===// +#include + #include "FuzzerInternal.h" +#include + namespace fuzzer { -static char FlipRandomBit(char X) { - int Bit = rand() % 8; +typedef size_t (MutationDispatcher::*Mutator)(uint8_t *Data, size_t Size, + size_t Max); + +struct MutationDispatcher::Impl { + std::vector Dictionary; + std::vector 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; char R; if (X & (1 << Bit)) @@ -25,38 +51,101 @@ static char FlipRandomBit(char X) { return R; } -static char RandCh() { - if (rand() % 2) return rand(); +static char RandCh(FuzzerRandomBase &Rand) { + if (Rand.RandBool()) return Rand(256); const char *Special = "!*'();:@&=+$,/?%#[]123ABCxyz-`~."; - return Special[rand() % (sizeof(Special) - 1)]; -} - -void Mutate(Unit *U, size_t MaxLen) { - assert(MaxLen > 0); - assert(U->size() <= MaxLen); - switch (rand() % 3) { - case 0: - if (U->size()) - U->erase(U->begin() + rand() % U->size()); - break; - case 1: - if (U->empty()) { - U->push_back(RandCh()); - } else if (U->size() < MaxLen) { - U->insert(U->begin() + rand() % U->size(), RandCh()); - } else { // At MaxLen. - uint8_t Ch = RandCh(); - size_t Idx = rand() % U->size(); - (*U)[Idx] = Ch; - } - break; - default: - if (!U->empty()) { - size_t idx = rand() % U->size(); - (*U)[idx] = FlipRandomBit((*U)[idx]); - } - break; + return Special[Rand(sizeof(Special) - 1)]; +} + +size_t MutationDispatcher::Mutate_ShuffleBytes(uint8_t *Data, size_t Size, + size_t MaxSize) { + assert(Size); + size_t ShuffleAmount = Rand(std::min(Size, 8UL)) + 1; // [1,8] and <= Size. + size_t ShuffleStart = Rand(Size - ShuffleAmount); + assert(ShuffleStart + ShuffleAmount <= Size); + std::random_shuffle(Data + ShuffleStart, Data + ShuffleStart + ShuffleAmount, + Rand); + return Size; +} + +size_t MutationDispatcher::Mutate_EraseByte(uint8_t *Data, size_t Size, + size_t MaxSize) { + assert(Size); + if (Size == 1) return 0; + size_t Idx = Rand(Size); + // Erase Data[Idx]. + memmove(Data + Idx, Data + Idx + 1, Size - Idx - 1); + return Size - 1; +} + +size_t MutationDispatcher::Mutate_InsertByte(uint8_t *Data, size_t Size, + size_t MaxSize) { + if (Size == MaxSize) return 0; + size_t Idx = Rand(Size + 1); + // Insert new value at Data[Idx]. + memmove(Data + Idx + 1, Data + Idx, Size - Idx); + Data[Idx] = RandCh(Rand); + return Size + 1; +} + +size_t MutationDispatcher::Mutate_ChangeByte(uint8_t *Data, size_t Size, + size_t MaxSize) { + size_t Idx = Rand(Size); + Data[Idx] = RandCh(Rand); + return Size; +} + +size_t MutationDispatcher::Mutate_ChangeBit(uint8_t *Data, size_t Size, + size_t MaxSize) { + size_t Idx = Rand(Size); + Data[Idx] = FlipRandomBit(Data[Idx], Rand); + return Size; +} + +size_t MutationDispatcher::Mutate_AddWordFromDictionary(uint8_t *Data, + size_t Size, + size_t MaxSize) { + auto &D = MDImpl->Dictionary; + assert(!D.empty()); + if (D.empty()) return 0; + const Unit &Word = D[Rand(D.size())]; + if (Size + Word.size() > MaxSize) return 0; + 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); + assert(Size <= MaxSize); + if (Size == 0) { + for (size_t i = 0; i < MaxSize; i++) + Data[i] = RandCh(Rand); + return MaxSize; + } + assert(Size > 0); + // Some mutations may fail (e.g. can't insert more bytes if Size == 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()); + size_t NewSize = + (this->*(MDImpl->Mutators[MutatorIdx]))(Data, Size, MaxSize); + if (NewSize) return NewSize; } + 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