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