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()) return Rand(256); 65 const char Special[] = "!*'();:@&=+$,/?%#[]012Az-`~.\xff\x00"; 66 return Special[Rand(sizeof(Special) - 1)]; 67 } 68 69 size_t MutationDispatcher::Mutate_Custom(uint8_t *Data, size_t Size, 70 size_t MaxSize) { 71 return EF->LLVMFuzzerCustomMutator(Data, Size, MaxSize, Rand.Rand()); 72 } 73 74 size_t MutationDispatcher::Mutate_CustomCrossOver(uint8_t *Data, size_t Size, 75 size_t MaxSize) { 76 if (Size == 0) 77 return 0; 78 if (!CrossOverWith) return 0; 79 const Unit &Other = *CrossOverWith; 80 if (Other.empty()) 81 return 0; 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()); 86 if (!NewSize) 87 return 0; 88 assert(NewSize <= MaxSize && "CustomCrossOver returned overisized unit"); 89 memcpy(Data, U.data(), NewSize); 90 return NewSize; 91 } 92 93 size_t MutationDispatcher::Mutate_ShuffleBytes(uint8_t *Data, size_t Size, 94 size_t MaxSize) { 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); 101 return Size; 102 } 103 104 size_t MutationDispatcher::Mutate_EraseBytes(uint8_t *Data, size_t Size, 105 size_t MaxSize) { 106 if (Size <= 1) return 0; 107 size_t N = Rand(Size / 2) + 1; 108 assert(N < Size); 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); 113 return Size - N; 114 } 115 116 size_t MutationDispatcher::Mutate_InsertByte(uint8_t *Data, size_t Size, 117 size_t MaxSize) { 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); 123 return Size + 1; 124 } 125 126 size_t MutationDispatcher::Mutate_InsertRepeatedBytes(uint8_t *Data, 127 size_t Size, 128 size_t MaxSize) { 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; 141 return Size + N; 142 } 143 144 size_t MutationDispatcher::Mutate_ChangeByte(uint8_t *Data, size_t Size, 145 size_t MaxSize) { 146 if (Size > MaxSize) return 0; 147 size_t Idx = Rand(Size); 148 Data[Idx] = RandCh(Rand); 149 return Size; 150 } 151 152 size_t MutationDispatcher::Mutate_ChangeBit(uint8_t *Data, size_t Size, 153 size_t MaxSize) { 154 if (Size > MaxSize) return 0; 155 size_t Idx = Rand(Size); 156 Data[Idx] ^= 1 << Rand(8); 157 return Size; 158 } 159 160 size_t MutationDispatcher::Mutate_AddWordFromManualDictionary(uint8_t *Data, 161 size_t Size, 162 size_t MaxSize) { 163 return AddWordFromDictionary(ManualDictionary, Data, Size, MaxSize); 164 } 165 166 size_t MutationDispatcher::ApplyDictionaryEntry(uint8_t *Data, size_t Size, 167 size_t MaxSize, 168 DictionaryEntry &DE) { 169 const Word &W = DE.GetW(); 170 bool UsePositionHint = DE.HasPositionHint() && 171 DE.GetPositionHint() + W.size() < Size && 172 Rand.RandBool(); 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()); 178 Size += 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()); 183 } 184 return Size; 185 } 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 size_t Size) { 198 bool HandleFirst = Rand.RandBool(); 199 const void *ExistingBytes, *DesiredBytes; 200 Word W; 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++) { 212 Cur = 213 (const uint8_t *)SearchMemory(Cur, End - Cur, ExistingBytes, ArgSize); 214 if (!Cur) break; 215 Positions[NumPositions++] = Cur - Data; 216 } 217 if (!NumPositions) continue; 218 return DictionaryEntry(W, Positions[Rand(NumPositions)]); 219 } 220 DictionaryEntry DE(W); 221 return DE; 222 } 223 224 225 template <class T> 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); 234 } 235 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); 240 } 241 242 size_t MutationDispatcher::Mutate_AddWordFromTORC( 243 uint8_t *Data, size_t Size, size_t MaxSize) { 244 Word W; 245 DictionaryEntry DE; 246 switch (Rand(4)) { 247 case 0: { 248 auto X = TPC.TORC8.Get(Rand.Rand()); 249 DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size); 250 } break; 251 case 1: { 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); 255 else 256 DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size); 257 } break; 258 case 2: { 259 auto X = TPC.TORCW.Get(Rand.Rand()); 260 DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size); 261 } break; 262 case 3: if (Options.UseMemmem) { 263 auto X = TPC.MMT.Get(Rand.Rand()); 264 DE = DictionaryEntry(X); 265 } break; 266 default: 267 assert(0); 268 } 269 if (!DE.GetW().size()) return 0; 270 Size = ApplyDictionaryEntry(Data, Size, MaxSize, DE); 271 if (!Size) return 0; 272 DictionaryEntry &DERef = 273 CmpDictionaryEntriesDeque[CmpDictionaryEntriesDequeIdx++ % 274 kCmpDictionaryEntriesDequeSize]; 275 DERef = DE; 276 CurrentDictionaryEntrySequence.push_back(&DERef); 277 return Size; 278 } 279 280 size_t MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary( 281 uint8_t *Data, size_t Size, size_t MaxSize) { 282 return AddWordFromDictionary(PersistentAutoDictionary, Data, Size, MaxSize); 283 } 284 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); 291 if (!Size) return 0; 292 DE.IncUseCount(); 293 CurrentDictionaryEntrySequence.push_back(&DE); 294 return Size; 295 } 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 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); 309 return ToSize; 310 } 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 size_t MaxToSize) { 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; 326 if (To == From) { 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); 331 } else { 332 memmove(To + ToInsertPos + CopySize, To + ToInsertPos, TailSize); 333 memmove(To + ToInsertPos, From + FromBeg, CopySize); 334 } 335 return ToSize + CopySize; 336 } 337 338 size_t MutationDispatcher::Mutate_CopyPart(uint8_t *Data, size_t Size, 339 size_t MaxSize) { 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); 345 else 346 return InsertPartOf(Data, Size, Data, Size, MaxSize); 347 } 348 349 size_t MutationDispatcher::Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size, 350 size_t MaxSize) { 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; 355 size_t E = B; 356 while (E < Size && isdigit(Data[E])) E++; 357 assert(B < 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'; 363 364 // Mutate the integer value. 365 switch(Rand(5)) { 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; 371 default: assert(0); 372 } 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'; 378 Val /= 10; 379 } 380 return Size; 381 } 382 383 template<class T> 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); 388 T Val; 389 if (Off < 64 && !Rand(4)) { 390 Val = Size; 391 if (Rand.RandBool()) 392 Val = Bswap(Val); 393 } else { 394 memcpy(&Val, Data + Off, sizeof(Val)); 395 T Add = Rand(21); 396 Add -= 10; 397 if (Rand.RandBool()) 398 Val = Bswap(T(Bswap(Val) + Add)); // Add assuming different endiannes. 399 else 400 Val = Val + Add; // Add assuming current endiannes. 401 if (Add == 0 || Rand.RandBool()) // Maybe negate. 402 Val = -Val; 403 } 404 memcpy(Data + Off, &Val, sizeof(Val)); 405 return Size; 406 } 407 408 size_t MutationDispatcher::Mutate_ChangeBinaryInteger(uint8_t *Data, 409 size_t Size, 410 size_t MaxSize) { 411 if (Size > MaxSize) return 0; 412 switch (Rand(4)) { 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); 417 default: assert(0); 418 } 419 return 0; 420 } 421 422 size_t MutationDispatcher::Mutate_CrossOver(uint8_t *Data, size_t Size, 423 size_t MaxSize) { 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; 429 size_t NewSize = 0; 430 switch(Rand(3)) { 431 case 0: 432 MutateInPlaceHere.resize(MaxSize); 433 NewSize = CrossOver(Data, Size, O.data(), O.size(), 434 MutateInPlaceHere.data(), MaxSize); 435 memcpy(Data, MutateInPlaceHere.data(), NewSize); 436 break; 437 case 1: 438 NewSize = InsertPartOf(O.data(), O.size(), Data, Size, MaxSize); 439 if (!NewSize) 440 NewSize = CopyPartOf(O.data(), O.size(), Data, Size); 441 break; 442 case 2: 443 NewSize = CopyPartOf(O.data(), O.size(), Data, Size); 444 break; 445 default: assert(0); 446 } 447 assert(NewSize > 0 && "CrossOver returned empty unit"); 448 assert(NewSize <= MaxSize && "CrossOver returned overisized unit"); 449 return NewSize; 450 } 451 452 void MutationDispatcher::StartMutationSequence() { 453 CurrentMutatorSequence.clear(); 454 CurrentDictionaryEntrySequence.clear(); 455 } 456 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}); 466 } 467 } 468 469 void MutationDispatcher::PrintRecommendedDictionary() { 470 Vector<DictionaryEntry> V; 471 for (auto &DE : PersistentAutoDictionary) 472 if (!ManualDictionary.ContainsWord(DE.GetW())) 473 V.push_back(DE); 474 if (V.empty()) return; 475 Printf("###### Recommended dictionary. ######\n"); 476 for (auto &DE: V) { 477 assert(DE.GetW().size()); 478 Printf("\""); 479 PrintASCII(DE.GetW(), "\""); 480 Printf(" # Uses: %zd\n", DE.GetUseCount()); 481 } 482 Printf("###### End of recommended dictionary. ######\n"); 483 } 484 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()) { 493 Printf(" DE: "); 494 EntriesToPrint = Verbose ? CurrentDictionaryEntrySequence.size() 495 : std::min(kMaxMutationsToPrint, 496 CurrentDictionaryEntrySequence.size()); 497 for (size_t i = 0; i < EntriesToPrint; i++) { 498 Printf("\""); 499 PrintASCII(CurrentDictionaryEntrySequence[i]->GetW(), "\"-"); 500 } 501 } 502 } 503 504 std::string MutationDispatcher::MutationSequence() { 505 std::string MS; 506 for (auto M : CurrentMutatorSequence) { 507 MS += M.Name; 508 MS += "-"; 509 } 510 return MS; 511 } 512 513 size_t MutationDispatcher::Mutate(uint8_t *Data, size_t Size, size_t MaxSize) { 514 return MutateImpl(Data, Size, MaxSize, Mutators); 515 } 516 517 size_t MutationDispatcher::DefaultMutate(uint8_t *Data, size_t Size, 518 size_t MaxSize) { 519 return MutateImpl(Data, Size, MaxSize, DefaultMutators); 520 } 521 522 // Mutates Data in place, returns new size. 523 size_t MutationDispatcher::MutateImpl(uint8_t *Data, size_t Size, 524 size_t MaxSize, 525 Vector<Mutator> &Mutators) { 526 assert(MaxSize > 0); 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); 537 return NewSize; 538 } 539 } 540 *Data = ' '; 541 return 1; // Fallback, should not happen frequently. 542 } 543 544 // Mask represents the set of Data bytes that are worth mutating. 545 size_t MutationDispatcher::MutateWithMask(uint8_t *Data, size_t Size, 546 size_t MaxSize, 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 550 // * Mutate T 551 // * Copy T back. 552 // This is totally unoptimized. 553 auto &T = MutateWithMaskTemp; 554 if (T.size() < Size) 555 T.resize(Size); 556 size_t OneBits = 0; 557 for (size_t I = 0; I < MaskedSize; I++) 558 if (Mask[I]) 559 T[OneBits++] = Data[I]; 560 561 if (!OneBits) return 0; 562 assert(!T.empty()); 563 size_t NewSize = Mutate(T.data(), OneBits, OneBits); 564 assert(NewSize <= OneBits); 565 (void)NewSize; 566 // Even if NewSize < OneBits we still use all OneBits bytes. 567 for (size_t I = 0, J = 0; I < MaskedSize; I++) 568 if (Mask[I]) 569 Data[I] = T[J++]; 570 return Size; 571 } 572 573 void MutationDispatcher::AddWordToManualDictionary(const Word &W) { 574 ManualDictionary.push_back( 575 {W, std::numeric_limits<size_t>::max()}); 576 } 577 578 } // namespace fuzzer 579