29 : Rand(Rand), Options(Options) {
30 DefaultMutators.insert(
31 DefaultMutators.begin(),
36 "InsertRepeatedBytes"},
52 DefaultMutators.push_back(
55 if (
EF->LLVMFuzzerCustomMutator)
58 Mutators = DefaultMutators;
60 if (
EF->LLVMFuzzerCustomCrossOver)
66 if (Rand.
RandBool())
return Rand(256);
67 const char *Special =
"!*'();:@&=+$,/?%#[]012Az-`~.\xff\x00";
68 return Special[Rand(
sizeof(Special) - 1)];
73 return EF->LLVMFuzzerCustomMutator(Data, Size, MaxSize, Rand.
Rand());
78 if (!Corpus || Corpus->
size() < 2 || Size == 0)
80 size_t Idx = Rand(Corpus->
size());
84 MutateInPlaceHere.resize(MaxSize);
85 auto &U = MutateInPlaceHere;
86 size_t NewSize =
EF->LLVMFuzzerCustomCrossOver(
87 Data, Size, Other.data(), Other.size(), U.data(), U.size(), Rand.
Rand());
90 assert(NewSize <= MaxSize &&
"CustomCrossOver returned overisized unit");
91 memcpy(Data, U.data(), NewSize);
97 if (Size > MaxSize)
return 0;
99 size_t ShuffleAmount =
100 Rand(
std::min(Size, (
size_t)8)) + 1;
101 size_t ShuffleStart = Rand(Size - ShuffleAmount);
102 assert(ShuffleStart + ShuffleAmount <= Size);
103 std::random_shuffle(Data + ShuffleStart, Data + ShuffleStart + ShuffleAmount,
111 if (Size == 1)
return 0;
112 size_t N = Rand(Size / 2) + 1;
114 size_t Idx = Rand(Size - N + 1);
116 memmove(Data + Idx, Data + Idx + N, Size - Idx - N);
123 if (Size >= MaxSize)
return 0;
124 size_t Idx = Rand(Size + 1);
126 memmove(Data + Idx + 1, Data + Idx, Size - Idx);
134 const size_t kMinBytesToInsert = 3;
135 if (Size + kMinBytesToInsert >= MaxSize)
return 0;
136 size_t MaxBytesToInsert =
std::min(MaxSize - Size, (
size_t)128);
137 size_t N = Rand(MaxBytesToInsert - kMinBytesToInsert + 1) + kMinBytesToInsert;
138 assert(Size + N <= MaxSize && N);
139 size_t Idx = Rand(Size + 1);
141 memmove(Data + Idx + N, Data + Idx, Size - Idx);
144 for (
size_t i = 0;
i <
N;
i++)
145 Data[Idx +
i] = Byte;
151 if (Size > MaxSize)
return 0;
152 size_t Idx = Rand(Size);
159 if (Size > MaxSize)
return 0;
160 size_t Idx = Rand(Size);
161 Data[Idx] ^= 1 << Rand(8);
168 return AddWordFromDictionary(ManualDictionary, Data, Size, MaxSize);
172 uint8_t *Data,
size_t Size,
size_t MaxSize) {
173 return AddWordFromDictionary(TempAutoDictionary, Data, Size, MaxSize);
176 size_t MutationDispatcher::ApplyDictionaryEntry(uint8_t *Data,
size_t Size,
184 if (Size + W.
size() > MaxSize)
return 0;
186 memmove(Data + Idx + W.
size(), Data + Idx, Size - Idx);
187 memcpy(Data + Idx, W.
data(), W.
size());
190 if (W.
size() > Size)
return 0;
192 memcpy(Data + Idx, W.
data(), W.
size());
204 DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP(
205 T Arg1,
T Arg2,
const uint8_t *Data,
size_t Size) {
206 ScopedDoingMyOwnMemmem scoped_doing_my_own_memmem;
208 T ExistingBytes, DesiredBytes;
210 const uint8_t *
End = Data + Size;
211 for (
int Arg = 0; Arg < 2; Arg++) {
212 ExistingBytes = HandleFirst ? Arg1 :
Arg2;
213 DesiredBytes = HandleFirst ? Arg2 : Arg1;
214 DesiredBytes += Rand(-1, 1);
217 HandleFirst = !HandleFirst;
218 W.Set(reinterpret_cast<uint8_t*>(&DesiredBytes),
sizeof(
T));
219 const size_t kMaxNumPositions = 8;
220 size_t Positions[kMaxNumPositions];
221 size_t NumPositions = 0;
222 for (
const uint8_t *Cur = Data;
223 Cur < End && NumPositions < kMaxNumPositions; Cur++) {
224 Cur = (uint8_t *)
SearchMemory(Cur, End - Cur, &ExistingBytes,
sizeof(
T));
226 Positions[NumPositions++] = Cur - Data;
228 if (!NumPositions)
break;
229 return DictionaryEntry(W, Positions[Rand(NumPositions)]);
231 DictionaryEntry DE(W);
236 uint8_t *Data,
size_t Size,
size_t MaxSize) {
241 DE = MakeDictionaryEntryFromCMP(
X.A,
X.B, Data, Size);
244 if ((
X.A >> 16) == 0 && (
X.B >> 16) == 0 && Rand.
RandBool())
245 DE = MakeDictionaryEntryFromCMP((uint16_t)
X.A, (uint16_t)
X.B, Data,
248 DE = MakeDictionaryEntryFromCMP(
X.A,
X.B, Data, Size);
250 Size = ApplyDictionaryEntry(Data, Size, MaxSize, DE);
253 CmpDictionaryEntriesDeque[CmpDictionaryEntriesDequeIdx++ %
254 kCmpDictionaryEntriesDequeSize];
256 CurrentDictionaryEntrySequence.push_back(&DERef);
261 uint8_t *Data,
size_t Size,
size_t MaxSize) {
262 return AddWordFromDictionary(PersistentAutoDictionary, Data, Size, MaxSize);
265 size_t MutationDispatcher::AddWordFromDictionary(
Dictionary &
D, uint8_t *Data,
266 size_t Size,
size_t MaxSize) {
267 if (Size > MaxSize)
return 0;
268 if (D.
empty())
return 0;
270 Size = ApplyDictionaryEntry(Data, Size, MaxSize, DE);
273 CurrentDictionaryEntrySequence.push_back(&DE);
279 size_t MutationDispatcher::CopyPartOf(
const uint8_t *From,
size_t FromSize,
280 uint8_t *To,
size_t ToSize) {
282 size_t ToBeg = Rand(ToSize);
283 size_t CopySize = Rand(ToSize - ToBeg) + 1;
284 assert(ToBeg + CopySize <= ToSize);
285 CopySize =
std::min(CopySize, FromSize);
286 size_t FromBeg = Rand(FromSize - CopySize + 1);
287 assert(FromBeg + CopySize <= FromSize);
288 memmove(To + ToBeg, From + FromBeg, CopySize);
294 size_t MutationDispatcher::InsertPartOf(
const uint8_t *From,
size_t FromSize,
295 uint8_t *To,
size_t ToSize,
297 if (ToSize >= MaxToSize)
return 0;
298 size_t AvailableSpace = MaxToSize - ToSize;
299 size_t MaxCopySize =
std::min(AvailableSpace, FromSize);
300 size_t CopySize = Rand(MaxCopySize) + 1;
301 size_t FromBeg = Rand(FromSize - CopySize + 1);
302 assert(FromBeg + CopySize <= FromSize);
303 size_t ToInsertPos = Rand(ToSize + 1);
304 assert(ToInsertPos + CopySize <= MaxToSize);
305 size_t TailSize = ToSize - ToInsertPos;
307 MutateInPlaceHere.resize(MaxToSize);
308 memcpy(MutateInPlaceHere.data(), From + FromBeg, CopySize);
309 memmove(To + ToInsertPos + CopySize, To + ToInsertPos, TailSize);
310 memmove(To + ToInsertPos, MutateInPlaceHere.data(), CopySize);
312 memmove(To + ToInsertPos + CopySize, To + ToInsertPos, TailSize);
313 memmove(To + ToInsertPos, From + FromBeg, CopySize);
315 return ToSize + CopySize;
320 if (Size > MaxSize)
return 0;
322 return CopyPartOf(Data, Size, Data, Size);
324 return InsertPartOf(Data, Size, Data, Size, MaxSize);
329 if (Size > MaxSize)
return 0;
330 size_t B = Rand(Size);
331 while (B < Size && !isdigit(Data[B])) B++;
332 if (B == Size)
return 0;
334 while (E < Size && isdigit(Data[E])) E++;
338 uint64_t Val = Data[
B] -
'0';
339 for (
size_t i = B + 1;
i <
E;
i++)
340 Val = Val * 10 + Data[
i] -
'0';
344 case 0: Val++;
break;
345 case 1: Val--;
break;
346 case 2: Val /= 2;
break;
347 case 3: Val *= 2;
break;
348 case 4: Val = Rand(Val * Val);
break;
352 for (
size_t i = B;
i <
E;
i++) {
353 size_t Idx = E + B -
i - 1;
354 assert(Idx >= B && Idx < E);
355 Data[Idx] = (Val % 10) +
'0';
363 if (Size <
sizeof(
T))
return 0;
364 size_t Off = Rand(Size -
sizeof(
T) + 1);
365 assert(Off +
sizeof(
T) <= Size);
367 if (Off < 64 && !Rand(4)) {
372 memcpy(&Val, Data + Off,
sizeof(Val));
382 memcpy(Data + Off, &Val,
sizeof(Val));
389 if (Size > MaxSize)
return 0;
391 case 3:
return ChangeBinaryInteger<uint64_t>(Data, Size, Rand);
392 case 2:
return ChangeBinaryInteger<uint32_t>(Data, Size, Rand);
393 case 1:
return ChangeBinaryInteger<uint16_t>(Data, Size, Rand);
394 case 0:
return ChangeBinaryInteger<uint8_t>(Data, Size, Rand);
402 if (Size > MaxSize)
return 0;
403 if (!Corpus || Corpus->
size() < 2 || Size == 0)
return 0;
404 size_t Idx = Rand(Corpus->
size());
405 const Unit &O = (*Corpus)[Idx];
406 if (O.empty())
return 0;
407 MutateInPlaceHere.resize(MaxSize);
408 auto &U = MutateInPlaceHere;
412 NewSize =
CrossOver(Data, Size, O.data(), O.size(), U.data(), U.size());
415 NewSize = InsertPartOf(O.data(), O.size(), U.data(), U.size(), MaxSize);
420 NewSize = CopyPartOf(O.data(), O.size(), U.data(), U.size());
424 assert(NewSize > 0 &&
"CrossOver returned empty unit");
425 assert(NewSize <= MaxSize &&
"CrossOver returned overisized unit");
426 memcpy(Data, U.data(), NewSize);
431 CurrentMutatorSequence.clear();
432 CurrentDictionaryEntrySequence.clear();
437 for (
auto DE : CurrentDictionaryEntrySequence) {
447 std::vector<DictionaryEntry> V;
448 for (
auto &DE : PersistentAutoDictionary)
451 if (V.empty())
return;
452 Printf(
"###### Recommended dictionary. ######\n");
458 Printf(
"###### End of recommended dictionary. ######\n");
462 Printf(
"MS: %zd ", CurrentMutatorSequence.size());
463 for (
auto M : CurrentMutatorSequence)
465 if (!CurrentDictionaryEntrySequence.empty()) {
467 for (
auto DE : CurrentDictionaryEntrySequence) {
475 return MutateImpl(Data, Size, MaxSize, Mutators);
480 return MutateImpl(Data, Size, MaxSize, DefaultMutators);
484 size_t MutationDispatcher::MutateImpl(uint8_t *Data,
size_t Size,
486 const std::vector<Mutator> &Mutators) {
489 for (
size_t i = 0;
i <
Min(
size_t(4), MaxSize);
i++)
499 for (
int Iter = 0; Iter < 100; Iter++) {
500 auto M = Mutators[Rand(Mutators.size())];
501 size_t NewSize = (this->*(M.Fn))(Data, Size, MaxSize);
502 if (NewSize && NewSize <= MaxSize) {
505 CurrentMutatorSequence.push_back(M);
514 {W, std::numeric_limits<size_t>::max()});
518 static const size_t kMaxAutoDictSize = 1 << 14;
519 if (TempAutoDictionary.
size() >= kMaxAutoDictSize)
return;
524 TempAutoDictionary.
clear();
static char RandCh(Random &Rand)
size_t Mutate_InsertByte(uint8_t *Data, size_t Size, size_t MaxSize)
Mutates data by inserting a byte.
size_t Mutate_Custom(uint8_t *Data, size_t Size, size_t MaxSize)
Mutates data by invoking user-provided mutator.
const uint8_t * data() const
TableOfRecentCompares< uint32_t, kTORCSize > TORC4
void StartMutationSequence()
Indicate that we are about to start a new sequence of mutations.
size_t Mutate_ChangeBinaryInteger(uint8_t *Data, size_t Size, size_t MaxSize)
Change a 1-, 2-, 4-, or 8-byte integer in interesting ways.
size_t Mutate_CrossOver(uint8_t *Data, size_t Size, size_t MaxSize)
CrossOver Data with some other element of the corpus.
size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize)
Applies one of the configured mutations.
size_t CrossOver(const uint8_t *Data1, size_t Size1, const uint8_t *Data2, size_t Size2, uint8_t *Out, size_t MaxOutSize)
Creates a cross-over of two pieces of Data, returns its size.
size_t DefaultMutate(uint8_t *Data, size_t Size, size_t MaxSize)
Applies one of the default mutations.
size_t Mutate_AddWordFromManualDictionary(uint8_t *Data, size_t Size, size_t MaxSize)
Mutates data by adding a word from the manual dictionary.
void PrintRecommendedDictionary()
static GCRegistry::Add< StatepointGC > D("statepoint-example","an example strategy for statepoint")
void PrintMutationSequence()
Print the current sequence of mutations.
void RecordSuccessfulMutationSequence()
Indicate that the current sequence of mutations was successfull.
void AddWordToAutoDictionary(DictionaryEntry DE)
MutationDispatcher(Random &Rand, const FuzzingOptions &Options)
size_t Mutate_ChangeBit(uint8_t *Data, size_t Size, size_t MaxSize)
Mutates data by chanding one bit.
size_t Mutate_CustomCrossOver(uint8_t *Data, size_t Size, size_t MaxSize)
Mutates data by invoking user-provided crossover.
static GCRegistry::Add< OcamlGC > B("ocaml","ocaml 3.10-compatible GC")
Maximum length of the test input libFuzzer tries to guess a good value based on the corpus and reports it always prefer smaller inputs during the corpus shuffle When libFuzzer itself reports a bug this exit code will be used If indicates the maximal total time in seconds to run the fuzzer minimizes the provided crash input Use with etc Experimental Use value profile to guide fuzzing Number of simultaneous worker processes to run the jobs If min(jobs, NumberOfCpuCores()/2)\" is used.") FUZZER_FLAG_INT(reload
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
void Printf(const char *Fmt,...)
static PassOptionList PrintAfter("print-after", llvm::cl::desc("Print IR after specified passes"), cl::Hidden)
size_t Mutate_AddWordFromTemporaryAutoDictionary(uint8_t *Data, size_t Size, size_t MaxSize)
Mutates data by adding a word from the temporary automatic dictionary.
bool HasPositionHint() const
void ClearAutoDictionary()
size_t Mutate_InsertRepeatedBytes(uint8_t *Data, size_t Size, size_t MaxSize)
Mutates data by inserting several repeated bytes.
void AddWordToManualDictionary(const Word &W)
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang","erlang-compatible garbage collector")
size_t Mutate_AddWordFromPersistentAutoDictionary(uint8_t *Data, size_t Size, size_t MaxSize)
Mutates data by adding a word from the persistent automatic dictionary.
static const unsigned End
void push_back(DictionaryEntry DE)
size_t Mutate_CopyPart(uint8_t *Data, size_t Size, size_t MaxSize)
Mutates data by copying/inserting a part of data into a different place.
size_t Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size, size_t MaxSize)
Tries to find an ASCII integer in Data, changes it to another ASCII int.
bool ToASCII(uint8_t *Data, size_t Size)
bool ContainsWord(const Word &W) const
const void * SearchMemory(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen)
size_t GetUseCount() const
TableOfRecentCompares< uint64_t, kTORCSize > TORC8
size_t GetPositionHint() const
size_t Mutate_ChangeByte(uint8_t *Data, size_t Size, size_t MaxSize)
Mutates data by chanding one byte.
static const size_t kMaxDictSize
std::vector< uint8_t > Unit
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
size_t ChangeBinaryInteger(uint8_t *Data, size_t Size, Random &Rand)
const Word & GetW() const
size_t Mutate_AddWordFromTORC(uint8_t *Data, size_t Size, size_t MaxSize)
Mutates data by adding a word from the TORC.
size_t Mutate_EraseBytes(uint8_t *Data, size_t Size, size_t MaxSize)
Mutates data by erasing bytes.
size_t Mutate_ShuffleBytes(uint8_t *Data, size_t Size, size_t MaxSize)
Mutates data by shuffling bytes.
static void PrintASCII(const Word &W, const char *PrintAfter)