File: | lib/Fuzzer/FuzzerMutate.cpp |
Warning: | line 213, column 5 Value stored to 'HandleFirst' is never read |
1 | //===- FuzzerMutate.cpp - Mutate a test input -----------------------------===// |
2 | // |
3 | // The LLVM Compiler Infrastructure |
4 | // |
5 | // This file is distributed under the University of Illinois Open Source |
6 | // License. See LICENSE.TXT for details. |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | // Mutate a test input. |
10 | //===----------------------------------------------------------------------===// |
11 | |
12 | #include "FuzzerCorpus.h" |
13 | #include "FuzzerDefs.h" |
14 | #include "FuzzerExtFunctions.h" |
15 | #include "FuzzerIO.h" |
16 | #include "FuzzerMutate.h" |
17 | #include "FuzzerOptions.h" |
18 | |
19 | namespace fuzzer { |
20 | |
21 | const size_t Dictionary::kMaxDictSize; |
22 | |
23 | static void PrintASCII(const Word &W, const char *PrintAfter) { |
24 | PrintASCII(W.data(), W.size(), PrintAfter); |
25 | } |
26 | |
27 | MutationDispatcher::MutationDispatcher(Random &Rand, |
28 | const FuzzingOptions &Options) |
29 | : Rand(Rand), Options(Options) { |
30 | DefaultMutators.insert( |
31 | DefaultMutators.begin(), |
32 | { |
33 | {&MutationDispatcher::Mutate_EraseBytes, "EraseBytes"}, |
34 | {&MutationDispatcher::Mutate_InsertByte, "InsertByte"}, |
35 | {&MutationDispatcher::Mutate_InsertRepeatedBytes, |
36 | "InsertRepeatedBytes"}, |
37 | {&MutationDispatcher::Mutate_ChangeByte, "ChangeByte"}, |
38 | {&MutationDispatcher::Mutate_ChangeBit, "ChangeBit"}, |
39 | {&MutationDispatcher::Mutate_ShuffleBytes, "ShuffleBytes"}, |
40 | {&MutationDispatcher::Mutate_ChangeASCIIInteger, "ChangeASCIIInt"}, |
41 | {&MutationDispatcher::Mutate_ChangeBinaryInteger, "ChangeBinInt"}, |
42 | {&MutationDispatcher::Mutate_CopyPart, "CopyPart"}, |
43 | {&MutationDispatcher::Mutate_CrossOver, "CrossOver"}, |
44 | {&MutationDispatcher::Mutate_AddWordFromManualDictionary, |
45 | "ManualDict"}, |
46 | {&MutationDispatcher::Mutate_AddWordFromTemporaryAutoDictionary, |
47 | "TempAutoDict"}, |
48 | {&MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary, |
49 | "PersAutoDict"}, |
50 | }); |
51 | if(Options.UseCmp) |
52 | DefaultMutators.push_back( |
53 | {&MutationDispatcher::Mutate_AddWordFromTORC, "CMP"}); |
54 | |
55 | if (EF->LLVMFuzzerCustomMutator) |
56 | Mutators.push_back({&MutationDispatcher::Mutate_Custom, "Custom"}); |
57 | else |
58 | Mutators = DefaultMutators; |
59 | |
60 | if (EF->LLVMFuzzerCustomCrossOver) |
61 | Mutators.push_back( |
62 | {&MutationDispatcher::Mutate_CustomCrossOver, "CustomCrossOver"}); |
63 | } |
64 | |
65 | static char RandCh(Random &Rand) { |
66 | if (Rand.RandBool()) return Rand(256); |
67 | const char *Special = "!*'();:@&=+$,/?%#[]012Az-`~.\xff\x00"; |
68 | return Special[Rand(sizeof(Special) - 1)]; |
69 | } |
70 | |
71 | size_t MutationDispatcher::Mutate_Custom(uint8_t *Data, size_t Size, |
72 | size_t MaxSize) { |
73 | return EF->LLVMFuzzerCustomMutator(Data, Size, MaxSize, Rand.Rand()); |
74 | } |
75 | |
76 | size_t MutationDispatcher::Mutate_CustomCrossOver(uint8_t *Data, size_t Size, |
77 | size_t MaxSize) { |
78 | if (!Corpus || Corpus->size() < 2 || Size == 0) |
79 | return 0; |
80 | size_t Idx = Rand(Corpus->size()); |
81 | const Unit &Other = (*Corpus)[Idx]; |
82 | if (Other.empty()) |
83 | return 0; |
84 | CustomCrossOverInPlaceHere.resize(MaxSize); |
85 | auto &U = CustomCrossOverInPlaceHere; |
86 | size_t NewSize = EF->LLVMFuzzerCustomCrossOver( |
87 | Data, Size, Other.data(), Other.size(), U.data(), U.size(), Rand.Rand()); |
88 | if (!NewSize) |
89 | return 0; |
90 | assert(NewSize <= MaxSize && "CustomCrossOver returned overisized unit")((NewSize <= MaxSize && "CustomCrossOver returned overisized unit" ) ? static_cast<void> (0) : __assert_fail ("NewSize <= MaxSize && \"CustomCrossOver returned overisized unit\"" , "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303041/lib/Fuzzer/FuzzerMutate.cpp" , 90, __PRETTY_FUNCTION__)); |
91 | memcpy(Data, U.data(), NewSize); |
92 | return NewSize; |
93 | } |
94 | |
95 | size_t MutationDispatcher::Mutate_ShuffleBytes(uint8_t *Data, size_t Size, |
96 | size_t MaxSize) { |
97 | if (Size > MaxSize || Size == 0) return 0; |
98 | size_t ShuffleAmount = |
99 | Rand(std::min(Size, (size_t)8)) + 1; // [1,8] and <= Size. |
100 | size_t ShuffleStart = Rand(Size - ShuffleAmount); |
101 | assert(ShuffleStart + ShuffleAmount <= Size)((ShuffleStart + ShuffleAmount <= Size) ? static_cast<void > (0) : __assert_fail ("ShuffleStart + ShuffleAmount <= Size" , "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303041/lib/Fuzzer/FuzzerMutate.cpp" , 101, __PRETTY_FUNCTION__)); |
102 | std::shuffle(Data + ShuffleStart, Data + ShuffleStart + ShuffleAmount, Rand); |
103 | return Size; |
104 | } |
105 | |
106 | size_t MutationDispatcher::Mutate_EraseBytes(uint8_t *Data, size_t Size, |
107 | size_t MaxSize) { |
108 | if (Size <= 1) return 0; |
109 | size_t N = Rand(Size / 2) + 1; |
110 | assert(N < Size)((N < Size) ? static_cast<void> (0) : __assert_fail ( "N < Size", "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303041/lib/Fuzzer/FuzzerMutate.cpp" , 110, __PRETTY_FUNCTION__)); |
111 | size_t Idx = Rand(Size - N + 1); |
112 | // Erase Data[Idx:Idx+N]. |
113 | memmove(Data + Idx, Data + Idx + N, Size - Idx - N); |
114 | // Printf("Erase: %zd %zd => %zd; Idx %zd\n", N, Size, Size - N, Idx); |
115 | return Size - N; |
116 | } |
117 | |
118 | size_t MutationDispatcher::Mutate_InsertByte(uint8_t *Data, size_t Size, |
119 | size_t MaxSize) { |
120 | if (Size >= MaxSize) return 0; |
121 | size_t Idx = Rand(Size + 1); |
122 | // Insert new value at Data[Idx]. |
123 | memmove(Data + Idx + 1, Data + Idx, Size - Idx); |
124 | Data[Idx] = RandCh(Rand); |
125 | return Size + 1; |
126 | } |
127 | |
128 | size_t MutationDispatcher::Mutate_InsertRepeatedBytes(uint8_t *Data, |
129 | size_t Size, |
130 | size_t MaxSize) { |
131 | const size_t kMinBytesToInsert = 3; |
132 | if (Size + kMinBytesToInsert >= MaxSize) return 0; |
133 | size_t MaxBytesToInsert = std::min(MaxSize - Size, (size_t)128); |
134 | size_t N = Rand(MaxBytesToInsert - kMinBytesToInsert + 1) + kMinBytesToInsert; |
135 | assert(Size + N <= MaxSize && N)((Size + N <= MaxSize && N) ? static_cast<void> (0) : __assert_fail ("Size + N <= MaxSize && N", "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303041/lib/Fuzzer/FuzzerMutate.cpp" , 135, __PRETTY_FUNCTION__)); |
136 | size_t Idx = Rand(Size + 1); |
137 | // Insert new values at Data[Idx]. |
138 | memmove(Data + Idx + N, Data + Idx, Size - Idx); |
139 | // Give preference to 0x00 and 0xff. |
140 | uint8_t Byte = Rand.RandBool() ? Rand(256) : (Rand.RandBool() ? 0 : 255); |
141 | for (size_t i = 0; i < N; i++) |
142 | Data[Idx + i] = Byte; |
143 | return Size + N; |
144 | } |
145 | |
146 | size_t MutationDispatcher::Mutate_ChangeByte(uint8_t *Data, size_t Size, |
147 | size_t MaxSize) { |
148 | if (Size > MaxSize) return 0; |
149 | size_t Idx = Rand(Size); |
150 | Data[Idx] = RandCh(Rand); |
151 | return Size; |
152 | } |
153 | |
154 | size_t MutationDispatcher::Mutate_ChangeBit(uint8_t *Data, size_t Size, |
155 | size_t MaxSize) { |
156 | if (Size > MaxSize) return 0; |
157 | size_t Idx = Rand(Size); |
158 | Data[Idx] ^= 1 << Rand(8); |
159 | return Size; |
160 | } |
161 | |
162 | size_t MutationDispatcher::Mutate_AddWordFromManualDictionary(uint8_t *Data, |
163 | size_t Size, |
164 | size_t MaxSize) { |
165 | return AddWordFromDictionary(ManualDictionary, Data, Size, MaxSize); |
166 | } |
167 | |
168 | size_t MutationDispatcher::Mutate_AddWordFromTemporaryAutoDictionary( |
169 | uint8_t *Data, size_t Size, size_t MaxSize) { |
170 | return AddWordFromDictionary(TempAutoDictionary, Data, Size, MaxSize); |
171 | } |
172 | |
173 | size_t MutationDispatcher::ApplyDictionaryEntry(uint8_t *Data, size_t Size, |
174 | size_t MaxSize, |
175 | DictionaryEntry &DE) { |
176 | const Word &W = DE.GetW(); |
177 | bool UsePositionHint = DE.HasPositionHint() && |
178 | DE.GetPositionHint() + W.size() < Size && |
179 | Rand.RandBool(); |
180 | if (Rand.RandBool()) { // Insert W. |
181 | if (Size + W.size() > MaxSize) return 0; |
182 | size_t Idx = UsePositionHint ? DE.GetPositionHint() : Rand(Size + 1); |
183 | memmove(Data + Idx + W.size(), Data + Idx, Size - Idx); |
184 | memcpy(Data + Idx, W.data(), W.size()); |
185 | Size += W.size(); |
186 | } else { // Overwrite some bytes with W. |
187 | if (W.size() > Size) return 0; |
188 | size_t Idx = UsePositionHint ? DE.GetPositionHint() : Rand(Size - W.size()); |
189 | memcpy(Data + Idx, W.data(), W.size()); |
190 | } |
191 | return Size; |
192 | } |
193 | |
194 | // Somewhere in the past we have observed a comparison instructions |
195 | // with arguments Arg1 Arg2. This function tries to guess a dictionary |
196 | // entry that will satisfy that comparison. |
197 | // It first tries to find one of the arguments (possibly swapped) in the |
198 | // input and if it succeeds it creates a DE with a position hint. |
199 | // Otherwise it creates a DE with one of the arguments w/o a position hint. |
200 | DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP( |
201 | const void *Arg1, const void *Arg2, |
202 | const void *Arg1Mutation, const void *Arg2Mutation, |
203 | size_t ArgSize, const uint8_t *Data, |
204 | size_t Size) { |
205 | ScopedDoingMyOwnMemOrStr scoped_doing_my_own_mem_os_str; |
206 | bool HandleFirst = Rand.RandBool(); |
207 | const void *ExistingBytes, *DesiredBytes; |
208 | Word W; |
209 | const uint8_t *End = Data + Size; |
210 | for (int Arg = 0; Arg < 2; Arg++) { |
211 | ExistingBytes = HandleFirst ? Arg1 : Arg2; |
212 | DesiredBytes = HandleFirst ? Arg2Mutation : Arg1Mutation; |
213 | HandleFirst = !HandleFirst; |
Value stored to 'HandleFirst' is never read | |
214 | W.Set(reinterpret_cast<const uint8_t*>(DesiredBytes), ArgSize); |
215 | const size_t kMaxNumPositions = 8; |
216 | size_t Positions[kMaxNumPositions]; |
217 | size_t NumPositions = 0; |
218 | for (const uint8_t *Cur = Data; |
219 | Cur < End && NumPositions < kMaxNumPositions; Cur++) { |
220 | Cur = |
221 | (const uint8_t *)SearchMemory(Cur, End - Cur, ExistingBytes, ArgSize); |
222 | if (!Cur) break; |
223 | Positions[NumPositions++] = Cur - Data; |
224 | } |
225 | if (!NumPositions) break; |
226 | return DictionaryEntry(W, Positions[Rand(NumPositions)]); |
227 | } |
228 | DictionaryEntry DE(W); |
229 | return DE; |
230 | } |
231 | |
232 | |
233 | template <class T> |
234 | DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP( |
235 | T Arg1, T Arg2, const uint8_t *Data, size_t Size) { |
236 | if (Rand.RandBool()) Arg1 = Bswap(Arg1); |
237 | if (Rand.RandBool()) Arg2 = Bswap(Arg2); |
238 | T Arg1Mutation = Arg1 + Rand(-1, 1); |
239 | T Arg2Mutation = Arg2 + Rand(-1, 1); |
240 | return MakeDictionaryEntryFromCMP(&Arg1, &Arg2, &Arg1Mutation, &Arg2Mutation, |
241 | sizeof(Arg1), Data, Size); |
242 | } |
243 | |
244 | DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP( |
245 | const Word &Arg1, const Word &Arg2, const uint8_t *Data, size_t Size) { |
246 | return MakeDictionaryEntryFromCMP(Arg1.data(), Arg2.data(), Arg1.data(), |
247 | Arg2.data(), Arg1.size(), Data, Size); |
248 | } |
249 | |
250 | size_t MutationDispatcher::Mutate_AddWordFromTORC( |
251 | uint8_t *Data, size_t Size, size_t MaxSize) { |
252 | Word W; |
253 | DictionaryEntry DE; |
254 | switch (Rand(3)) { |
255 | case 0: { |
256 | auto X = TPC.TORC8.Get(Rand.Rand()); |
257 | DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size); |
258 | } break; |
259 | case 1: { |
260 | auto X = TPC.TORC4.Get(Rand.Rand()); |
261 | if ((X.A >> 16) == 0 && (X.B >> 16) == 0 && Rand.RandBool()) |
262 | DE = MakeDictionaryEntryFromCMP((uint16_t)X.A, (uint16_t)X.B, Data, Size); |
263 | else |
264 | DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size); |
265 | } break; |
266 | case 2: { |
267 | auto X = TPC.TORCW.Get(Rand.Rand()); |
268 | DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size); |
269 | } break; |
270 | default: |
271 | assert(0)((0) ? static_cast<void> (0) : __assert_fail ("0", "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303041/lib/Fuzzer/FuzzerMutate.cpp" , 271, __PRETTY_FUNCTION__)); |
272 | } |
273 | if (!DE.GetW().size()) return 0; |
274 | Size = ApplyDictionaryEntry(Data, Size, MaxSize, DE); |
275 | if (!Size) return 0; |
276 | DictionaryEntry &DERef = |
277 | CmpDictionaryEntriesDeque[CmpDictionaryEntriesDequeIdx++ % |
278 | kCmpDictionaryEntriesDequeSize]; |
279 | DERef = DE; |
280 | CurrentDictionaryEntrySequence.push_back(&DERef); |
281 | return Size; |
282 | } |
283 | |
284 | size_t MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary( |
285 | uint8_t *Data, size_t Size, size_t MaxSize) { |
286 | return AddWordFromDictionary(PersistentAutoDictionary, Data, Size, MaxSize); |
287 | } |
288 | |
289 | size_t MutationDispatcher::AddWordFromDictionary(Dictionary &D, uint8_t *Data, |
290 | size_t Size, size_t MaxSize) { |
291 | if (Size > MaxSize) return 0; |
292 | if (D.empty()) return 0; |
293 | DictionaryEntry &DE = D[Rand(D.size())]; |
294 | Size = ApplyDictionaryEntry(Data, Size, MaxSize, DE); |
295 | if (!Size) return 0; |
296 | DE.IncUseCount(); |
297 | CurrentDictionaryEntrySequence.push_back(&DE); |
298 | return Size; |
299 | } |
300 | |
301 | // Overwrites part of To[0,ToSize) with a part of From[0,FromSize). |
302 | // Returns ToSize. |
303 | size_t MutationDispatcher::CopyPartOf(const uint8_t *From, size_t FromSize, |
304 | uint8_t *To, size_t ToSize) { |
305 | // Copy From[FromBeg, FromBeg + CopySize) into To[ToBeg, ToBeg + CopySize). |
306 | size_t ToBeg = Rand(ToSize); |
307 | size_t CopySize = Rand(ToSize - ToBeg) + 1; |
308 | assert(ToBeg + CopySize <= ToSize)((ToBeg + CopySize <= ToSize) ? static_cast<void> (0 ) : __assert_fail ("ToBeg + CopySize <= ToSize", "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303041/lib/Fuzzer/FuzzerMutate.cpp" , 308, __PRETTY_FUNCTION__)); |
309 | CopySize = std::min(CopySize, FromSize); |
310 | size_t FromBeg = Rand(FromSize - CopySize + 1); |
311 | assert(FromBeg + CopySize <= FromSize)((FromBeg + CopySize <= FromSize) ? static_cast<void> (0) : __assert_fail ("FromBeg + CopySize <= FromSize", "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303041/lib/Fuzzer/FuzzerMutate.cpp" , 311, __PRETTY_FUNCTION__)); |
312 | memmove(To + ToBeg, From + FromBeg, CopySize); |
313 | return ToSize; |
314 | } |
315 | |
316 | // Inserts part of From[0,ToSize) into To. |
317 | // Returns new size of To on success or 0 on failure. |
318 | size_t MutationDispatcher::InsertPartOf(const uint8_t *From, size_t FromSize, |
319 | uint8_t *To, size_t ToSize, |
320 | size_t MaxToSize) { |
321 | if (ToSize >= MaxToSize) return 0; |
322 | size_t AvailableSpace = MaxToSize - ToSize; |
323 | size_t MaxCopySize = std::min(AvailableSpace, FromSize); |
324 | size_t CopySize = Rand(MaxCopySize) + 1; |
325 | size_t FromBeg = Rand(FromSize - CopySize + 1); |
326 | assert(FromBeg + CopySize <= FromSize)((FromBeg + CopySize <= FromSize) ? static_cast<void> (0) : __assert_fail ("FromBeg + CopySize <= FromSize", "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303041/lib/Fuzzer/FuzzerMutate.cpp" , 326, __PRETTY_FUNCTION__)); |
327 | size_t ToInsertPos = Rand(ToSize + 1); |
328 | assert(ToInsertPos + CopySize <= MaxToSize)((ToInsertPos + CopySize <= MaxToSize) ? static_cast<void > (0) : __assert_fail ("ToInsertPos + CopySize <= MaxToSize" , "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303041/lib/Fuzzer/FuzzerMutate.cpp" , 328, __PRETTY_FUNCTION__)); |
329 | size_t TailSize = ToSize - ToInsertPos; |
330 | if (To == From) { |
331 | MutateInPlaceHere.resize(MaxToSize); |
332 | memcpy(MutateInPlaceHere.data(), From + FromBeg, CopySize); |
333 | memmove(To + ToInsertPos + CopySize, To + ToInsertPos, TailSize); |
334 | memmove(To + ToInsertPos, MutateInPlaceHere.data(), CopySize); |
335 | } else { |
336 | memmove(To + ToInsertPos + CopySize, To + ToInsertPos, TailSize); |
337 | memmove(To + ToInsertPos, From + FromBeg, CopySize); |
338 | } |
339 | return ToSize + CopySize; |
340 | } |
341 | |
342 | size_t MutationDispatcher::Mutate_CopyPart(uint8_t *Data, size_t Size, |
343 | size_t MaxSize) { |
344 | if (Size > MaxSize || Size == 0) return 0; |
345 | if (Rand.RandBool()) |
346 | return CopyPartOf(Data, Size, Data, Size); |
347 | else |
348 | return InsertPartOf(Data, Size, Data, Size, MaxSize); |
349 | } |
350 | |
351 | size_t MutationDispatcher::Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size, |
352 | size_t MaxSize) { |
353 | if (Size > MaxSize) return 0; |
354 | size_t B = Rand(Size); |
355 | while (B < Size && !isdigit(Data[B])) B++; |
356 | if (B == Size) return 0; |
357 | size_t E = B; |
358 | while (E < Size && isdigit(Data[E])) E++; |
359 | assert(B < E)((B < E) ? static_cast<void> (0) : __assert_fail ("B < E" , "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303041/lib/Fuzzer/FuzzerMutate.cpp" , 359, __PRETTY_FUNCTION__)); |
360 | // now we have digits in [B, E). |
361 | // strtol and friends don't accept non-zero-teminated data, parse it manually. |
362 | uint64_t Val = Data[B] - '0'; |
363 | for (size_t i = B + 1; i < E; i++) |
364 | Val = Val * 10 + Data[i] - '0'; |
365 | |
366 | // Mutate the integer value. |
367 | switch(Rand(5)) { |
368 | case 0: Val++; break; |
369 | case 1: Val--; break; |
370 | case 2: Val /= 2; break; |
371 | case 3: Val *= 2; break; |
372 | case 4: Val = Rand(Val * Val); break; |
373 | default: assert(0)((0) ? static_cast<void> (0) : __assert_fail ("0", "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303041/lib/Fuzzer/FuzzerMutate.cpp" , 373, __PRETTY_FUNCTION__)); |
374 | } |
375 | // Just replace the bytes with the new ones, don't bother moving bytes. |
376 | for (size_t i = B; i < E; i++) { |
377 | size_t Idx = E + B - i - 1; |
378 | assert(Idx >= B && Idx < E)((Idx >= B && Idx < E) ? static_cast<void> (0) : __assert_fail ("Idx >= B && Idx < E", "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303041/lib/Fuzzer/FuzzerMutate.cpp" , 378, __PRETTY_FUNCTION__)); |
379 | Data[Idx] = (Val % 10) + '0'; |
380 | Val /= 10; |
381 | } |
382 | return Size; |
383 | } |
384 | |
385 | template<class T> |
386 | size_t ChangeBinaryInteger(uint8_t *Data, size_t Size, Random &Rand) { |
387 | if (Size < sizeof(T)) return 0; |
388 | size_t Off = Rand(Size - sizeof(T) + 1); |
389 | assert(Off + sizeof(T) <= Size)((Off + sizeof(T) <= Size) ? static_cast<void> (0) : __assert_fail ("Off + sizeof(T) <= Size", "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303041/lib/Fuzzer/FuzzerMutate.cpp" , 389, __PRETTY_FUNCTION__)); |
390 | T Val; |
391 | if (Off < 64 && !Rand(4)) { |
392 | Val = Size; |
393 | if (Rand.RandBool()) |
394 | Val = Bswap(Val); |
395 | } else { |
396 | memcpy(&Val, Data + Off, sizeof(Val)); |
397 | T Add = Rand(21); |
398 | Add -= 10; |
399 | if (Rand.RandBool()) |
400 | Val = Bswap(T(Bswap(Val) + Add)); // Add assuming different endiannes. |
401 | else |
402 | Val = Val + Add; // Add assuming current endiannes. |
403 | if (Add == 0 || Rand.RandBool()) // Maybe negate. |
404 | Val = -Val; |
405 | } |
406 | memcpy(Data + Off, &Val, sizeof(Val)); |
407 | return Size; |
408 | } |
409 | |
410 | size_t MutationDispatcher::Mutate_ChangeBinaryInteger(uint8_t *Data, |
411 | size_t Size, |
412 | size_t MaxSize) { |
413 | if (Size > MaxSize) return 0; |
414 | switch (Rand(4)) { |
415 | case 3: return ChangeBinaryInteger<uint64_t>(Data, Size, Rand); |
416 | case 2: return ChangeBinaryInteger<uint32_t>(Data, Size, Rand); |
417 | case 1: return ChangeBinaryInteger<uint16_t>(Data, Size, Rand); |
418 | case 0: return ChangeBinaryInteger<uint8_t>(Data, Size, Rand); |
419 | default: assert(0)((0) ? static_cast<void> (0) : __assert_fail ("0", "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303041/lib/Fuzzer/FuzzerMutate.cpp" , 419, __PRETTY_FUNCTION__)); |
420 | } |
421 | return 0; |
422 | } |
423 | |
424 | size_t MutationDispatcher::Mutate_CrossOver(uint8_t *Data, size_t Size, |
425 | size_t MaxSize) { |
426 | if (Size > MaxSize) return 0; |
427 | if (!Corpus || Corpus->size() < 2 || Size == 0) return 0; |
428 | size_t Idx = Rand(Corpus->size()); |
429 | const Unit &O = (*Corpus)[Idx]; |
430 | if (O.empty()) return 0; |
431 | MutateInPlaceHere.resize(MaxSize); |
432 | auto &U = MutateInPlaceHere; |
433 | size_t NewSize = 0; |
434 | switch(Rand(3)) { |
435 | case 0: |
436 | NewSize = CrossOver(Data, Size, O.data(), O.size(), U.data(), U.size()); |
437 | break; |
438 | case 1: |
439 | NewSize = InsertPartOf(O.data(), O.size(), U.data(), U.size(), MaxSize); |
440 | if (!NewSize) |
441 | NewSize = CopyPartOf(O.data(), O.size(), U.data(), U.size()); |
442 | break; |
443 | case 2: |
444 | NewSize = CopyPartOf(O.data(), O.size(), U.data(), U.size()); |
445 | break; |
446 | default: assert(0)((0) ? static_cast<void> (0) : __assert_fail ("0", "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303041/lib/Fuzzer/FuzzerMutate.cpp" , 446, __PRETTY_FUNCTION__)); |
447 | } |
448 | assert(NewSize > 0 && "CrossOver returned empty unit")((NewSize > 0 && "CrossOver returned empty unit") ? static_cast<void> (0) : __assert_fail ("NewSize > 0 && \"CrossOver returned empty unit\"" , "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303041/lib/Fuzzer/FuzzerMutate.cpp" , 448, __PRETTY_FUNCTION__)); |
449 | assert(NewSize <= MaxSize && "CrossOver returned overisized unit")((NewSize <= MaxSize && "CrossOver returned overisized unit" ) ? static_cast<void> (0) : __assert_fail ("NewSize <= MaxSize && \"CrossOver returned overisized unit\"" , "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303041/lib/Fuzzer/FuzzerMutate.cpp" , 449, __PRETTY_FUNCTION__)); |
450 | memcpy(Data, U.data(), NewSize); |
451 | return NewSize; |
452 | } |
453 | |
454 | void MutationDispatcher::StartMutationSequence() { |
455 | CurrentMutatorSequence.clear(); |
456 | CurrentDictionaryEntrySequence.clear(); |
457 | } |
458 | |
459 | // Copy successful dictionary entries to PersistentAutoDictionary. |
460 | void MutationDispatcher::RecordSuccessfulMutationSequence() { |
461 | for (auto DE : CurrentDictionaryEntrySequence) { |
462 | // PersistentAutoDictionary.AddWithSuccessCountOne(DE); |
463 | DE->IncSuccessCount(); |
464 | assert(DE->GetW().size())((DE->GetW().size()) ? static_cast<void> (0) : __assert_fail ("DE->GetW().size()", "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303041/lib/Fuzzer/FuzzerMutate.cpp" , 464, __PRETTY_FUNCTION__)); |
465 | // Linear search is fine here as this happens seldom. |
466 | if (!PersistentAutoDictionary.ContainsWord(DE->GetW())) |
467 | PersistentAutoDictionary.push_back({DE->GetW(), 1}); |
468 | } |
469 | } |
470 | |
471 | void MutationDispatcher::PrintRecommendedDictionary() { |
472 | std::vector<DictionaryEntry> V; |
473 | for (auto &DE : PersistentAutoDictionary) |
474 | if (!ManualDictionary.ContainsWord(DE.GetW())) |
475 | V.push_back(DE); |
476 | if (V.empty()) return; |
477 | Printf("###### Recommended dictionary. ######\n"); |
478 | for (auto &DE: V) { |
479 | assert(DE.GetW().size())((DE.GetW().size()) ? static_cast<void> (0) : __assert_fail ("DE.GetW().size()", "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303041/lib/Fuzzer/FuzzerMutate.cpp" , 479, __PRETTY_FUNCTION__)); |
480 | Printf("\""); |
481 | PrintASCII(DE.GetW(), "\""); |
482 | Printf(" # Uses: %zd\n", DE.GetUseCount()); |
483 | } |
484 | Printf("###### End of recommended dictionary. ######\n"); |
485 | } |
486 | |
487 | void MutationDispatcher::PrintMutationSequence() { |
488 | Printf("MS: %zd ", CurrentMutatorSequence.size()); |
489 | for (auto M : CurrentMutatorSequence) |
490 | Printf("%s-", M.Name); |
491 | if (!CurrentDictionaryEntrySequence.empty()) { |
492 | Printf(" DE: "); |
493 | for (auto DE : CurrentDictionaryEntrySequence) { |
494 | Printf("\""); |
495 | PrintASCII(DE->GetW(), "\"-"); |
496 | } |
497 | } |
498 | } |
499 | |
500 | size_t MutationDispatcher::Mutate(uint8_t *Data, size_t Size, size_t MaxSize) { |
501 | return MutateImpl(Data, Size, MaxSize, Mutators); |
502 | } |
503 | |
504 | size_t MutationDispatcher::DefaultMutate(uint8_t *Data, size_t Size, |
505 | size_t MaxSize) { |
506 | return MutateImpl(Data, Size, MaxSize, DefaultMutators); |
507 | } |
508 | |
509 | // Mutates Data in place, returns new size. |
510 | size_t MutationDispatcher::MutateImpl(uint8_t *Data, size_t Size, |
511 | size_t MaxSize, |
512 | const std::vector<Mutator> &Mutators) { |
513 | assert(MaxSize > 0)((MaxSize > 0) ? static_cast<void> (0) : __assert_fail ("MaxSize > 0", "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn303041/lib/Fuzzer/FuzzerMutate.cpp" , 513, __PRETTY_FUNCTION__)); |
514 | // Some mutations may fail (e.g. can't insert more bytes if Size == MaxSize), |
515 | // in which case they will return 0. |
516 | // Try several times before returning un-mutated data. |
517 | for (int Iter = 0; Iter < 100; Iter++) { |
518 | auto M = Mutators[Rand(Mutators.size())]; |
519 | size_t NewSize = (this->*(M.Fn))(Data, Size, MaxSize); |
520 | if (NewSize && NewSize <= MaxSize) { |
521 | if (Options.OnlyASCII) |
522 | ToASCII(Data, NewSize); |
523 | CurrentMutatorSequence.push_back(M); |
524 | return NewSize; |
525 | } |
526 | } |
527 | *Data = ' '; |
528 | return 1; // Fallback, should not happen frequently. |
529 | } |
530 | |
531 | void MutationDispatcher::AddWordToManualDictionary(const Word &W) { |
532 | ManualDictionary.push_back( |
533 | {W, std::numeric_limits<size_t>::max()}); |
534 | } |
535 | |
536 | void MutationDispatcher::AddWordToAutoDictionary(DictionaryEntry DE) { |
537 | static const size_t kMaxAutoDictSize = 1 << 14; |
538 | if (TempAutoDictionary.size() >= kMaxAutoDictSize) return; |
539 | TempAutoDictionary.push_back(DE); |
540 | } |
541 | |
542 | void MutationDispatcher::ClearAutoDictionary() { |
543 | TempAutoDictionary.clear(); |
544 | } |
545 | |
546 | } // namespace fuzzer |