Coverage Report

Created: 2018-09-25 14:53

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