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