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