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 | |