1 //===- FuzzerMutate.cpp - Mutate a test input -----------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
8 // Mutate a test input.
9 //===----------------------------------------------------------------------===//
11 #include "FuzzerDefs.h"
12 #include "FuzzerExtFunctions.h"
14 #include "FuzzerMutate.h"
15 #include "FuzzerOptions.h"
16 #include "FuzzerTracePC.h"
20 const size_t Dictionary::kMaxDictSize
;
21 static const size_t kMaxMutationsToPrint
= 10;
23 static void PrintASCII(const Word
&W
, const char *PrintAfter
) {
24 PrintASCII(W
.data(), W
.size(), PrintAfter
);
27 MutationDispatcher::MutationDispatcher(Random
&Rand
,
28 const FuzzingOptions
&Options
)
29 : Rand(Rand
), Options(Options
) {
30 DefaultMutators
.insert(
31 DefaultMutators
.begin(),
33 {&MutationDispatcher::Mutate_EraseBytes
, "EraseBytes"},
34 {&MutationDispatcher::Mutate_InsertByte
, "InsertByte"},
35 {&MutationDispatcher::Mutate_InsertRepeatedBytes
,
36 "InsertRepeatedBytes"},
37 {&MutationDispatcher::Mutate_ChangeByte
, "ChangeByte"},
38 {&MutationDispatcher::Mutate_ChangeBit
, "ChangeBit"},
39 {&MutationDispatcher::Mutate_ShuffleBytes
, "ShuffleBytes"},
40 {&MutationDispatcher::Mutate_ChangeASCIIInteger
, "ChangeASCIIInt"},
41 {&MutationDispatcher::Mutate_ChangeBinaryInteger
, "ChangeBinInt"},
42 {&MutationDispatcher::Mutate_CopyPart
, "CopyPart"},
43 {&MutationDispatcher::Mutate_CrossOver
, "CrossOver"},
44 {&MutationDispatcher::Mutate_AddWordFromManualDictionary
,
46 {&MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary
,
50 DefaultMutators
.push_back(
51 {&MutationDispatcher::Mutate_AddWordFromTORC
, "CMP"});
53 if (EF
->LLVMFuzzerCustomMutator
)
54 Mutators
.push_back({&MutationDispatcher::Mutate_Custom
, "Custom"});
56 Mutators
= DefaultMutators
;
58 if (EF
->LLVMFuzzerCustomCrossOver
)
60 {&MutationDispatcher::Mutate_CustomCrossOver
, "CustomCrossOver"});
63 static char RandCh(Random
&Rand
) {
64 if (Rand
.RandBool()) return Rand(256);
65 const char Special
[] = "!*'();:@&=+$,/?%#[]012Az-`~.\xff\x00";
66 return Special
[Rand(sizeof(Special
) - 1)];
69 size_t MutationDispatcher::Mutate_Custom(uint8_t *Data
, size_t Size
,
71 return EF
->LLVMFuzzerCustomMutator(Data
, Size
, MaxSize
, Rand
.Rand());
74 size_t MutationDispatcher::Mutate_CustomCrossOver(uint8_t *Data
, size_t Size
,
78 if (!CrossOverWith
) return 0;
79 const Unit
&Other
= *CrossOverWith
;
82 CustomCrossOverInPlaceHere
.resize(MaxSize
);
83 auto &U
= CustomCrossOverInPlaceHere
;
84 size_t NewSize
= EF
->LLVMFuzzerCustomCrossOver(
85 Data
, Size
, Other
.data(), Other
.size(), U
.data(), U
.size(), Rand
.Rand());
88 assert(NewSize
<= MaxSize
&& "CustomCrossOver returned overisized unit");
89 memcpy(Data
, U
.data(), NewSize
);
93 size_t MutationDispatcher::Mutate_ShuffleBytes(uint8_t *Data
, size_t Size
,
95 if (Size
> MaxSize
|| Size
== 0) return 0;
96 size_t ShuffleAmount
=
97 Rand(std::min(Size
, (size_t)8)) + 1; // [1,8] and <= Size.
98 size_t ShuffleStart
= Rand(Size
- ShuffleAmount
);
99 assert(ShuffleStart
+ ShuffleAmount
<= Size
);
100 std::shuffle(Data
+ ShuffleStart
, Data
+ ShuffleStart
+ ShuffleAmount
, Rand
);
104 size_t MutationDispatcher::Mutate_EraseBytes(uint8_t *Data
, size_t Size
,
106 if (Size
<= 1) return 0;
107 size_t N
= Rand(Size
/ 2) + 1;
109 size_t Idx
= Rand(Size
- N
+ 1);
110 // Erase Data[Idx:Idx+N].
111 memmove(Data
+ Idx
, Data
+ Idx
+ N
, Size
- Idx
- N
);
112 // Printf("Erase: %zd %zd => %zd; Idx %zd\n", N, Size, Size - N, Idx);
116 size_t MutationDispatcher::Mutate_InsertByte(uint8_t *Data
, size_t Size
,
118 if (Size
>= MaxSize
) return 0;
119 size_t Idx
= Rand(Size
+ 1);
120 // Insert new value at Data[Idx].
121 memmove(Data
+ Idx
+ 1, Data
+ Idx
, Size
- Idx
);
122 Data
[Idx
] = RandCh(Rand
);
126 size_t MutationDispatcher::Mutate_InsertRepeatedBytes(uint8_t *Data
,
129 const size_t kMinBytesToInsert
= 3;
130 if (Size
+ kMinBytesToInsert
>= MaxSize
) return 0;
131 size_t MaxBytesToInsert
= std::min(MaxSize
- Size
, (size_t)128);
132 size_t N
= Rand(MaxBytesToInsert
- kMinBytesToInsert
+ 1) + kMinBytesToInsert
;
133 assert(Size
+ N
<= MaxSize
&& N
);
134 size_t Idx
= Rand(Size
+ 1);
135 // Insert new values at Data[Idx].
136 memmove(Data
+ Idx
+ N
, Data
+ Idx
, Size
- Idx
);
137 // Give preference to 0x00 and 0xff.
138 uint8_t Byte
= Rand
.RandBool() ? Rand(256) : (Rand
.RandBool() ? 0 : 255);
139 for (size_t i
= 0; i
< N
; i
++)
140 Data
[Idx
+ i
] = Byte
;
144 size_t MutationDispatcher::Mutate_ChangeByte(uint8_t *Data
, size_t Size
,
146 if (Size
> MaxSize
) return 0;
147 size_t Idx
= Rand(Size
);
148 Data
[Idx
] = RandCh(Rand
);
152 size_t MutationDispatcher::Mutate_ChangeBit(uint8_t *Data
, size_t Size
,
154 if (Size
> MaxSize
) return 0;
155 size_t Idx
= Rand(Size
);
156 Data
[Idx
] ^= 1 << Rand(8);
160 size_t MutationDispatcher::Mutate_AddWordFromManualDictionary(uint8_t *Data
,
163 return AddWordFromDictionary(ManualDictionary
, Data
, Size
, MaxSize
);
166 size_t MutationDispatcher::ApplyDictionaryEntry(uint8_t *Data
, size_t Size
,
168 DictionaryEntry
&DE
) {
169 const Word
&W
= DE
.GetW();
170 bool UsePositionHint
= DE
.HasPositionHint() &&
171 DE
.GetPositionHint() + W
.size() < Size
&&
173 if (Rand
.RandBool()) { // Insert W.
174 if (Size
+ W
.size() > MaxSize
) return 0;
175 size_t Idx
= UsePositionHint
? DE
.GetPositionHint() : Rand(Size
+ 1);
176 memmove(Data
+ Idx
+ W
.size(), Data
+ Idx
, Size
- Idx
);
177 memcpy(Data
+ Idx
, W
.data(), W
.size());
179 } else { // Overwrite some bytes with W.
180 if (W
.size() > Size
) return 0;
181 size_t Idx
= UsePositionHint
? DE
.GetPositionHint() : Rand(Size
- W
.size());
182 memcpy(Data
+ Idx
, W
.data(), W
.size());
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
,
198 bool HandleFirst
= Rand
.RandBool();
199 const void *ExistingBytes
, *DesiredBytes
;
201 const uint8_t *End
= Data
+ Size
;
202 for (int Arg
= 0; Arg
< 2; Arg
++) {
203 ExistingBytes
= HandleFirst
? Arg1
: Arg2
;
204 DesiredBytes
= HandleFirst
? Arg2Mutation
: Arg1Mutation
;
205 HandleFirst
= !HandleFirst
;
206 W
.Set(reinterpret_cast<const uint8_t*>(DesiredBytes
), ArgSize
);
207 const size_t kMaxNumPositions
= 8;
208 size_t Positions
[kMaxNumPositions
];
209 size_t NumPositions
= 0;
210 for (const uint8_t *Cur
= Data
;
211 Cur
< End
&& NumPositions
< kMaxNumPositions
; Cur
++) {
213 (const uint8_t *)SearchMemory(Cur
, End
- Cur
, ExistingBytes
, ArgSize
);
215 Positions
[NumPositions
++] = Cur
- Data
;
217 if (!NumPositions
) continue;
218 return DictionaryEntry(W
, Positions
[Rand(NumPositions
)]);
220 DictionaryEntry
DE(W
);
226 DictionaryEntry
MutationDispatcher::MakeDictionaryEntryFromCMP(
227 T Arg1
, T Arg2
, const uint8_t *Data
, size_t Size
) {
228 if (Rand
.RandBool()) Arg1
= Bswap(Arg1
);
229 if (Rand
.RandBool()) Arg2
= Bswap(Arg2
);
230 T Arg1Mutation
= Arg1
+ Rand(-1, 1);
231 T Arg2Mutation
= Arg2
+ Rand(-1, 1);
232 return MakeDictionaryEntryFromCMP(&Arg1
, &Arg2
, &Arg1Mutation
, &Arg2Mutation
,
233 sizeof(Arg1
), Data
, Size
);
236 DictionaryEntry
MutationDispatcher::MakeDictionaryEntryFromCMP(
237 const Word
&Arg1
, const Word
&Arg2
, const uint8_t *Data
, size_t Size
) {
238 return MakeDictionaryEntryFromCMP(Arg1
.data(), Arg2
.data(), Arg1
.data(),
239 Arg2
.data(), Arg1
.size(), Data
, Size
);
242 size_t MutationDispatcher::Mutate_AddWordFromTORC(
243 uint8_t *Data
, size_t Size
, size_t MaxSize
) {
248 auto X
= TPC
.TORC8
.Get(Rand
.Rand());
249 DE
= MakeDictionaryEntryFromCMP(X
.A
, X
.B
, Data
, Size
);
252 auto X
= TPC
.TORC4
.Get(Rand
.Rand());
253 if ((X
.A
>> 16) == 0 && (X
.B
>> 16) == 0 && Rand
.RandBool())
254 DE
= MakeDictionaryEntryFromCMP((uint16_t)X
.A
, (uint16_t)X
.B
, Data
, Size
);
256 DE
= MakeDictionaryEntryFromCMP(X
.A
, X
.B
, Data
, Size
);
259 auto X
= TPC
.TORCW
.Get(Rand
.Rand());
260 DE
= MakeDictionaryEntryFromCMP(X
.A
, X
.B
, Data
, Size
);
262 case 3: if (Options
.UseMemmem
) {
263 auto X
= TPC
.MMT
.Get(Rand
.Rand());
264 DE
= DictionaryEntry(X
);
269 if (!DE
.GetW().size()) return 0;
270 Size
= ApplyDictionaryEntry(Data
, Size
, MaxSize
, DE
);
272 DictionaryEntry
&DERef
=
273 CmpDictionaryEntriesDeque
[CmpDictionaryEntriesDequeIdx
++ %
274 kCmpDictionaryEntriesDequeSize
];
276 CurrentDictionaryEntrySequence
.push_back(&DERef
);
280 size_t MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary(
281 uint8_t *Data
, size_t Size
, size_t MaxSize
) {
282 return AddWordFromDictionary(PersistentAutoDictionary
, Data
, Size
, MaxSize
);
285 size_t MutationDispatcher::AddWordFromDictionary(Dictionary
&D
, uint8_t *Data
,
286 size_t Size
, size_t MaxSize
) {
287 if (Size
> MaxSize
) return 0;
288 if (D
.empty()) return 0;
289 DictionaryEntry
&DE
= D
[Rand(D
.size())];
290 Size
= ApplyDictionaryEntry(Data
, Size
, MaxSize
, DE
);
293 CurrentDictionaryEntrySequence
.push_back(&DE
);
297 // Overwrites part of To[0,ToSize) with a part of From[0,FromSize).
299 size_t MutationDispatcher::CopyPartOf(const uint8_t *From
, size_t FromSize
,
300 uint8_t *To
, size_t ToSize
) {
301 // Copy From[FromBeg, FromBeg + CopySize) into To[ToBeg, ToBeg + CopySize).
302 size_t ToBeg
= Rand(ToSize
);
303 size_t CopySize
= Rand(ToSize
- ToBeg
) + 1;
304 assert(ToBeg
+ CopySize
<= ToSize
);
305 CopySize
= std::min(CopySize
, FromSize
);
306 size_t FromBeg
= Rand(FromSize
- CopySize
+ 1);
307 assert(FromBeg
+ CopySize
<= FromSize
);
308 memmove(To
+ ToBeg
, From
+ FromBeg
, CopySize
);
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
,
317 if (ToSize
>= MaxToSize
) return 0;
318 size_t AvailableSpace
= MaxToSize
- ToSize
;
319 size_t MaxCopySize
= std::min(AvailableSpace
, FromSize
);
320 size_t CopySize
= Rand(MaxCopySize
) + 1;
321 size_t FromBeg
= Rand(FromSize
- CopySize
+ 1);
322 assert(FromBeg
+ CopySize
<= FromSize
);
323 size_t ToInsertPos
= Rand(ToSize
+ 1);
324 assert(ToInsertPos
+ CopySize
<= MaxToSize
);
325 size_t TailSize
= ToSize
- ToInsertPos
;
327 MutateInPlaceHere
.resize(MaxToSize
);
328 memcpy(MutateInPlaceHere
.data(), From
+ FromBeg
, CopySize
);
329 memmove(To
+ ToInsertPos
+ CopySize
, To
+ ToInsertPos
, TailSize
);
330 memmove(To
+ ToInsertPos
, MutateInPlaceHere
.data(), CopySize
);
332 memmove(To
+ ToInsertPos
+ CopySize
, To
+ ToInsertPos
, TailSize
);
333 memmove(To
+ ToInsertPos
, From
+ FromBeg
, CopySize
);
335 return ToSize
+ CopySize
;
338 size_t MutationDispatcher::Mutate_CopyPart(uint8_t *Data
, size_t Size
,
340 if (Size
> MaxSize
|| Size
== 0) return 0;
341 // If Size == MaxSize, `InsertPartOf(...)` will
342 // fail so there's no point using it in this case.
343 if (Size
== MaxSize
|| Rand
.RandBool())
344 return CopyPartOf(Data
, Size
, Data
, Size
);
346 return InsertPartOf(Data
, Size
, Data
, Size
, MaxSize
);
349 size_t MutationDispatcher::Mutate_ChangeASCIIInteger(uint8_t *Data
, size_t Size
,
351 if (Size
> MaxSize
) return 0;
352 size_t B
= Rand(Size
);
353 while (B
< Size
&& !isdigit(Data
[B
])) B
++;
354 if (B
== Size
) return 0;
356 while (E
< Size
&& isdigit(Data
[E
])) E
++;
358 // now we have digits in [B, E).
359 // strtol and friends don't accept non-zero-teminated data, parse it manually.
360 uint64_t Val
= Data
[B
] - '0';
361 for (size_t i
= B
+ 1; i
< E
; i
++)
362 Val
= Val
* 10 + Data
[i
] - '0';
364 // Mutate the integer value.
366 case 0: Val
++; break;
367 case 1: Val
--; break;
368 case 2: Val
/= 2; break;
369 case 3: Val
*= 2; break;
370 case 4: Val
= Rand(Val
* Val
); break;
373 // Just replace the bytes with the new ones, don't bother moving bytes.
374 for (size_t i
= B
; i
< E
; i
++) {
375 size_t Idx
= E
+ B
- i
- 1;
376 assert(Idx
>= B
&& Idx
< E
);
377 Data
[Idx
] = (Val
% 10) + '0';
384 size_t ChangeBinaryInteger(uint8_t *Data
, size_t Size
, Random
&Rand
) {
385 if (Size
< sizeof(T
)) return 0;
386 size_t Off
= Rand(Size
- sizeof(T
) + 1);
387 assert(Off
+ sizeof(T
) <= Size
);
389 if (Off
< 64 && !Rand(4)) {
394 memcpy(&Val
, Data
+ Off
, sizeof(Val
));
398 Val
= Bswap(T(Bswap(Val
) + Add
)); // Add assuming different endiannes.
400 Val
= Val
+ Add
; // Add assuming current endiannes.
401 if (Add
== 0 || Rand
.RandBool()) // Maybe negate.
404 memcpy(Data
+ Off
, &Val
, sizeof(Val
));
408 size_t MutationDispatcher::Mutate_ChangeBinaryInteger(uint8_t *Data
,
411 if (Size
> MaxSize
) return 0;
413 case 3: return ChangeBinaryInteger
<uint64_t>(Data
, Size
, Rand
);
414 case 2: return ChangeBinaryInteger
<uint32_t>(Data
, Size
, Rand
);
415 case 1: return ChangeBinaryInteger
<uint16_t>(Data
, Size
, Rand
);
416 case 0: return ChangeBinaryInteger
<uint8_t>(Data
, Size
, Rand
);
422 size_t MutationDispatcher::Mutate_CrossOver(uint8_t *Data
, size_t Size
,
424 if (Size
> MaxSize
) return 0;
425 if (Size
== 0) return 0;
426 if (!CrossOverWith
) return 0;
427 const Unit
&O
= *CrossOverWith
;
428 if (O
.empty()) return 0;
432 MutateInPlaceHere
.resize(MaxSize
);
433 NewSize
= CrossOver(Data
, Size
, O
.data(), O
.size(),
434 MutateInPlaceHere
.data(), MaxSize
);
435 memcpy(Data
, MutateInPlaceHere
.data(), NewSize
);
438 NewSize
= InsertPartOf(O
.data(), O
.size(), Data
, Size
, MaxSize
);
440 NewSize
= CopyPartOf(O
.data(), O
.size(), Data
, Size
);
443 NewSize
= CopyPartOf(O
.data(), O
.size(), Data
, Size
);
447 assert(NewSize
> 0 && "CrossOver returned empty unit");
448 assert(NewSize
<= MaxSize
&& "CrossOver returned overisized unit");
452 void MutationDispatcher::StartMutationSequence() {
453 CurrentMutatorSequence
.clear();
454 CurrentDictionaryEntrySequence
.clear();
457 // Copy successful dictionary entries to PersistentAutoDictionary.
458 void MutationDispatcher::RecordSuccessfulMutationSequence() {
459 for (auto DE
: CurrentDictionaryEntrySequence
) {
460 // PersistentAutoDictionary.AddWithSuccessCountOne(DE);
461 DE
->IncSuccessCount();
462 assert(DE
->GetW().size());
463 // Linear search is fine here as this happens seldom.
464 if (!PersistentAutoDictionary
.ContainsWord(DE
->GetW()))
465 PersistentAutoDictionary
.push_back({DE
->GetW(), 1});
469 void MutationDispatcher::PrintRecommendedDictionary() {
470 Vector
<DictionaryEntry
> V
;
471 for (auto &DE
: PersistentAutoDictionary
)
472 if (!ManualDictionary
.ContainsWord(DE
.GetW()))
474 if (V
.empty()) return;
475 Printf("###### Recommended dictionary. ######\n");
477 assert(DE
.GetW().size());
479 PrintASCII(DE
.GetW(), "\"");
480 Printf(" # Uses: %zd\n", DE
.GetUseCount());
482 Printf("###### End of recommended dictionary. ######\n");
485 void MutationDispatcher::PrintMutationSequence(bool Verbose
) {
486 Printf("MS: %zd ", CurrentMutatorSequence
.size());
487 size_t EntriesToPrint
=
488 Verbose
? CurrentMutatorSequence
.size()
489 : std::min(kMaxMutationsToPrint
, CurrentMutatorSequence
.size());
490 for (size_t i
= 0; i
< EntriesToPrint
; i
++)
491 Printf("%s-", CurrentMutatorSequence
[i
].Name
);
492 if (!CurrentDictionaryEntrySequence
.empty()) {
494 EntriesToPrint
= Verbose
? CurrentDictionaryEntrySequence
.size()
495 : std::min(kMaxMutationsToPrint
,
496 CurrentDictionaryEntrySequence
.size());
497 for (size_t i
= 0; i
< EntriesToPrint
; i
++) {
499 PrintASCII(CurrentDictionaryEntrySequence
[i
]->GetW(), "\"-");
504 std::string
MutationDispatcher::MutationSequence() {
506 for (auto M
: CurrentMutatorSequence
) {
513 size_t MutationDispatcher::Mutate(uint8_t *Data
, size_t Size
, size_t MaxSize
) {
514 return MutateImpl(Data
, Size
, MaxSize
, Mutators
);
517 size_t MutationDispatcher::DefaultMutate(uint8_t *Data
, size_t Size
,
519 return MutateImpl(Data
, Size
, MaxSize
, DefaultMutators
);
522 // Mutates Data in place, returns new size.
523 size_t MutationDispatcher::MutateImpl(uint8_t *Data
, size_t Size
,
525 Vector
<Mutator
> &Mutators
) {
527 // Some mutations may fail (e.g. can't insert more bytes if Size == MaxSize),
528 // in which case they will return 0.
529 // Try several times before returning un-mutated data.
530 for (int Iter
= 0; Iter
< 100; Iter
++) {
531 auto M
= Mutators
[Rand(Mutators
.size())];
532 size_t NewSize
= (this->*(M
.Fn
))(Data
, Size
, MaxSize
);
533 if (NewSize
&& NewSize
<= MaxSize
) {
534 if (Options
.OnlyASCII
)
535 ToASCII(Data
, NewSize
);
536 CurrentMutatorSequence
.push_back(M
);
541 return 1; // Fallback, should not happen frequently.
544 // Mask represents the set of Data bytes that are worth mutating.
545 size_t MutationDispatcher::MutateWithMask(uint8_t *Data
, size_t Size
,
547 const Vector
<uint8_t> &Mask
) {
548 size_t MaskedSize
= std::min(Size
, Mask
.size());
549 // * Copy the worthy bytes into a temporary array T
552 // This is totally unoptimized.
553 auto &T
= MutateWithMaskTemp
;
557 for (size_t I
= 0; I
< MaskedSize
; I
++)
559 T
[OneBits
++] = Data
[I
];
561 if (!OneBits
) return 0;
563 size_t NewSize
= Mutate(T
.data(), OneBits
, OneBits
);
564 assert(NewSize
<= OneBits
);
566 // Even if NewSize < OneBits we still use all OneBits bytes.
567 for (size_t I
= 0, J
= 0; I
< MaskedSize
; I
++)
573 void MutationDispatcher::AddWordToManualDictionary(const Word
&W
) {
574 ManualDictionary
.push_back(
575 {W
, std::numeric_limits
<size_t>::max()});
578 } // namespace fuzzer