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. 28 void PrintMutationSequence(); 29 /// Indicate that the current sequence of mutations was successful. 30 void RecordSuccessfulMutationSequence(); 31 /// Mutates data by invoking user-provided mutator. 32 size_t Mutate_Custom(uint8_t *Data, size_t Size, size_t MaxSize); 33 /// Mutates data by invoking user-provided crossover. 34 size_t Mutate_CustomCrossOver(uint8_t *Data, size_t Size, size_t MaxSize); 35 /// Mutates data by shuffling bytes. 36 size_t Mutate_ShuffleBytes(uint8_t *Data, size_t Size, size_t MaxSize); 37 /// Mutates data by erasing bytes. 38 size_t Mutate_EraseBytes(uint8_t *Data, size_t Size, size_t MaxSize); 39 /// Mutates data by inserting a byte. 40 size_t Mutate_InsertByte(uint8_t *Data, size_t Size, size_t MaxSize); 41 /// Mutates data by inserting several repeated bytes. 42 size_t Mutate_InsertRepeatedBytes(uint8_t *Data, size_t Size, size_t MaxSize); 43 /// Mutates data by chanding one byte. 44 size_t Mutate_ChangeByte(uint8_t *Data, size_t Size, size_t MaxSize); 45 /// Mutates data by chanding one bit. 46 size_t Mutate_ChangeBit(uint8_t *Data, size_t Size, size_t MaxSize); 47 /// Mutates data by copying/inserting a part of data into a different place. 48 size_t Mutate_CopyPart(uint8_t *Data, size_t Size, size_t MaxSize); 49 50 /// Mutates data by adding a word from the manual dictionary. 51 size_t Mutate_AddWordFromManualDictionary(uint8_t *Data, size_t Size, 52 size_t MaxSize); 53 54 /// Mutates data by adding a word from the TORC. 55 size_t Mutate_AddWordFromTORC(uint8_t *Data, size_t Size, size_t MaxSize); 56 57 /// Mutates data by adding a word from the persistent automatic dictionary. 58 size_t Mutate_AddWordFromPersistentAutoDictionary(uint8_t *Data, size_t Size, 59 size_t MaxSize); 60 61 /// Tries to find an ASCII integer in Data, changes it to another ASCII int. 62 size_t Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size, size_t MaxSize); 63 /// Change a 1-, 2-, 4-, or 8-byte integer in interesting ways. 64 size_t Mutate_ChangeBinaryInteger(uint8_t *Data, size_t Size, size_t MaxSize); 65 66 /// CrossOver Data with CrossOverWith. 67 size_t Mutate_CrossOver(uint8_t *Data, size_t Size, size_t MaxSize); 68 69 /// Applies one of the configured mutations. 70 /// Returns the new size of data which could be up to MaxSize. 71 size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize); 72 73 /// Applies one of the configured mutations to the bytes of Data 74 /// that have '1' in Mask. 75 /// Mask.size() should be >= Size. 76 size_t MutateWithMask(uint8_t *Data, size_t Size, size_t MaxSize, 77 const Vector<uint8_t> &Mask); 78 79 /// Applies one of the default mutations. Provided as a service 80 /// to mutation authors. 81 size_t DefaultMutate(uint8_t *Data, size_t Size, size_t MaxSize); 82 83 /// Creates a cross-over of two pieces of Data, returns its size. 84 size_t CrossOver(const uint8_t *Data1, size_t Size1, const uint8_t *Data2, 85 size_t Size2, uint8_t *Out, size_t MaxOutSize); 86 87 void AddWordToManualDictionary(const Word &W); 88 89 void PrintRecommendedDictionary(); 90 91 void SetCrossOverWith(const Unit *U) { CrossOverWith = U; } 92 93 Random &GetRand() { return Rand; } 94 95 private: 96 struct Mutator { 97 size_t (MutationDispatcher::*Fn)(uint8_t *Data, size_t Size, size_t Max); 98 const char *Name; 99 }; 100 101 size_t AddWordFromDictionary(Dictionary &D, uint8_t *Data, size_t Size, 102 size_t MaxSize); 103 size_t MutateImpl(uint8_t *Data, size_t Size, size_t MaxSize, 104 Vector<Mutator> &Mutators); 105 106 size_t InsertPartOf(const uint8_t *From, size_t FromSize, uint8_t *To, 107 size_t ToSize, size_t MaxToSize); 108 size_t CopyPartOf(const uint8_t *From, size_t FromSize, uint8_t *To, 109 size_t ToSize); 110 size_t ApplyDictionaryEntry(uint8_t *Data, size_t Size, size_t MaxSize, 111 DictionaryEntry &DE); 112 113 template <class T> 114 DictionaryEntry MakeDictionaryEntryFromCMP(T Arg1, T Arg2, 115 const uint8_t *Data, size_t Size); 116 DictionaryEntry MakeDictionaryEntryFromCMP(const Word &Arg1, const Word &Arg2, 117 const uint8_t *Data, size_t Size); 118 DictionaryEntry MakeDictionaryEntryFromCMP(const void *Arg1, const void *Arg2, 119 const void *Arg1Mutation, 120 const void *Arg2Mutation, 121 size_t ArgSize, 122 const uint8_t *Data, size_t Size); 123 124 Random &Rand; 125 const FuzzingOptions Options; 126 127 // Dictionary provided by the user via -dict=DICT_FILE. 128 Dictionary ManualDictionary; 129 // Temporary dictionary modified by the fuzzer itself, 130 // recreated periodically. 131 Dictionary TempAutoDictionary; 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 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 Vector<uint8_t> MutateInPlaceHere; 144 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 Vector<uint8_t> CustomCrossOverInPlaceHere; 148 149 Vector<Mutator> Mutators; 150 Vector<Mutator> DefaultMutators; 151 Vector<Mutator> CurrentMutatorSequence; 152 }; 153 154 } // namespace fuzzer 155 156 #endif // LLVM_FUZZER_MUTATE_H 157