]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/compiler-rt/lib/fuzzer/FuzzerMutate.cpp
Merge clang 7.0.1 and several follow-up changes
[FreeBSD/FreeBSD.git] / contrib / compiler-rt / lib / fuzzer / FuzzerMutate.cpp
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 "FuzzerMutate.h"
13 #include "FuzzerCorpus.h"
14 #include "FuzzerDefs.h"
15 #include "FuzzerExtFunctions.h"
16 #include "FuzzerIO.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", 0, 0},
34           {&MutationDispatcher::Mutate_InsertByte, "InsertByte", 0, 0},
35           {&MutationDispatcher::Mutate_InsertRepeatedBytes,
36            "InsertRepeatedBytes", 0, 0},
37           {&MutationDispatcher::Mutate_ChangeByte, "ChangeByte", 0, 0},
38           {&MutationDispatcher::Mutate_ChangeBit, "ChangeBit", 0, 0},
39           {&MutationDispatcher::Mutate_ShuffleBytes, "ShuffleBytes", 0, 0},
40           {&MutationDispatcher::Mutate_ChangeASCIIInteger, "ChangeASCIIInt", 0,
41            0},
42           {&MutationDispatcher::Mutate_ChangeBinaryInteger, "ChangeBinInt", 0,
43            0},
44           {&MutationDispatcher::Mutate_CopyPart, "CopyPart", 0, 0},
45           {&MutationDispatcher::Mutate_CrossOver, "CrossOver", 0, 0},
46           {&MutationDispatcher::Mutate_AddWordFromManualDictionary,
47            "ManualDict", 0, 0},
48           {&MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary,
49            "PersAutoDict", 0, 0},
50       });
51   if(Options.UseCmp)
52     DefaultMutators.push_back(
53         {&MutationDispatcher::Mutate_AddWordFromTORC, "CMP", 0, 0});
54
55   if (EF->LLVMFuzzerCustomMutator)
56     Mutators.push_back({&MutationDispatcher::Mutate_Custom, "Custom", 0, 0});
57   else
58     Mutators = DefaultMutators;
59
60   if (EF->LLVMFuzzerCustomCrossOver)
61     Mutators.push_back(
62         {&MutationDispatcher::Mutate_CustomCrossOver, "CustomCrossOver", 0, 0});
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");
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);
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);
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);
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::ApplyDictionaryEntry(uint8_t *Data, size_t Size,
169                                                 size_t MaxSize,
170                                                 DictionaryEntry &DE) {
171   const Word &W = DE.GetW();
172   bool UsePositionHint = DE.HasPositionHint() &&
173                          DE.GetPositionHint() + W.size() < Size &&
174                          Rand.RandBool();
175   if (Rand.RandBool()) {  // Insert W.
176     if (Size + W.size() > MaxSize) return 0;
177     size_t Idx = UsePositionHint ? DE.GetPositionHint() : Rand(Size + 1);
178     memmove(Data + Idx + W.size(), Data + Idx, Size - Idx);
179     memcpy(Data + Idx, W.data(), W.size());
180     Size += W.size();
181   } else {  // Overwrite some bytes with W.
182     if (W.size() > Size) return 0;
183     size_t Idx = UsePositionHint ? DE.GetPositionHint() : Rand(Size - W.size());
184     memcpy(Data + Idx, W.data(), W.size());
185   }
186   return Size;
187 }
188
189 // Somewhere in the past we have observed a comparison instructions
190 // with arguments Arg1 Arg2. This function tries to guess a dictionary
191 // entry that will satisfy that comparison.
192 // It first tries to find one of the arguments (possibly swapped) in the
193 // input and if it succeeds it creates a DE with a position hint.
194 // Otherwise it creates a DE with one of the arguments w/o a position hint.
195 DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP(
196     const void *Arg1, const void *Arg2,
197     const void *Arg1Mutation, const void *Arg2Mutation,
198     size_t ArgSize, const uint8_t *Data,
199     size_t Size) {
200   bool HandleFirst = Rand.RandBool();
201   const void *ExistingBytes, *DesiredBytes;
202   Word W;
203   const uint8_t *End = Data + Size;
204   for (int Arg = 0; Arg < 2; Arg++) {
205     ExistingBytes = HandleFirst ? Arg1 : Arg2;
206     DesiredBytes = HandleFirst ? Arg2Mutation : Arg1Mutation;
207     HandleFirst = !HandleFirst;
208     W.Set(reinterpret_cast<const uint8_t*>(DesiredBytes), ArgSize);
209     const size_t kMaxNumPositions = 8;
210     size_t Positions[kMaxNumPositions];
211     size_t NumPositions = 0;
212     for (const uint8_t *Cur = Data;
213          Cur < End && NumPositions < kMaxNumPositions; Cur++) {
214       Cur =
215           (const uint8_t *)SearchMemory(Cur, End - Cur, ExistingBytes, ArgSize);
216       if (!Cur) break;
217       Positions[NumPositions++] = Cur - Data;
218     }
219     if (!NumPositions) continue;
220     return DictionaryEntry(W, Positions[Rand(NumPositions)]);
221   }
222   DictionaryEntry DE(W);
223   return DE;
224 }
225
226
227 template <class T>
228 DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP(
229     T Arg1, T Arg2, const uint8_t *Data, size_t Size) {
230   if (Rand.RandBool()) Arg1 = Bswap(Arg1);
231   if (Rand.RandBool()) Arg2 = Bswap(Arg2);
232   T Arg1Mutation = Arg1 + Rand(-1, 1);
233   T Arg2Mutation = Arg2 + Rand(-1, 1);
234   return MakeDictionaryEntryFromCMP(&Arg1, &Arg2, &Arg1Mutation, &Arg2Mutation,
235                                     sizeof(Arg1), Data, Size);
236 }
237
238 DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP(
239     const Word &Arg1, const Word &Arg2, const uint8_t *Data, size_t Size) {
240   return MakeDictionaryEntryFromCMP(Arg1.data(), Arg2.data(), Arg1.data(),
241                                     Arg2.data(), Arg1.size(), Data, Size);
242 }
243
244 size_t MutationDispatcher::Mutate_AddWordFromTORC(
245     uint8_t *Data, size_t Size, size_t MaxSize) {
246   Word W;
247   DictionaryEntry DE;
248   switch (Rand(4)) {
249   case 0: {
250     auto X = TPC.TORC8.Get(Rand.Rand());
251     DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size);
252   } break;
253   case 1: {
254     auto X = TPC.TORC4.Get(Rand.Rand());
255     if ((X.A >> 16) == 0 && (X.B >> 16) == 0 && Rand.RandBool())
256       DE = MakeDictionaryEntryFromCMP((uint16_t)X.A, (uint16_t)X.B, Data, Size);
257     else
258       DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size);
259   } break;
260   case 2: {
261     auto X = TPC.TORCW.Get(Rand.Rand());
262     DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size);
263   } break;
264   case 3: if (Options.UseMemmem) {
265     auto X = TPC.MMT.Get(Rand.Rand());
266     DE = DictionaryEntry(X);
267   } break;
268   default:
269     assert(0);
270   }
271   if (!DE.GetW().size()) return 0;
272   Size = ApplyDictionaryEntry(Data, Size, MaxSize, DE);
273   if (!Size) return 0;
274   DictionaryEntry &DERef =
275       CmpDictionaryEntriesDeque[CmpDictionaryEntriesDequeIdx++ %
276                                 kCmpDictionaryEntriesDequeSize];
277   DERef = DE;
278   CurrentDictionaryEntrySequence.push_back(&DERef);
279   return Size;
280 }
281
282 size_t MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary(
283     uint8_t *Data, size_t Size, size_t MaxSize) {
284   return AddWordFromDictionary(PersistentAutoDictionary, Data, Size, MaxSize);
285 }
286
287 size_t MutationDispatcher::AddWordFromDictionary(Dictionary &D, uint8_t *Data,
288                                                  size_t Size, size_t MaxSize) {
289   if (Size > MaxSize) return 0;
290   if (D.empty()) return 0;
291   DictionaryEntry &DE = D[Rand(D.size())];
292   Size = ApplyDictionaryEntry(Data, Size, MaxSize, DE);
293   if (!Size) return 0;
294   DE.IncUseCount();
295   CurrentDictionaryEntrySequence.push_back(&DE);
296   return Size;
297 }
298
299 // Overwrites part of To[0,ToSize) with a part of From[0,FromSize).
300 // Returns ToSize.
301 size_t MutationDispatcher::CopyPartOf(const uint8_t *From, size_t FromSize,
302                                       uint8_t *To, size_t ToSize) {
303   // Copy From[FromBeg, FromBeg + CopySize) into To[ToBeg, ToBeg + CopySize).
304   size_t ToBeg = Rand(ToSize);
305   size_t CopySize = Rand(ToSize - ToBeg) + 1;
306   assert(ToBeg + CopySize <= ToSize);
307   CopySize = std::min(CopySize, FromSize);
308   size_t FromBeg = Rand(FromSize - CopySize + 1);
309   assert(FromBeg + CopySize <= FromSize);
310   memmove(To + ToBeg, From + FromBeg, CopySize);
311   return ToSize;
312 }
313
314 // Inserts part of From[0,ToSize) into To.
315 // Returns new size of To on success or 0 on failure.
316 size_t MutationDispatcher::InsertPartOf(const uint8_t *From, size_t FromSize,
317                                         uint8_t *To, size_t ToSize,
318                                         size_t MaxToSize) {
319   if (ToSize >= MaxToSize) return 0;
320   size_t AvailableSpace = MaxToSize - ToSize;
321   size_t MaxCopySize = std::min(AvailableSpace, FromSize);
322   size_t CopySize = Rand(MaxCopySize) + 1;
323   size_t FromBeg = Rand(FromSize - CopySize + 1);
324   assert(FromBeg + CopySize <= FromSize);
325   size_t ToInsertPos = Rand(ToSize + 1);
326   assert(ToInsertPos + CopySize <= MaxToSize);
327   size_t TailSize = ToSize - ToInsertPos;
328   if (To == From) {
329     MutateInPlaceHere.resize(MaxToSize);
330     memcpy(MutateInPlaceHere.data(), From + FromBeg, CopySize);
331     memmove(To + ToInsertPos + CopySize, To + ToInsertPos, TailSize);
332     memmove(To + ToInsertPos, MutateInPlaceHere.data(), CopySize);
333   } else {
334     memmove(To + ToInsertPos + CopySize, To + ToInsertPos, TailSize);
335     memmove(To + ToInsertPos, From + FromBeg, CopySize);
336   }
337   return ToSize + CopySize;
338 }
339
340 size_t MutationDispatcher::Mutate_CopyPart(uint8_t *Data, size_t Size,
341                                            size_t MaxSize) {
342   if (Size > MaxSize || Size == 0) return 0;
343   // If Size == MaxSize, `InsertPartOf(...)` will
344   // fail so there's no point using it in this case.
345   if (Size == MaxSize || 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);
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);
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);
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);
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);
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);
447   }
448   assert(NewSize > 0 && "CrossOver returned empty unit");
449   assert(NewSize <= MaxSize && "CrossOver returned overisized unit");
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());
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   RecordUsefulMutations();
470 }
471
472 void MutationDispatcher::PrintRecommendedDictionary() {
473   Vector<DictionaryEntry> V;
474   for (auto &DE : PersistentAutoDictionary)
475     if (!ManualDictionary.ContainsWord(DE.GetW()))
476       V.push_back(DE);
477   if (V.empty()) return;
478   Printf("###### Recommended dictionary. ######\n");
479   for (auto &DE: V) {
480     assert(DE.GetW().size());
481     Printf("\"");
482     PrintASCII(DE.GetW(), "\"");
483     Printf(" # Uses: %zd\n", DE.GetUseCount());
484   }
485   Printf("###### End of recommended dictionary. ######\n");
486 }
487
488 void MutationDispatcher::PrintMutationSequence() {
489   Printf("MS: %zd ", CurrentMutatorSequence.size());
490   for (auto M : CurrentMutatorSequence) 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                                       Vector<Mutator> &Mutators) {
513   assert(MaxSize > 0);
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       M->TotalCount++;
525       return NewSize;
526     }
527   }
528   *Data = ' ';
529   return 1;   // Fallback, should not happen frequently.
530 }
531
532 // Mask represents the set of Data bytes that are worth mutating.
533 size_t MutationDispatcher::MutateWithMask(uint8_t *Data, size_t Size,
534                                           size_t MaxSize,
535                                           const Vector<uint8_t> &Mask) {
536   assert(Size <= Mask.size());
537   // * Copy the worthy bytes into a temporary array T
538   // * Mutate T
539   // * Copy T back.
540   // This is totally unoptimized.
541   auto &T = MutateWithMaskTemp;
542   if (T.size() < Size)
543     T.resize(Size);
544   size_t OneBits = 0;
545   for (size_t I = 0; I < Size; I++)
546     if (Mask[I])
547       T[OneBits++] = Data[I];
548
549   assert(!T.empty());
550   size_t NewSize = Mutate(T.data(), OneBits, OneBits);
551   assert(NewSize <= OneBits);
552   (void)NewSize;
553   // Even if NewSize < OneBits we still use all OneBits bytes.
554   for (size_t I = 0, J = 0; I < Size; I++)
555     if (Mask[I])
556       Data[I] = T[J++];
557   return Size;
558 }
559
560 void MutationDispatcher::AddWordToManualDictionary(const Word &W) {
561   ManualDictionary.push_back(
562       {W, std::numeric_limits<size_t>::max()});
563 }
564
565 void MutationDispatcher::RecordUsefulMutations() {
566   for (auto M : CurrentMutatorSequence) M->UsefulCount++;
567 }
568
569 void MutationDispatcher::PrintMutationStats() {
570   Printf("\nstat::mutation_usefulness:      ");
571   for (size_t i = 0; i < Mutators.size(); i++) {
572     double UsefulPercentage =
573         Mutators[i].TotalCount
574             ? (100.0 * Mutators[i].UsefulCount) / Mutators[i].TotalCount
575             : 0;
576     Printf("%.3f", UsefulPercentage);
577     if (i < Mutators.size() - 1) Printf(",");
578   }
579   Printf("\n");
580 }
581
582 }  // namespace fuzzer