blob: fac3c7afb4a18737fea1c195529720ee522e043b [file] [log] [blame]
george.karpenkov29efa6d2017-08-21 23:25:50 +00001//===- 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 "FuzzerMutate.h"
13#include "FuzzerCorpus.h"
14#include "FuzzerDefs.h"
15#include "FuzzerExtFunctions.h"
16#include "FuzzerIO.h"
17#include "FuzzerOptions.h"
18
19namespace fuzzer {
20
21const size_t Dictionary::kMaxDictSize;
22
23static void PrintASCII(const Word &W, const char *PrintAfter) {
24 PrintASCII(W.data(), W.size(), PrintAfter);
25}
26
27MutationDispatcher::MutationDispatcher(Random &Rand,
28 const FuzzingOptions &Options)
29 : Rand(Rand), Options(Options) {
30 DefaultMutators.insert(
31 DefaultMutators.begin(),
32 {
dor1s9dfdc272018-08-02 22:30:03 +000033 // Initialize useful and total mutation counts as 1 in order to
34 // have mutation stats (i.e. weights) with equal non-zero values.
35 {&MutationDispatcher::Mutate_EraseBytes, "EraseBytes", 1, 1},
36 {&MutationDispatcher::Mutate_InsertByte, "InsertByte", 1, 1},
george.karpenkov29efa6d2017-08-21 23:25:50 +000037 {&MutationDispatcher::Mutate_InsertRepeatedBytes,
dor1s9dfdc272018-08-02 22:30:03 +000038 "InsertRepeatedBytes", 1, 1},
39 {&MutationDispatcher::Mutate_ChangeByte, "ChangeByte", 1, 1},
40 {&MutationDispatcher::Mutate_ChangeBit, "ChangeBit", 1, 1},
41 {&MutationDispatcher::Mutate_ShuffleBytes, "ShuffleBytes", 1, 1},
42 {&MutationDispatcher::Mutate_ChangeASCIIInteger, "ChangeASCIIInt", 1,
43 1},
44 {&MutationDispatcher::Mutate_ChangeBinaryInteger, "ChangeBinInt", 1,
45 1},
46 {&MutationDispatcher::Mutate_CopyPart, "CopyPart", 1, 1},
47 {&MutationDispatcher::Mutate_CrossOver, "CrossOver", 1, 1},
george.karpenkov29efa6d2017-08-21 23:25:50 +000048 {&MutationDispatcher::Mutate_AddWordFromManualDictionary,
dor1s9dfdc272018-08-02 22:30:03 +000049 "ManualDict", 1, 1},
george.karpenkov29efa6d2017-08-21 23:25:50 +000050 {&MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary,
dor1s9dfdc272018-08-02 22:30:03 +000051 "PersAutoDict", 1, 1},
george.karpenkov29efa6d2017-08-21 23:25:50 +000052 });
53 if(Options.UseCmp)
54 DefaultMutators.push_back(
dor1s9dfdc272018-08-02 22:30:03 +000055 {&MutationDispatcher::Mutate_AddWordFromTORC, "CMP", 1, 1});
george.karpenkov29efa6d2017-08-21 23:25:50 +000056
57 if (EF->LLVMFuzzerCustomMutator)
dor1s9dfdc272018-08-02 22:30:03 +000058 Mutators.push_back({&MutationDispatcher::Mutate_Custom, "Custom", 1, 1});
george.karpenkov29efa6d2017-08-21 23:25:50 +000059 else
60 Mutators = DefaultMutators;
61
62 if (EF->LLVMFuzzerCustomCrossOver)
63 Mutators.push_back(
dor1s9dfdc272018-08-02 22:30:03 +000064 {&MutationDispatcher::Mutate_CustomCrossOver, "CustomCrossOver", 1, 1});
65
66 // For weighted mutation selection, init with uniform weights distribution.
67 Stats.resize(Mutators.size());
george.karpenkov29efa6d2017-08-21 23:25:50 +000068}
69
70static char RandCh(Random &Rand) {
71 if (Rand.RandBool()) return Rand(256);
morehousea3809d52018-01-30 18:25:55 +000072 const char Special[] = "!*'();:@&=+$,/?%#[]012Az-`~.\xff\x00";
george.karpenkov29efa6d2017-08-21 23:25:50 +000073 return Special[Rand(sizeof(Special) - 1)];
74}
75
76size_t MutationDispatcher::Mutate_Custom(uint8_t *Data, size_t Size,
77 size_t MaxSize) {
78 return EF->LLVMFuzzerCustomMutator(Data, Size, MaxSize, Rand.Rand());
79}
80
81size_t MutationDispatcher::Mutate_CustomCrossOver(uint8_t *Data, size_t Size,
82 size_t MaxSize) {
83 if (!Corpus || Corpus->size() < 2 || Size == 0)
84 return 0;
85 size_t Idx = Rand(Corpus->size());
86 const Unit &Other = (*Corpus)[Idx];
87 if (Other.empty())
88 return 0;
89 CustomCrossOverInPlaceHere.resize(MaxSize);
90 auto &U = CustomCrossOverInPlaceHere;
91 size_t NewSize = EF->LLVMFuzzerCustomCrossOver(
92 Data, Size, Other.data(), Other.size(), U.data(), U.size(), Rand.Rand());
93 if (!NewSize)
94 return 0;
95 assert(NewSize <= MaxSize && "CustomCrossOver returned overisized unit");
96 memcpy(Data, U.data(), NewSize);
97 return NewSize;
98}
99
100size_t MutationDispatcher::Mutate_ShuffleBytes(uint8_t *Data, size_t Size,
101 size_t MaxSize) {
102 if (Size > MaxSize || Size == 0) return 0;
103 size_t ShuffleAmount =
104 Rand(std::min(Size, (size_t)8)) + 1; // [1,8] and <= Size.
105 size_t ShuffleStart = Rand(Size - ShuffleAmount);
106 assert(ShuffleStart + ShuffleAmount <= Size);
107 std::shuffle(Data + ShuffleStart, Data + ShuffleStart + ShuffleAmount, Rand);
108 return Size;
109}
110
111size_t MutationDispatcher::Mutate_EraseBytes(uint8_t *Data, size_t Size,
112 size_t MaxSize) {
113 if (Size <= 1) return 0;
114 size_t N = Rand(Size / 2) + 1;
115 assert(N < Size);
116 size_t Idx = Rand(Size - N + 1);
117 // Erase Data[Idx:Idx+N].
118 memmove(Data + Idx, Data + Idx + N, Size - Idx - N);
119 // Printf("Erase: %zd %zd => %zd; Idx %zd\n", N, Size, Size - N, Idx);
120 return Size - N;
121}
122
123size_t MutationDispatcher::Mutate_InsertByte(uint8_t *Data, size_t Size,
124 size_t MaxSize) {
125 if (Size >= MaxSize) return 0;
126 size_t Idx = Rand(Size + 1);
127 // Insert new value at Data[Idx].
128 memmove(Data + Idx + 1, Data + Idx, Size - Idx);
129 Data[Idx] = RandCh(Rand);
130 return Size + 1;
131}
132
133size_t MutationDispatcher::Mutate_InsertRepeatedBytes(uint8_t *Data,
134 size_t Size,
135 size_t MaxSize) {
136 const size_t kMinBytesToInsert = 3;
137 if (Size + kMinBytesToInsert >= MaxSize) return 0;
138 size_t MaxBytesToInsert = std::min(MaxSize - Size, (size_t)128);
139 size_t N = Rand(MaxBytesToInsert - kMinBytesToInsert + 1) + kMinBytesToInsert;
140 assert(Size + N <= MaxSize && N);
141 size_t Idx = Rand(Size + 1);
142 // Insert new values at Data[Idx].
143 memmove(Data + Idx + N, Data + Idx, Size - Idx);
144 // Give preference to 0x00 and 0xff.
145 uint8_t Byte = Rand.RandBool() ? Rand(256) : (Rand.RandBool() ? 0 : 255);
146 for (size_t i = 0; i < N; i++)
147 Data[Idx + i] = Byte;
148 return Size + N;
149}
150
151size_t MutationDispatcher::Mutate_ChangeByte(uint8_t *Data, size_t Size,
152 size_t MaxSize) {
153 if (Size > MaxSize) return 0;
154 size_t Idx = Rand(Size);
155 Data[Idx] = RandCh(Rand);
156 return Size;
157}
158
159size_t MutationDispatcher::Mutate_ChangeBit(uint8_t *Data, size_t Size,
160 size_t MaxSize) {
161 if (Size > MaxSize) return 0;
162 size_t Idx = Rand(Size);
163 Data[Idx] ^= 1 << Rand(8);
164 return Size;
165}
166
167size_t MutationDispatcher::Mutate_AddWordFromManualDictionary(uint8_t *Data,
168 size_t Size,
169 size_t MaxSize) {
170 return AddWordFromDictionary(ManualDictionary, Data, Size, MaxSize);
171}
172
173size_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.
200DictionaryEntry 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) {
george.karpenkov29efa6d2017-08-21 23:25:50 +0000205 bool HandleFirst = Rand.RandBool();
206 const void *ExistingBytes, *DesiredBytes;
207 Word W;
208 const uint8_t *End = Data + Size;
209 for (int Arg = 0; Arg < 2; Arg++) {
210 ExistingBytes = HandleFirst ? Arg1 : Arg2;
211 DesiredBytes = HandleFirst ? Arg2Mutation : Arg1Mutation;
212 HandleFirst = !HandleFirst;
213 W.Set(reinterpret_cast<const uint8_t*>(DesiredBytes), ArgSize);
214 const size_t kMaxNumPositions = 8;
215 size_t Positions[kMaxNumPositions];
216 size_t NumPositions = 0;
217 for (const uint8_t *Cur = Data;
218 Cur < End && NumPositions < kMaxNumPositions; Cur++) {
219 Cur =
220 (const uint8_t *)SearchMemory(Cur, End - Cur, ExistingBytes, ArgSize);
221 if (!Cur) break;
222 Positions[NumPositions++] = Cur - Data;
223 }
224 if (!NumPositions) continue;
225 return DictionaryEntry(W, Positions[Rand(NumPositions)]);
226 }
227 DictionaryEntry DE(W);
228 return DE;
229}
230
231
232template <class T>
233DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP(
234 T Arg1, T Arg2, const uint8_t *Data, size_t Size) {
235 if (Rand.RandBool()) Arg1 = Bswap(Arg1);
236 if (Rand.RandBool()) Arg2 = Bswap(Arg2);
237 T Arg1Mutation = Arg1 + Rand(-1, 1);
238 T Arg2Mutation = Arg2 + Rand(-1, 1);
239 return MakeDictionaryEntryFromCMP(&Arg1, &Arg2, &Arg1Mutation, &Arg2Mutation,
240 sizeof(Arg1), Data, Size);
241}
242
243DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP(
244 const Word &Arg1, const Word &Arg2, const uint8_t *Data, size_t Size) {
245 return MakeDictionaryEntryFromCMP(Arg1.data(), Arg2.data(), Arg1.data(),
246 Arg2.data(), Arg1.size(), Data, Size);
247}
248
249size_t MutationDispatcher::Mutate_AddWordFromTORC(
250 uint8_t *Data, size_t Size, size_t MaxSize) {
251 Word W;
252 DictionaryEntry DE;
253 switch (Rand(4)) {
254 case 0: {
255 auto X = TPC.TORC8.Get(Rand.Rand());
256 DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size);
257 } break;
258 case 1: {
259 auto X = TPC.TORC4.Get(Rand.Rand());
260 if ((X.A >> 16) == 0 && (X.B >> 16) == 0 && Rand.RandBool())
261 DE = MakeDictionaryEntryFromCMP((uint16_t)X.A, (uint16_t)X.B, Data, Size);
262 else
263 DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size);
264 } break;
265 case 2: {
266 auto X = TPC.TORCW.Get(Rand.Rand());
267 DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size);
268 } break;
269 case 3: if (Options.UseMemmem) {
morehousec46c27f2018-07-09 22:31:26 +0000270 auto X = TPC.MMT.Get(Rand.Rand());
271 DE = DictionaryEntry(X);
272 } break;
george.karpenkov29efa6d2017-08-21 23:25:50 +0000273 default:
274 assert(0);
275 }
276 if (!DE.GetW().size()) return 0;
277 Size = ApplyDictionaryEntry(Data, Size, MaxSize, DE);
278 if (!Size) return 0;
279 DictionaryEntry &DERef =
280 CmpDictionaryEntriesDeque[CmpDictionaryEntriesDequeIdx++ %
281 kCmpDictionaryEntriesDequeSize];
282 DERef = DE;
283 CurrentDictionaryEntrySequence.push_back(&DERef);
284 return Size;
285}
286
287size_t MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary(
288 uint8_t *Data, size_t Size, size_t MaxSize) {
289 return AddWordFromDictionary(PersistentAutoDictionary, Data, Size, MaxSize);
290}
291
292size_t MutationDispatcher::AddWordFromDictionary(Dictionary &D, uint8_t *Data,
293 size_t Size, size_t MaxSize) {
294 if (Size > MaxSize) return 0;
295 if (D.empty()) return 0;
296 DictionaryEntry &DE = D[Rand(D.size())];
297 Size = ApplyDictionaryEntry(Data, Size, MaxSize, DE);
298 if (!Size) return 0;
299 DE.IncUseCount();
300 CurrentDictionaryEntrySequence.push_back(&DE);
301 return Size;
302}
303
304// Overwrites part of To[0,ToSize) with a part of From[0,FromSize).
305// Returns ToSize.
306size_t MutationDispatcher::CopyPartOf(const uint8_t *From, size_t FromSize,
307 uint8_t *To, size_t ToSize) {
308 // Copy From[FromBeg, FromBeg + CopySize) into To[ToBeg, ToBeg + CopySize).
309 size_t ToBeg = Rand(ToSize);
310 size_t CopySize = Rand(ToSize - ToBeg) + 1;
311 assert(ToBeg + CopySize <= ToSize);
312 CopySize = std::min(CopySize, FromSize);
313 size_t FromBeg = Rand(FromSize - CopySize + 1);
314 assert(FromBeg + CopySize <= FromSize);
315 memmove(To + ToBeg, From + FromBeg, CopySize);
316 return ToSize;
317}
318
319// Inserts part of From[0,ToSize) into To.
320// Returns new size of To on success or 0 on failure.
321size_t MutationDispatcher::InsertPartOf(const uint8_t *From, size_t FromSize,
322 uint8_t *To, size_t ToSize,
323 size_t MaxToSize) {
324 if (ToSize >= MaxToSize) return 0;
325 size_t AvailableSpace = MaxToSize - ToSize;
326 size_t MaxCopySize = std::min(AvailableSpace, FromSize);
327 size_t CopySize = Rand(MaxCopySize) + 1;
328 size_t FromBeg = Rand(FromSize - CopySize + 1);
329 assert(FromBeg + CopySize <= FromSize);
330 size_t ToInsertPos = Rand(ToSize + 1);
331 assert(ToInsertPos + CopySize <= MaxToSize);
332 size_t TailSize = ToSize - ToInsertPos;
333 if (To == From) {
334 MutateInPlaceHere.resize(MaxToSize);
335 memcpy(MutateInPlaceHere.data(), From + FromBeg, CopySize);
336 memmove(To + ToInsertPos + CopySize, To + ToInsertPos, TailSize);
337 memmove(To + ToInsertPos, MutateInPlaceHere.data(), CopySize);
338 } else {
339 memmove(To + ToInsertPos + CopySize, To + ToInsertPos, TailSize);
340 memmove(To + ToInsertPos, From + FromBeg, CopySize);
341 }
342 return ToSize + CopySize;
343}
344
345size_t MutationDispatcher::Mutate_CopyPart(uint8_t *Data, size_t Size,
346 size_t MaxSize) {
347 if (Size > MaxSize || Size == 0) return 0;
delcypher1fda1312018-04-24 06:31:09 +0000348 // If Size == MaxSize, `InsertPartOf(...)` will
349 // fail so there's no point using it in this case.
350 if (Size == MaxSize || Rand.RandBool())
george.karpenkov29efa6d2017-08-21 23:25:50 +0000351 return CopyPartOf(Data, Size, Data, Size);
352 else
353 return InsertPartOf(Data, Size, Data, Size, MaxSize);
354}
355
356size_t MutationDispatcher::Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size,
357 size_t MaxSize) {
358 if (Size > MaxSize) return 0;
359 size_t B = Rand(Size);
360 while (B < Size && !isdigit(Data[B])) B++;
361 if (B == Size) return 0;
362 size_t E = B;
363 while (E < Size && isdigit(Data[E])) E++;
364 assert(B < E);
365 // now we have digits in [B, E).
366 // strtol and friends don't accept non-zero-teminated data, parse it manually.
367 uint64_t Val = Data[B] - '0';
368 for (size_t i = B + 1; i < E; i++)
369 Val = Val * 10 + Data[i] - '0';
370
371 // Mutate the integer value.
372 switch(Rand(5)) {
373 case 0: Val++; break;
374 case 1: Val--; break;
375 case 2: Val /= 2; break;
376 case 3: Val *= 2; break;
377 case 4: Val = Rand(Val * Val); break;
378 default: assert(0);
379 }
380 // Just replace the bytes with the new ones, don't bother moving bytes.
381 for (size_t i = B; i < E; i++) {
382 size_t Idx = E + B - i - 1;
383 assert(Idx >= B && Idx < E);
384 Data[Idx] = (Val % 10) + '0';
385 Val /= 10;
386 }
387 return Size;
388}
389
390template<class T>
391size_t ChangeBinaryInteger(uint8_t *Data, size_t Size, Random &Rand) {
392 if (Size < sizeof(T)) return 0;
393 size_t Off = Rand(Size - sizeof(T) + 1);
394 assert(Off + sizeof(T) <= Size);
395 T Val;
396 if (Off < 64 && !Rand(4)) {
397 Val = Size;
398 if (Rand.RandBool())
399 Val = Bswap(Val);
400 } else {
401 memcpy(&Val, Data + Off, sizeof(Val));
402 T Add = Rand(21);
403 Add -= 10;
404 if (Rand.RandBool())
405 Val = Bswap(T(Bswap(Val) + Add)); // Add assuming different endiannes.
406 else
407 Val = Val + Add; // Add assuming current endiannes.
408 if (Add == 0 || Rand.RandBool()) // Maybe negate.
409 Val = -Val;
410 }
411 memcpy(Data + Off, &Val, sizeof(Val));
412 return Size;
413}
414
415size_t MutationDispatcher::Mutate_ChangeBinaryInteger(uint8_t *Data,
416 size_t Size,
417 size_t MaxSize) {
418 if (Size > MaxSize) return 0;
419 switch (Rand(4)) {
420 case 3: return ChangeBinaryInteger<uint64_t>(Data, Size, Rand);
421 case 2: return ChangeBinaryInteger<uint32_t>(Data, Size, Rand);
422 case 1: return ChangeBinaryInteger<uint16_t>(Data, Size, Rand);
423 case 0: return ChangeBinaryInteger<uint8_t>(Data, Size, Rand);
424 default: assert(0);
425 }
426 return 0;
427}
428
429size_t MutationDispatcher::Mutate_CrossOver(uint8_t *Data, size_t Size,
430 size_t MaxSize) {
431 if (Size > MaxSize) return 0;
432 if (!Corpus || Corpus->size() < 2 || Size == 0) return 0;
433 size_t Idx = Rand(Corpus->size());
434 const Unit &O = (*Corpus)[Idx];
435 if (O.empty()) return 0;
436 MutateInPlaceHere.resize(MaxSize);
437 auto &U = MutateInPlaceHere;
438 size_t NewSize = 0;
439 switch(Rand(3)) {
morehousec46c27f2018-07-09 22:31:26 +0000440 case 0:
441 NewSize = CrossOver(Data, Size, O.data(), O.size(), U.data(), U.size());
442 break;
443 case 1:
444 NewSize = InsertPartOf(O.data(), O.size(), U.data(), U.size(), MaxSize);
445 if (!NewSize)
446 NewSize = CopyPartOf(O.data(), O.size(), U.data(), U.size());
447 break;
448 case 2:
george.karpenkov29efa6d2017-08-21 23:25:50 +0000449 NewSize = CopyPartOf(O.data(), O.size(), U.data(), U.size());
morehousec46c27f2018-07-09 22:31:26 +0000450 break;
451 default: assert(0);
george.karpenkov29efa6d2017-08-21 23:25:50 +0000452 }
453 assert(NewSize > 0 && "CrossOver returned empty unit");
454 assert(NewSize <= MaxSize && "CrossOver returned overisized unit");
455 memcpy(Data, U.data(), NewSize);
456 return NewSize;
457}
458
459void MutationDispatcher::StartMutationSequence() {
morehousec46c27f2018-07-09 22:31:26 +0000460 CurrentMutatorSequence.clear();
george.karpenkov29efa6d2017-08-21 23:25:50 +0000461 CurrentDictionaryEntrySequence.clear();
462}
463
464// Copy successful dictionary entries to PersistentAutoDictionary.
465void MutationDispatcher::RecordSuccessfulMutationSequence() {
466 for (auto DE : CurrentDictionaryEntrySequence) {
467 // PersistentAutoDictionary.AddWithSuccessCountOne(DE);
468 DE->IncSuccessCount();
469 assert(DE->GetW().size());
470 // Linear search is fine here as this happens seldom.
471 if (!PersistentAutoDictionary.ContainsWord(DE->GetW()))
472 PersistentAutoDictionary.push_back({DE->GetW(), 1});
473 }
dor1s2f728942018-07-17 20:37:40 +0000474 RecordUsefulMutations();
george.karpenkov29efa6d2017-08-21 23:25:50 +0000475}
476
477void MutationDispatcher::PrintRecommendedDictionary() {
george.karpenkovfbfa45c2017-08-27 23:20:09 +0000478 Vector<DictionaryEntry> V;
george.karpenkov29efa6d2017-08-21 23:25:50 +0000479 for (auto &DE : PersistentAutoDictionary)
480 if (!ManualDictionary.ContainsWord(DE.GetW()))
481 V.push_back(DE);
482 if (V.empty()) return;
483 Printf("###### Recommended dictionary. ######\n");
484 for (auto &DE: V) {
485 assert(DE.GetW().size());
486 Printf("\"");
487 PrintASCII(DE.GetW(), "\"");
488 Printf(" # Uses: %zd\n", DE.GetUseCount());
489 }
490 Printf("###### End of recommended dictionary. ######\n");
491}
492
493void MutationDispatcher::PrintMutationSequence() {
morehousec46c27f2018-07-09 22:31:26 +0000494 Printf("MS: %zd ", CurrentMutatorSequence.size());
dor1s2f728942018-07-17 20:37:40 +0000495 for (auto M : CurrentMutatorSequence) Printf("%s-", M->Name);
george.karpenkov29efa6d2017-08-21 23:25:50 +0000496 if (!CurrentDictionaryEntrySequence.empty()) {
497 Printf(" DE: ");
498 for (auto DE : CurrentDictionaryEntrySequence) {
499 Printf("\"");
500 PrintASCII(DE->GetW(), "\"-");
501 }
502 }
503}
504
505size_t MutationDispatcher::Mutate(uint8_t *Data, size_t Size, size_t MaxSize) {
506 return MutateImpl(Data, Size, MaxSize, Mutators);
507}
508
509size_t MutationDispatcher::DefaultMutate(uint8_t *Data, size_t Size,
510 size_t MaxSize) {
511 return MutateImpl(Data, Size, MaxSize, DefaultMutators);
512}
513
514// Mutates Data in place, returns new size.
515size_t MutationDispatcher::MutateImpl(uint8_t *Data, size_t Size,
516 size_t MaxSize,
george.karpenkovfbfa45c2017-08-27 23:20:09 +0000517 Vector<Mutator> &Mutators) {
george.karpenkov29efa6d2017-08-21 23:25:50 +0000518 assert(MaxSize > 0);
519 // Some mutations may fail (e.g. can't insert more bytes if Size == MaxSize),
520 // in which case they will return 0.
521 // Try several times before returning un-mutated data.
dor1s9dfdc272018-08-02 22:30:03 +0000522 Mutator *M = nullptr;
george.karpenkov29efa6d2017-08-21 23:25:50 +0000523 for (int Iter = 0; Iter < 100; Iter++) {
dor1s9dfdc272018-08-02 22:30:03 +0000524 // Even when using weighted mutations, fallback to the default selection in
525 // 20% of cases.
526 if (Options.UseWeightedMutations && Rand(5))
527 M = &Mutators[WeightedIndex()];
528 else
529 M = &Mutators[Rand(Mutators.size())];
dor1s2f728942018-07-17 20:37:40 +0000530 size_t NewSize = (this->*(M->Fn))(Data, Size, MaxSize);
george.karpenkov29efa6d2017-08-21 23:25:50 +0000531 if (NewSize && NewSize <= MaxSize) {
532 if (Options.OnlyASCII)
533 ToASCII(Data, NewSize);
morehousec46c27f2018-07-09 22:31:26 +0000534 CurrentMutatorSequence.push_back(M);
dor1s2f728942018-07-17 20:37:40 +0000535 M->TotalCount++;
george.karpenkov29efa6d2017-08-21 23:25:50 +0000536 return NewSize;
537 }
538 }
539 *Data = ' ';
540 return 1; // Fallback, should not happen frequently.
541}
542
kcc0cab3f02018-07-19 01:23:32 +0000543// Mask represents the set of Data bytes that are worth mutating.
544size_t MutationDispatcher::MutateWithMask(uint8_t *Data, size_t Size,
545 size_t MaxSize,
546 const Vector<uint8_t> &Mask) {
547 assert(Size <= Mask.size());
548 // * Copy the worthy bytes into a temporary array T
549 // * Mutate T
550 // * Copy T back.
551 // This is totally unoptimized.
552 auto &T = MutateWithMaskTemp;
553 if (T.size() < Size)
554 T.resize(Size);
555 size_t OneBits = 0;
556 for (size_t I = 0; I < Size; I++)
557 if (Mask[I])
558 T[OneBits++] = Data[I];
559
560 assert(!T.empty());
561 size_t NewSize = Mutate(T.data(), OneBits, OneBits);
562 assert(NewSize <= OneBits);
kcc55f07962018-07-19 03:16:12 +0000563 (void)NewSize;
kcc0cab3f02018-07-19 01:23:32 +0000564 // Even if NewSize < OneBits we still use all OneBits bytes.
565 for (size_t I = 0, J = 0; I < Size; I++)
566 if (Mask[I])
567 Data[I] = T[J++];
568 return Size;
569}
570
george.karpenkov29efa6d2017-08-21 23:25:50 +0000571void MutationDispatcher::AddWordToManualDictionary(const Word &W) {
572 ManualDictionary.push_back(
573 {W, std::numeric_limits<size_t>::max()});
574}
575
dor1s2f728942018-07-17 20:37:40 +0000576void MutationDispatcher::RecordUsefulMutations() {
577 for (auto M : CurrentMutatorSequence) M->UsefulCount++;
578}
579
580void MutationDispatcher::PrintMutationStats() {
581 Printf("\nstat::mutation_usefulness: ");
dor1s9dfdc272018-08-02 22:30:03 +0000582 UpdateMutationStats();
583 for (size_t i = 0; i < Stats.size(); i++) {
584 Printf("%.3f", 100 * Stats[i]);
585 if (i < Stats.size() - 1)
586 Printf(",");
587 else
588 Printf("\n");
dor1s2f728942018-07-17 20:37:40 +0000589 }
dor1s2f728942018-07-17 20:37:40 +0000590}
591
dor1s9dfdc272018-08-02 22:30:03 +0000592void MutationDispatcher::UpdateMutationStats() {
593 // Calculate usefulness statistic for each mutation
594 for (size_t i = 0; i < Stats.size(); i++)
595 Stats[i] =
596 static_cast<double>(Mutators[i].UsefulCount) / Mutators[i].TotalCount;
597}
598
599void MutationDispatcher::UpdateDistribution() {
600 UpdateMutationStats();
601 Distribution = std::discrete_distribution<size_t>(Stats.begin(), Stats.end());
602}
603
604size_t MutationDispatcher::WeightedIndex() { return Distribution(GetRand()); }
605
george.karpenkov29efa6d2017-08-21 23:25:50 +0000606} // namespace fuzzer