1*0b57cec5SDimitry Andric //===- FuzzerMutate.h - Internal header for the Fuzzer ----------*- C++ -* ===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // fuzzer::MutationDispatcher 9*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 10*0b57cec5SDimitry Andric 11*0b57cec5SDimitry Andric #ifndef LLVM_FUZZER_MUTATE_H 12*0b57cec5SDimitry Andric #define LLVM_FUZZER_MUTATE_H 13*0b57cec5SDimitry Andric 14*0b57cec5SDimitry Andric #include "FuzzerDefs.h" 15*0b57cec5SDimitry Andric #include "FuzzerDictionary.h" 16*0b57cec5SDimitry Andric #include "FuzzerOptions.h" 17*0b57cec5SDimitry Andric #include "FuzzerRandom.h" 18*0b57cec5SDimitry Andric 19*0b57cec5SDimitry Andric namespace fuzzer { 20*0b57cec5SDimitry Andric 21*0b57cec5SDimitry Andric class MutationDispatcher { 22*0b57cec5SDimitry Andric public: 23*0b57cec5SDimitry Andric MutationDispatcher(Random &Rand, const FuzzingOptions &Options); 24*0b57cec5SDimitry Andric ~MutationDispatcher() {} 25*0b57cec5SDimitry Andric /// Indicate that we are about to start a new sequence of mutations. 26*0b57cec5SDimitry Andric void StartMutationSequence(); 27*0b57cec5SDimitry Andric /// Print the current sequence of mutations. 28*0b57cec5SDimitry Andric void PrintMutationSequence(); 29*0b57cec5SDimitry Andric /// Indicate that the current sequence of mutations was successful. 30*0b57cec5SDimitry Andric void RecordSuccessfulMutationSequence(); 31*0b57cec5SDimitry Andric /// Mutates data by invoking user-provided mutator. 32*0b57cec5SDimitry Andric size_t Mutate_Custom(uint8_t *Data, size_t Size, size_t MaxSize); 33*0b57cec5SDimitry Andric /// Mutates data by invoking user-provided crossover. 34*0b57cec5SDimitry Andric size_t Mutate_CustomCrossOver(uint8_t *Data, size_t Size, size_t MaxSize); 35*0b57cec5SDimitry Andric /// Mutates data by shuffling bytes. 36*0b57cec5SDimitry Andric size_t Mutate_ShuffleBytes(uint8_t *Data, size_t Size, size_t MaxSize); 37*0b57cec5SDimitry Andric /// Mutates data by erasing bytes. 38*0b57cec5SDimitry Andric size_t Mutate_EraseBytes(uint8_t *Data, size_t Size, size_t MaxSize); 39*0b57cec5SDimitry Andric /// Mutates data by inserting a byte. 40*0b57cec5SDimitry Andric size_t Mutate_InsertByte(uint8_t *Data, size_t Size, size_t MaxSize); 41*0b57cec5SDimitry Andric /// Mutates data by inserting several repeated bytes. 42*0b57cec5SDimitry Andric size_t Mutate_InsertRepeatedBytes(uint8_t *Data, size_t Size, size_t MaxSize); 43*0b57cec5SDimitry Andric /// Mutates data by chanding one byte. 44*0b57cec5SDimitry Andric size_t Mutate_ChangeByte(uint8_t *Data, size_t Size, size_t MaxSize); 45*0b57cec5SDimitry Andric /// Mutates data by chanding one bit. 46*0b57cec5SDimitry Andric size_t Mutate_ChangeBit(uint8_t *Data, size_t Size, size_t MaxSize); 47*0b57cec5SDimitry Andric /// Mutates data by copying/inserting a part of data into a different place. 48*0b57cec5SDimitry Andric size_t Mutate_CopyPart(uint8_t *Data, size_t Size, size_t MaxSize); 49*0b57cec5SDimitry Andric 50*0b57cec5SDimitry Andric /// Mutates data by adding a word from the manual dictionary. 51*0b57cec5SDimitry Andric size_t Mutate_AddWordFromManualDictionary(uint8_t *Data, size_t Size, 52*0b57cec5SDimitry Andric size_t MaxSize); 53*0b57cec5SDimitry Andric 54*0b57cec5SDimitry Andric /// Mutates data by adding a word from the TORC. 55*0b57cec5SDimitry Andric size_t Mutate_AddWordFromTORC(uint8_t *Data, size_t Size, size_t MaxSize); 56*0b57cec5SDimitry Andric 57*0b57cec5SDimitry Andric /// Mutates data by adding a word from the persistent automatic dictionary. 58*0b57cec5SDimitry Andric size_t Mutate_AddWordFromPersistentAutoDictionary(uint8_t *Data, size_t Size, 59*0b57cec5SDimitry Andric size_t MaxSize); 60*0b57cec5SDimitry Andric 61*0b57cec5SDimitry Andric /// Tries to find an ASCII integer in Data, changes it to another ASCII int. 62*0b57cec5SDimitry Andric size_t Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size, size_t MaxSize); 63*0b57cec5SDimitry Andric /// Change a 1-, 2-, 4-, or 8-byte integer in interesting ways. 64*0b57cec5SDimitry Andric size_t Mutate_ChangeBinaryInteger(uint8_t *Data, size_t Size, size_t MaxSize); 65*0b57cec5SDimitry Andric 66*0b57cec5SDimitry Andric /// CrossOver Data with CrossOverWith. 67*0b57cec5SDimitry Andric size_t Mutate_CrossOver(uint8_t *Data, size_t Size, size_t MaxSize); 68*0b57cec5SDimitry Andric 69*0b57cec5SDimitry Andric /// Applies one of the configured mutations. 70*0b57cec5SDimitry Andric /// Returns the new size of data which could be up to MaxSize. 71*0b57cec5SDimitry Andric size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize); 72*0b57cec5SDimitry Andric 73*0b57cec5SDimitry Andric /// Applies one of the configured mutations to the bytes of Data 74*0b57cec5SDimitry Andric /// that have '1' in Mask. 75*0b57cec5SDimitry Andric /// Mask.size() should be >= Size. 76*0b57cec5SDimitry Andric size_t MutateWithMask(uint8_t *Data, size_t Size, size_t MaxSize, 77*0b57cec5SDimitry Andric const Vector<uint8_t> &Mask); 78*0b57cec5SDimitry Andric 79*0b57cec5SDimitry Andric /// Applies one of the default mutations. Provided as a service 80*0b57cec5SDimitry Andric /// to mutation authors. 81*0b57cec5SDimitry Andric size_t DefaultMutate(uint8_t *Data, size_t Size, size_t MaxSize); 82*0b57cec5SDimitry Andric 83*0b57cec5SDimitry Andric /// Creates a cross-over of two pieces of Data, returns its size. 84*0b57cec5SDimitry Andric size_t CrossOver(const uint8_t *Data1, size_t Size1, const uint8_t *Data2, 85*0b57cec5SDimitry Andric size_t Size2, uint8_t *Out, size_t MaxOutSize); 86*0b57cec5SDimitry Andric 87*0b57cec5SDimitry Andric void AddWordToManualDictionary(const Word &W); 88*0b57cec5SDimitry Andric 89*0b57cec5SDimitry Andric void PrintRecommendedDictionary(); 90*0b57cec5SDimitry Andric 91*0b57cec5SDimitry Andric void SetCrossOverWith(const Unit *U) { CrossOverWith = U; } 92*0b57cec5SDimitry Andric 93*0b57cec5SDimitry Andric Random &GetRand() { return Rand; } 94*0b57cec5SDimitry Andric 95*0b57cec5SDimitry Andric private: 96*0b57cec5SDimitry Andric struct Mutator { 97*0b57cec5SDimitry Andric size_t (MutationDispatcher::*Fn)(uint8_t *Data, size_t Size, size_t Max); 98*0b57cec5SDimitry Andric const char *Name; 99*0b57cec5SDimitry Andric }; 100*0b57cec5SDimitry Andric 101*0b57cec5SDimitry Andric size_t AddWordFromDictionary(Dictionary &D, uint8_t *Data, size_t Size, 102*0b57cec5SDimitry Andric size_t MaxSize); 103*0b57cec5SDimitry Andric size_t MutateImpl(uint8_t *Data, size_t Size, size_t MaxSize, 104*0b57cec5SDimitry Andric Vector<Mutator> &Mutators); 105*0b57cec5SDimitry Andric 106*0b57cec5SDimitry Andric size_t InsertPartOf(const uint8_t *From, size_t FromSize, uint8_t *To, 107*0b57cec5SDimitry Andric size_t ToSize, size_t MaxToSize); 108*0b57cec5SDimitry Andric size_t CopyPartOf(const uint8_t *From, size_t FromSize, uint8_t *To, 109*0b57cec5SDimitry Andric size_t ToSize); 110*0b57cec5SDimitry Andric size_t ApplyDictionaryEntry(uint8_t *Data, size_t Size, size_t MaxSize, 111*0b57cec5SDimitry Andric DictionaryEntry &DE); 112*0b57cec5SDimitry Andric 113*0b57cec5SDimitry Andric template <class T> 114*0b57cec5SDimitry Andric DictionaryEntry MakeDictionaryEntryFromCMP(T Arg1, T Arg2, 115*0b57cec5SDimitry Andric const uint8_t *Data, size_t Size); 116*0b57cec5SDimitry Andric DictionaryEntry MakeDictionaryEntryFromCMP(const Word &Arg1, const Word &Arg2, 117*0b57cec5SDimitry Andric const uint8_t *Data, size_t Size); 118*0b57cec5SDimitry Andric DictionaryEntry MakeDictionaryEntryFromCMP(const void *Arg1, const void *Arg2, 119*0b57cec5SDimitry Andric const void *Arg1Mutation, 120*0b57cec5SDimitry Andric const void *Arg2Mutation, 121*0b57cec5SDimitry Andric size_t ArgSize, 122*0b57cec5SDimitry Andric const uint8_t *Data, size_t Size); 123*0b57cec5SDimitry Andric 124*0b57cec5SDimitry Andric Random &Rand; 125*0b57cec5SDimitry Andric const FuzzingOptions Options; 126*0b57cec5SDimitry Andric 127*0b57cec5SDimitry Andric // Dictionary provided by the user via -dict=DICT_FILE. 128*0b57cec5SDimitry Andric Dictionary ManualDictionary; 129*0b57cec5SDimitry Andric // Temporary dictionary modified by the fuzzer itself, 130*0b57cec5SDimitry Andric // recreated periodically. 131*0b57cec5SDimitry Andric Dictionary TempAutoDictionary; 132*0b57cec5SDimitry Andric // Persistent dictionary modified by the fuzzer, consists of 133*0b57cec5SDimitry Andric // entries that led to successful discoveries in the past mutations. 134*0b57cec5SDimitry Andric Dictionary PersistentAutoDictionary; 135*0b57cec5SDimitry Andric 136*0b57cec5SDimitry Andric Vector<DictionaryEntry *> CurrentDictionaryEntrySequence; 137*0b57cec5SDimitry Andric 138*0b57cec5SDimitry Andric static const size_t kCmpDictionaryEntriesDequeSize = 16; 139*0b57cec5SDimitry Andric DictionaryEntry CmpDictionaryEntriesDeque[kCmpDictionaryEntriesDequeSize]; 140*0b57cec5SDimitry Andric size_t CmpDictionaryEntriesDequeIdx = 0; 141*0b57cec5SDimitry Andric 142*0b57cec5SDimitry Andric const Unit *CrossOverWith = nullptr; 143*0b57cec5SDimitry Andric Vector<uint8_t> MutateInPlaceHere; 144*0b57cec5SDimitry Andric Vector<uint8_t> MutateWithMaskTemp; 145*0b57cec5SDimitry Andric // CustomCrossOver needs its own buffer as a custom implementation may call 146*0b57cec5SDimitry Andric // LLVMFuzzerMutate, which in turn may resize MutateInPlaceHere. 147*0b57cec5SDimitry Andric Vector<uint8_t> CustomCrossOverInPlaceHere; 148*0b57cec5SDimitry Andric 149*0b57cec5SDimitry Andric Vector<Mutator> Mutators; 150*0b57cec5SDimitry Andric Vector<Mutator> DefaultMutators; 151*0b57cec5SDimitry Andric Vector<Mutator> CurrentMutatorSequence; 152*0b57cec5SDimitry Andric }; 153*0b57cec5SDimitry Andric 154*0b57cec5SDimitry Andric } // namespace fuzzer 155*0b57cec5SDimitry Andric 156*0b57cec5SDimitry Andric #endif // LLVM_FUZZER_MUTATE_H 157