X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FFuzzer%2FFuzzerMutate.cpp;h=30e5b43c0839005f0392e99ed1088a5dba53ffef;hb=HEAD;hp=0e8429bcb2720d3698a1ec7e4347e58ee6804eda;hpb=872c556fa864f7314d97bad9b32db89496b6919e;p=oota-llvm.git diff --git a/lib/Fuzzer/FuzzerMutate.cpp b/lib/Fuzzer/FuzzerMutate.cpp index 0e8429bcb27..30e5b43c083 100644 --- a/lib/Fuzzer/FuzzerMutate.cpp +++ b/lib/Fuzzer/FuzzerMutate.cpp @@ -17,29 +17,44 @@ namespace fuzzer { -typedef size_t (MutationDispatcher::*Mutator)(uint8_t *Data, size_t Size, - size_t Max); +struct Mutator { + size_t (MutationDispatcher::*Fn)(uint8_t *Data, size_t Size, size_t Max); + const char *Name; +}; + +struct DictionaryEntry { + Unit Word; + size_t PositionHint; +}; struct MutationDispatcher::Impl { - std::vector Dictionary; + std::vector ManualDictionary; + std::vector AutoDictionary; 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); - Mutators.push_back(&MutationDispatcher::Mutate_ChangeASCIIInteger); - } - 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)); + std::vector CurrentMutatorSequence; + std::vector CurrentDictionaryEntrySequence; + const std::vector *Corpus = nullptr; + FuzzerRandomBase &Rand; + + void Add(Mutator M) { Mutators.push_back(M); } + Impl(FuzzerRandomBase &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_AddWordFromAutoDictionary, + "AddFromAutoDict"}); } + void SetCorpus(const std::vector *Corpus) { this->Corpus = Corpus; } + size_t AddWordFromDictionary(const std::vector &D, + uint8_t *Data, size_t Size, size_t MaxSize); }; - static char FlipRandomBit(char X, FuzzerRandomBase &Rand) { int Bit = Rand(8); char Mask = 1 << Bit; @@ -61,7 +76,8 @@ static char RandCh(FuzzerRandomBase &Rand) { 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 ShuffleAmount = + Rand(std::min(Size, (size_t)8)) + 1; // [1,8] and <= Size. size_t ShuffleStart = Rand(Size - ShuffleAmount); assert(ShuffleStart + ShuffleAmount <= Size); std::random_shuffle(Data + ShuffleStart, Data + ShuffleStart + ShuffleAmount, @@ -103,18 +119,42 @@ size_t MutationDispatcher::Mutate_ChangeBit(uint8_t *Data, size_t Size, return Size; } -size_t MutationDispatcher::Mutate_AddWordFromDictionary(uint8_t *Data, - size_t Size, - size_t MaxSize) { - auto &D = MDImpl->Dictionary; - assert(!D.empty()); +size_t MutationDispatcher::Mutate_AddWordFromManualDictionary(uint8_t *Data, + size_t Size, + size_t MaxSize) { + return MDImpl->AddWordFromDictionary(MDImpl->ManualDictionary, Data, Size, + MaxSize); +} + +size_t MutationDispatcher::Mutate_AddWordFromAutoDictionary(uint8_t *Data, + size_t Size, + size_t MaxSize) { + return MDImpl->AddWordFromDictionary(MDImpl->AutoDictionary, Data, Size, + MaxSize); +} + +size_t MutationDispatcher::Impl::AddWordFromDictionary( + const std::vector &D, uint8_t *Data, size_t Size, + size_t MaxSize) { 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(); + const DictionaryEntry &DE = D[Rand(D.size())]; + const Unit &Word = DE.Word; + size_t PositionHint = DE.PositionHint; + bool UsePositionHint = PositionHint != std::numeric_limits::max() && + PositionHint + Word.size() < Size && Rand.RandBool(); + if (Rand.RandBool()) { // Insert Word. + if (Size + Word.size() > MaxSize) return 0; + size_t Idx = UsePositionHint ? PositionHint : Rand(Size + 1); + memmove(Data + Idx + Word.size(), Data + Idx, Size - Idx); + memcpy(Data + Idx, Word.data(), Word.size()); + Size += Word.size(); + } else { // Overwrite some bytes with Word. + if (Word.size() > Size) return 0; + size_t Idx = UsePositionHint ? PositionHint : Rand(Size - Word.size()); + memcpy(Data + Idx, Word.data(), Word.size()); + } + CurrentDictionaryEntrySequence.push_back(DE); + return Size; } size_t MutationDispatcher::Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size, @@ -150,6 +190,40 @@ size_t MutationDispatcher::Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size, return 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]; + if (Other.empty()) return 0; + Unit U(MaxSize); + size_t NewSize = + CrossOver(Data, Size, Other.data(), Other.size(), U.data(), U.size()); + assert(NewSize > 0 && "CrossOver returned empty unit"); + assert(NewSize <= MaxSize && "CrossOver returned overisized unit"); + memcpy(Data, U.data(), NewSize); + return NewSize; +} + +void MutationDispatcher::StartMutationSequence() { + MDImpl->CurrentMutatorSequence.clear(); + MDImpl->CurrentDictionaryEntrySequence.clear(); +} + +void MutationDispatcher::PrintMutationSequence() { + Printf("MS: %zd ", MDImpl->CurrentMutatorSequence.size()); + for (auto M : MDImpl->CurrentMutatorSequence) + Printf("%s-", M.Name); + if (!MDImpl->CurrentDictionaryEntrySequence.empty()) { + Printf(" DE: "); + for (auto DE : MDImpl->CurrentDictionaryEntrySequence) { + Printf("\""); + PrintASCII(DE.Word, "\"-"); + } + } +} + // Mutates Data in place, returns new size. size_t MutationDispatcher::Mutate(uint8_t *Data, size_t Size, size_t MaxSize) { assert(MaxSize > 0); @@ -165,19 +239,38 @@ size_t MutationDispatcher::Mutate(uint8_t *Data, size_t Size, size_t MaxSize) { // 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; + auto M = MDImpl->Mutators[MutatorIdx]; + size_t NewSize = (this->*(M.Fn))(Data, Size, MaxSize); + if (NewSize) { + MDImpl->CurrentMutatorSequence.push_back(M); + return NewSize; + } } return Size; } -void MutationDispatcher::AddWordToDictionary(const uint8_t *Word, size_t Size) { - MDImpl->AddWordToDictionary(Word, Size); +void MutationDispatcher::SetCorpus(const std::vector *Corpus) { + MDImpl->SetCorpus(Corpus); +} + +void MutationDispatcher::AddWordToManualDictionary(const Unit &Word) { + MDImpl->ManualDictionary.push_back( + {Word, std::numeric_limits::max()}); +} + +void MutationDispatcher::AddWordToAutoDictionary(const Unit &Word, + size_t PositionHint) { + static const size_t kMaxAutoDictSize = 1 << 14; + if (MDImpl->AutoDictionary.size() >= kMaxAutoDictSize) return; + MDImpl->AutoDictionary.push_back({Word, PositionHint}); +} + +void MutationDispatcher::ClearAutoDictionary() { + MDImpl->AutoDictionary.clear(); } MutationDispatcher::MutationDispatcher(FuzzerRandomBase &Rand) : Rand(Rand) { - MDImpl = new Impl; + MDImpl = new Impl(Rand); } MutationDispatcher::~MutationDispatcher() { delete MDImpl; }