xref: /openbsd-src/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerMutate.cpp (revision 810390e339a5425391477d5d41c78d7cab2424ac)
13cab2bb3Spatrick //===- FuzzerMutate.cpp - Mutate a test input -----------------------------===//
23cab2bb3Spatrick //
33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information.
53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63cab2bb3Spatrick //
73cab2bb3Spatrick //===----------------------------------------------------------------------===//
83cab2bb3Spatrick // Mutate a test input.
93cab2bb3Spatrick //===----------------------------------------------------------------------===//
103cab2bb3Spatrick 
113cab2bb3Spatrick #include "FuzzerDefs.h"
123cab2bb3Spatrick #include "FuzzerExtFunctions.h"
133cab2bb3Spatrick #include "FuzzerIO.h"
143cab2bb3Spatrick #include "FuzzerMutate.h"
153cab2bb3Spatrick #include "FuzzerOptions.h"
163cab2bb3Spatrick #include "FuzzerTracePC.h"
173cab2bb3Spatrick 
183cab2bb3Spatrick namespace fuzzer {
193cab2bb3Spatrick 
203cab2bb3Spatrick const size_t Dictionary::kMaxDictSize;
21d89ec533Spatrick static const size_t kMaxMutationsToPrint = 10;
223cab2bb3Spatrick 
PrintASCII(const Word & W,const char * PrintAfter)233cab2bb3Spatrick static void PrintASCII(const Word &W, const char *PrintAfter) {
243cab2bb3Spatrick   PrintASCII(W.data(), W.size(), PrintAfter);
253cab2bb3Spatrick }
263cab2bb3Spatrick 
MutationDispatcher(Random & Rand,const FuzzingOptions & Options)273cab2bb3Spatrick MutationDispatcher::MutationDispatcher(Random &Rand,
283cab2bb3Spatrick                                        const FuzzingOptions &Options)
293cab2bb3Spatrick     : Rand(Rand), Options(Options) {
303cab2bb3Spatrick   DefaultMutators.insert(
313cab2bb3Spatrick       DefaultMutators.begin(),
323cab2bb3Spatrick       {
333cab2bb3Spatrick           {&MutationDispatcher::Mutate_EraseBytes, "EraseBytes"},
343cab2bb3Spatrick           {&MutationDispatcher::Mutate_InsertByte, "InsertByte"},
353cab2bb3Spatrick           {&MutationDispatcher::Mutate_InsertRepeatedBytes,
363cab2bb3Spatrick            "InsertRepeatedBytes"},
373cab2bb3Spatrick           {&MutationDispatcher::Mutate_ChangeByte, "ChangeByte"},
383cab2bb3Spatrick           {&MutationDispatcher::Mutate_ChangeBit, "ChangeBit"},
393cab2bb3Spatrick           {&MutationDispatcher::Mutate_ShuffleBytes, "ShuffleBytes"},
403cab2bb3Spatrick           {&MutationDispatcher::Mutate_ChangeASCIIInteger, "ChangeASCIIInt"},
413cab2bb3Spatrick           {&MutationDispatcher::Mutate_ChangeBinaryInteger, "ChangeBinInt"},
423cab2bb3Spatrick           {&MutationDispatcher::Mutate_CopyPart, "CopyPart"},
433cab2bb3Spatrick           {&MutationDispatcher::Mutate_CrossOver, "CrossOver"},
443cab2bb3Spatrick           {&MutationDispatcher::Mutate_AddWordFromManualDictionary,
453cab2bb3Spatrick            "ManualDict"},
463cab2bb3Spatrick           {&MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary,
473cab2bb3Spatrick            "PersAutoDict"},
483cab2bb3Spatrick       });
493cab2bb3Spatrick   if(Options.UseCmp)
503cab2bb3Spatrick     DefaultMutators.push_back(
513cab2bb3Spatrick         {&MutationDispatcher::Mutate_AddWordFromTORC, "CMP"});
523cab2bb3Spatrick 
533cab2bb3Spatrick   if (EF->LLVMFuzzerCustomMutator)
543cab2bb3Spatrick     Mutators.push_back({&MutationDispatcher::Mutate_Custom, "Custom"});
553cab2bb3Spatrick   else
563cab2bb3Spatrick     Mutators = DefaultMutators;
573cab2bb3Spatrick 
583cab2bb3Spatrick   if (EF->LLVMFuzzerCustomCrossOver)
593cab2bb3Spatrick     Mutators.push_back(
603cab2bb3Spatrick         {&MutationDispatcher::Mutate_CustomCrossOver, "CustomCrossOver"});
613cab2bb3Spatrick }
623cab2bb3Spatrick 
RandCh(Random & Rand)633cab2bb3Spatrick static char RandCh(Random &Rand) {
64d89ec533Spatrick   if (Rand.RandBool())
65d89ec533Spatrick     return static_cast<char>(Rand(256));
663cab2bb3Spatrick   const char Special[] = "!*'();:@&=+$,/?%#[]012Az-`~.\xff\x00";
673cab2bb3Spatrick   return Special[Rand(sizeof(Special) - 1)];
683cab2bb3Spatrick }
693cab2bb3Spatrick 
Mutate_Custom(uint8_t * Data,size_t Size,size_t MaxSize)703cab2bb3Spatrick size_t MutationDispatcher::Mutate_Custom(uint8_t *Data, size_t Size,
713cab2bb3Spatrick                                          size_t MaxSize) {
72d89ec533Spatrick   if (EF->__msan_unpoison)
73d89ec533Spatrick     EF->__msan_unpoison(Data, Size);
74d89ec533Spatrick   if (EF->__msan_unpoison_param)
75d89ec533Spatrick     EF->__msan_unpoison_param(4);
76d89ec533Spatrick   return EF->LLVMFuzzerCustomMutator(Data, Size, MaxSize,
77d89ec533Spatrick                                      Rand.Rand<unsigned int>());
783cab2bb3Spatrick }
793cab2bb3Spatrick 
Mutate_CustomCrossOver(uint8_t * Data,size_t Size,size_t MaxSize)803cab2bb3Spatrick size_t MutationDispatcher::Mutate_CustomCrossOver(uint8_t *Data, size_t Size,
813cab2bb3Spatrick                                                   size_t MaxSize) {
823cab2bb3Spatrick   if (Size == 0)
833cab2bb3Spatrick     return 0;
843cab2bb3Spatrick   if (!CrossOverWith) return 0;
853cab2bb3Spatrick   const Unit &Other = *CrossOverWith;
863cab2bb3Spatrick   if (Other.empty())
873cab2bb3Spatrick     return 0;
883cab2bb3Spatrick   CustomCrossOverInPlaceHere.resize(MaxSize);
893cab2bb3Spatrick   auto &U = CustomCrossOverInPlaceHere;
90d89ec533Spatrick 
91d89ec533Spatrick   if (EF->__msan_unpoison) {
92d89ec533Spatrick     EF->__msan_unpoison(Data, Size);
93d89ec533Spatrick     EF->__msan_unpoison(Other.data(), Other.size());
94d89ec533Spatrick     EF->__msan_unpoison(U.data(), U.size());
95d89ec533Spatrick   }
96d89ec533Spatrick   if (EF->__msan_unpoison_param)
97d89ec533Spatrick     EF->__msan_unpoison_param(7);
983cab2bb3Spatrick   size_t NewSize = EF->LLVMFuzzerCustomCrossOver(
99d89ec533Spatrick       Data, Size, Other.data(), Other.size(), U.data(), U.size(),
100d89ec533Spatrick       Rand.Rand<unsigned int>());
101d89ec533Spatrick 
1023cab2bb3Spatrick   if (!NewSize)
1033cab2bb3Spatrick     return 0;
1043cab2bb3Spatrick   assert(NewSize <= MaxSize && "CustomCrossOver returned overisized unit");
1053cab2bb3Spatrick   memcpy(Data, U.data(), NewSize);
1063cab2bb3Spatrick   return NewSize;
1073cab2bb3Spatrick }
1083cab2bb3Spatrick 
Mutate_ShuffleBytes(uint8_t * Data,size_t Size,size_t MaxSize)1093cab2bb3Spatrick size_t MutationDispatcher::Mutate_ShuffleBytes(uint8_t *Data, size_t Size,
1103cab2bb3Spatrick                                                size_t MaxSize) {
1113cab2bb3Spatrick   if (Size > MaxSize || Size == 0) return 0;
1123cab2bb3Spatrick   size_t ShuffleAmount =
1133cab2bb3Spatrick       Rand(std::min(Size, (size_t)8)) + 1; // [1,8] and <= Size.
1143cab2bb3Spatrick   size_t ShuffleStart = Rand(Size - ShuffleAmount);
1153cab2bb3Spatrick   assert(ShuffleStart + ShuffleAmount <= Size);
1163cab2bb3Spatrick   std::shuffle(Data + ShuffleStart, Data + ShuffleStart + ShuffleAmount, Rand);
1173cab2bb3Spatrick   return Size;
1183cab2bb3Spatrick }
1193cab2bb3Spatrick 
Mutate_EraseBytes(uint8_t * Data,size_t Size,size_t MaxSize)1203cab2bb3Spatrick size_t MutationDispatcher::Mutate_EraseBytes(uint8_t *Data, size_t Size,
1213cab2bb3Spatrick                                              size_t MaxSize) {
1223cab2bb3Spatrick   if (Size <= 1) return 0;
1233cab2bb3Spatrick   size_t N = Rand(Size / 2) + 1;
1243cab2bb3Spatrick   assert(N < Size);
1253cab2bb3Spatrick   size_t Idx = Rand(Size - N + 1);
1263cab2bb3Spatrick   // Erase Data[Idx:Idx+N].
1273cab2bb3Spatrick   memmove(Data + Idx, Data + Idx + N, Size - Idx - N);
1283cab2bb3Spatrick   // Printf("Erase: %zd %zd => %zd; Idx %zd\n", N, Size, Size - N, Idx);
1293cab2bb3Spatrick   return Size - N;
1303cab2bb3Spatrick }
1313cab2bb3Spatrick 
Mutate_InsertByte(uint8_t * Data,size_t Size,size_t MaxSize)1323cab2bb3Spatrick size_t MutationDispatcher::Mutate_InsertByte(uint8_t *Data, size_t Size,
1333cab2bb3Spatrick                                              size_t MaxSize) {
1343cab2bb3Spatrick   if (Size >= MaxSize) return 0;
1353cab2bb3Spatrick   size_t Idx = Rand(Size + 1);
1363cab2bb3Spatrick   // Insert new value at Data[Idx].
1373cab2bb3Spatrick   memmove(Data + Idx + 1, Data + Idx, Size - Idx);
1383cab2bb3Spatrick   Data[Idx] = RandCh(Rand);
1393cab2bb3Spatrick   return Size + 1;
1403cab2bb3Spatrick }
1413cab2bb3Spatrick 
Mutate_InsertRepeatedBytes(uint8_t * Data,size_t Size,size_t MaxSize)1423cab2bb3Spatrick size_t MutationDispatcher::Mutate_InsertRepeatedBytes(uint8_t *Data,
1433cab2bb3Spatrick                                                       size_t Size,
1443cab2bb3Spatrick                                                       size_t MaxSize) {
1453cab2bb3Spatrick   const size_t kMinBytesToInsert = 3;
1463cab2bb3Spatrick   if (Size + kMinBytesToInsert >= MaxSize) return 0;
1473cab2bb3Spatrick   size_t MaxBytesToInsert = std::min(MaxSize - Size, (size_t)128);
1483cab2bb3Spatrick   size_t N = Rand(MaxBytesToInsert - kMinBytesToInsert + 1) + kMinBytesToInsert;
1493cab2bb3Spatrick   assert(Size + N <= MaxSize && N);
1503cab2bb3Spatrick   size_t Idx = Rand(Size + 1);
1513cab2bb3Spatrick   // Insert new values at Data[Idx].
1523cab2bb3Spatrick   memmove(Data + Idx + N, Data + Idx, Size - Idx);
1533cab2bb3Spatrick   // Give preference to 0x00 and 0xff.
154d89ec533Spatrick   uint8_t Byte = static_cast<uint8_t>(
155d89ec533Spatrick       Rand.RandBool() ? Rand(256) : (Rand.RandBool() ? 0 : 255));
1563cab2bb3Spatrick   for (size_t i = 0; i < N; i++)
1573cab2bb3Spatrick     Data[Idx + i] = Byte;
1583cab2bb3Spatrick   return Size + N;
1593cab2bb3Spatrick }
1603cab2bb3Spatrick 
Mutate_ChangeByte(uint8_t * Data,size_t Size,size_t MaxSize)1613cab2bb3Spatrick size_t MutationDispatcher::Mutate_ChangeByte(uint8_t *Data, size_t Size,
1623cab2bb3Spatrick                                              size_t MaxSize) {
1633cab2bb3Spatrick   if (Size > MaxSize) return 0;
1643cab2bb3Spatrick   size_t Idx = Rand(Size);
1653cab2bb3Spatrick   Data[Idx] = RandCh(Rand);
1663cab2bb3Spatrick   return Size;
1673cab2bb3Spatrick }
1683cab2bb3Spatrick 
Mutate_ChangeBit(uint8_t * Data,size_t Size,size_t MaxSize)1693cab2bb3Spatrick size_t MutationDispatcher::Mutate_ChangeBit(uint8_t *Data, size_t Size,
1703cab2bb3Spatrick                                             size_t MaxSize) {
1713cab2bb3Spatrick   if (Size > MaxSize) return 0;
1723cab2bb3Spatrick   size_t Idx = Rand(Size);
1733cab2bb3Spatrick   Data[Idx] ^= 1 << Rand(8);
1743cab2bb3Spatrick   return Size;
1753cab2bb3Spatrick }
1763cab2bb3Spatrick 
Mutate_AddWordFromManualDictionary(uint8_t * Data,size_t Size,size_t MaxSize)1773cab2bb3Spatrick size_t MutationDispatcher::Mutate_AddWordFromManualDictionary(uint8_t *Data,
1783cab2bb3Spatrick                                                               size_t Size,
1793cab2bb3Spatrick                                                               size_t MaxSize) {
1803cab2bb3Spatrick   return AddWordFromDictionary(ManualDictionary, Data, Size, MaxSize);
1813cab2bb3Spatrick }
1823cab2bb3Spatrick 
ApplyDictionaryEntry(uint8_t * Data,size_t Size,size_t MaxSize,DictionaryEntry & DE)1833cab2bb3Spatrick size_t MutationDispatcher::ApplyDictionaryEntry(uint8_t *Data, size_t Size,
1843cab2bb3Spatrick                                                 size_t MaxSize,
1853cab2bb3Spatrick                                                 DictionaryEntry &DE) {
1863cab2bb3Spatrick   const Word &W = DE.GetW();
1873cab2bb3Spatrick   bool UsePositionHint = DE.HasPositionHint() &&
1883cab2bb3Spatrick                          DE.GetPositionHint() + W.size() < Size &&
1893cab2bb3Spatrick                          Rand.RandBool();
1903cab2bb3Spatrick   if (Rand.RandBool()) {  // Insert W.
1913cab2bb3Spatrick     if (Size + W.size() > MaxSize) return 0;
1923cab2bb3Spatrick     size_t Idx = UsePositionHint ? DE.GetPositionHint() : Rand(Size + 1);
1933cab2bb3Spatrick     memmove(Data + Idx + W.size(), Data + Idx, Size - Idx);
1943cab2bb3Spatrick     memcpy(Data + Idx, W.data(), W.size());
1953cab2bb3Spatrick     Size += W.size();
1963cab2bb3Spatrick   } else {  // Overwrite some bytes with W.
1973cab2bb3Spatrick     if (W.size() > Size) return 0;
198d89ec533Spatrick     size_t Idx =
199d89ec533Spatrick         UsePositionHint ? DE.GetPositionHint() : Rand(Size + 1 - W.size());
2003cab2bb3Spatrick     memcpy(Data + Idx, W.data(), W.size());
2013cab2bb3Spatrick   }
2023cab2bb3Spatrick   return Size;
2033cab2bb3Spatrick }
2043cab2bb3Spatrick 
2053cab2bb3Spatrick // Somewhere in the past we have observed a comparison instructions
2063cab2bb3Spatrick // with arguments Arg1 Arg2. This function tries to guess a dictionary
2073cab2bb3Spatrick // entry that will satisfy that comparison.
2083cab2bb3Spatrick // It first tries to find one of the arguments (possibly swapped) in the
2093cab2bb3Spatrick // input and if it succeeds it creates a DE with a position hint.
2103cab2bb3Spatrick // Otherwise it creates a DE with one of the arguments w/o a position hint.
MakeDictionaryEntryFromCMP(const void * Arg1,const void * Arg2,const void * Arg1Mutation,const void * Arg2Mutation,size_t ArgSize,const uint8_t * Data,size_t Size)2113cab2bb3Spatrick DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP(
2123cab2bb3Spatrick     const void *Arg1, const void *Arg2,
2133cab2bb3Spatrick     const void *Arg1Mutation, const void *Arg2Mutation,
2143cab2bb3Spatrick     size_t ArgSize, const uint8_t *Data,
2153cab2bb3Spatrick     size_t Size) {
2163cab2bb3Spatrick   bool HandleFirst = Rand.RandBool();
2173cab2bb3Spatrick   const void *ExistingBytes, *DesiredBytes;
2183cab2bb3Spatrick   Word W;
2193cab2bb3Spatrick   const uint8_t *End = Data + Size;
2203cab2bb3Spatrick   for (int Arg = 0; Arg < 2; Arg++) {
2213cab2bb3Spatrick     ExistingBytes = HandleFirst ? Arg1 : Arg2;
2223cab2bb3Spatrick     DesiredBytes = HandleFirst ? Arg2Mutation : Arg1Mutation;
2233cab2bb3Spatrick     HandleFirst = !HandleFirst;
2243cab2bb3Spatrick     W.Set(reinterpret_cast<const uint8_t*>(DesiredBytes), ArgSize);
2253cab2bb3Spatrick     const size_t kMaxNumPositions = 8;
2263cab2bb3Spatrick     size_t Positions[kMaxNumPositions];
2273cab2bb3Spatrick     size_t NumPositions = 0;
2283cab2bb3Spatrick     for (const uint8_t *Cur = Data;
2293cab2bb3Spatrick          Cur < End && NumPositions < kMaxNumPositions; Cur++) {
2303cab2bb3Spatrick       Cur =
2313cab2bb3Spatrick           (const uint8_t *)SearchMemory(Cur, End - Cur, ExistingBytes, ArgSize);
2323cab2bb3Spatrick       if (!Cur) break;
2333cab2bb3Spatrick       Positions[NumPositions++] = Cur - Data;
2343cab2bb3Spatrick     }
2353cab2bb3Spatrick     if (!NumPositions) continue;
2363cab2bb3Spatrick     return DictionaryEntry(W, Positions[Rand(NumPositions)]);
2373cab2bb3Spatrick   }
2383cab2bb3Spatrick   DictionaryEntry DE(W);
2393cab2bb3Spatrick   return DE;
2403cab2bb3Spatrick }
2413cab2bb3Spatrick 
2423cab2bb3Spatrick 
2433cab2bb3Spatrick template <class T>
MakeDictionaryEntryFromCMP(T Arg1,T Arg2,const uint8_t * Data,size_t Size)2443cab2bb3Spatrick DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP(
2453cab2bb3Spatrick     T Arg1, T Arg2, const uint8_t *Data, size_t Size) {
2463cab2bb3Spatrick   if (Rand.RandBool()) Arg1 = Bswap(Arg1);
2473cab2bb3Spatrick   if (Rand.RandBool()) Arg2 = Bswap(Arg2);
248d89ec533Spatrick   T Arg1Mutation = static_cast<T>(Arg1 + Rand(-1, 1));
249d89ec533Spatrick   T Arg2Mutation = static_cast<T>(Arg2 + Rand(-1, 1));
2503cab2bb3Spatrick   return MakeDictionaryEntryFromCMP(&Arg1, &Arg2, &Arg1Mutation, &Arg2Mutation,
2513cab2bb3Spatrick                                     sizeof(Arg1), Data, Size);
2523cab2bb3Spatrick }
2533cab2bb3Spatrick 
MakeDictionaryEntryFromCMP(const Word & Arg1,const Word & Arg2,const uint8_t * Data,size_t Size)2543cab2bb3Spatrick DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP(
2553cab2bb3Spatrick     const Word &Arg1, const Word &Arg2, const uint8_t *Data, size_t Size) {
2563cab2bb3Spatrick   return MakeDictionaryEntryFromCMP(Arg1.data(), Arg2.data(), Arg1.data(),
2573cab2bb3Spatrick                                     Arg2.data(), Arg1.size(), Data, Size);
2583cab2bb3Spatrick }
2593cab2bb3Spatrick 
Mutate_AddWordFromTORC(uint8_t * Data,size_t Size,size_t MaxSize)2603cab2bb3Spatrick size_t MutationDispatcher::Mutate_AddWordFromTORC(
2613cab2bb3Spatrick     uint8_t *Data, size_t Size, size_t MaxSize) {
2623cab2bb3Spatrick   Word W;
2633cab2bb3Spatrick   DictionaryEntry DE;
2643cab2bb3Spatrick   switch (Rand(4)) {
2653cab2bb3Spatrick   case 0: {
266d89ec533Spatrick     auto X = TPC.TORC8.Get(Rand.Rand<size_t>());
2673cab2bb3Spatrick     DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size);
2683cab2bb3Spatrick   } break;
2693cab2bb3Spatrick   case 1: {
270d89ec533Spatrick     auto X = TPC.TORC4.Get(Rand.Rand<size_t>());
2713cab2bb3Spatrick     if ((X.A >> 16) == 0 && (X.B >> 16) == 0 && Rand.RandBool())
2723cab2bb3Spatrick       DE = MakeDictionaryEntryFromCMP((uint16_t)X.A, (uint16_t)X.B, Data, Size);
2733cab2bb3Spatrick     else
2743cab2bb3Spatrick       DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size);
2753cab2bb3Spatrick   } break;
2763cab2bb3Spatrick   case 2: {
277d89ec533Spatrick     auto X = TPC.TORCW.Get(Rand.Rand<size_t>());
2783cab2bb3Spatrick     DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size);
2793cab2bb3Spatrick   } break;
2803cab2bb3Spatrick   case 3: if (Options.UseMemmem) {
281d89ec533Spatrick       auto X = TPC.MMT.Get(Rand.Rand<size_t>());
2823cab2bb3Spatrick       DE = DictionaryEntry(X);
2833cab2bb3Spatrick   } break;
2843cab2bb3Spatrick   default:
2853cab2bb3Spatrick     assert(0);
2863cab2bb3Spatrick   }
2873cab2bb3Spatrick   if (!DE.GetW().size()) return 0;
2883cab2bb3Spatrick   Size = ApplyDictionaryEntry(Data, Size, MaxSize, DE);
2893cab2bb3Spatrick   if (!Size) return 0;
2903cab2bb3Spatrick   DictionaryEntry &DERef =
2913cab2bb3Spatrick       CmpDictionaryEntriesDeque[CmpDictionaryEntriesDequeIdx++ %
2923cab2bb3Spatrick                                 kCmpDictionaryEntriesDequeSize];
2933cab2bb3Spatrick   DERef = DE;
2943cab2bb3Spatrick   CurrentDictionaryEntrySequence.push_back(&DERef);
2953cab2bb3Spatrick   return Size;
2963cab2bb3Spatrick }
2973cab2bb3Spatrick 
Mutate_AddWordFromPersistentAutoDictionary(uint8_t * Data,size_t Size,size_t MaxSize)2983cab2bb3Spatrick size_t MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary(
2993cab2bb3Spatrick     uint8_t *Data, size_t Size, size_t MaxSize) {
3003cab2bb3Spatrick   return AddWordFromDictionary(PersistentAutoDictionary, Data, Size, MaxSize);
3013cab2bb3Spatrick }
3023cab2bb3Spatrick 
AddWordFromDictionary(Dictionary & D,uint8_t * Data,size_t Size,size_t MaxSize)3033cab2bb3Spatrick size_t MutationDispatcher::AddWordFromDictionary(Dictionary &D, uint8_t *Data,
3043cab2bb3Spatrick                                                  size_t Size, size_t MaxSize) {
3053cab2bb3Spatrick   if (Size > MaxSize) return 0;
3063cab2bb3Spatrick   if (D.empty()) return 0;
3073cab2bb3Spatrick   DictionaryEntry &DE = D[Rand(D.size())];
3083cab2bb3Spatrick   Size = ApplyDictionaryEntry(Data, Size, MaxSize, DE);
3093cab2bb3Spatrick   if (!Size) return 0;
3103cab2bb3Spatrick   DE.IncUseCount();
3113cab2bb3Spatrick   CurrentDictionaryEntrySequence.push_back(&DE);
3123cab2bb3Spatrick   return Size;
3133cab2bb3Spatrick }
3143cab2bb3Spatrick 
3153cab2bb3Spatrick // Overwrites part of To[0,ToSize) with a part of From[0,FromSize).
3163cab2bb3Spatrick // Returns ToSize.
CopyPartOf(const uint8_t * From,size_t FromSize,uint8_t * To,size_t ToSize)3173cab2bb3Spatrick size_t MutationDispatcher::CopyPartOf(const uint8_t *From, size_t FromSize,
3183cab2bb3Spatrick                                       uint8_t *To, size_t ToSize) {
3193cab2bb3Spatrick   // Copy From[FromBeg, FromBeg + CopySize) into To[ToBeg, ToBeg + CopySize).
3203cab2bb3Spatrick   size_t ToBeg = Rand(ToSize);
3213cab2bb3Spatrick   size_t CopySize = Rand(ToSize - ToBeg) + 1;
3223cab2bb3Spatrick   assert(ToBeg + CopySize <= ToSize);
3233cab2bb3Spatrick   CopySize = std::min(CopySize, FromSize);
3243cab2bb3Spatrick   size_t FromBeg = Rand(FromSize - CopySize + 1);
3253cab2bb3Spatrick   assert(FromBeg + CopySize <= FromSize);
3263cab2bb3Spatrick   memmove(To + ToBeg, From + FromBeg, CopySize);
3273cab2bb3Spatrick   return ToSize;
3283cab2bb3Spatrick }
3293cab2bb3Spatrick 
3303cab2bb3Spatrick // Inserts part of From[0,ToSize) into To.
3313cab2bb3Spatrick // Returns new size of To on success or 0 on failure.
InsertPartOf(const uint8_t * From,size_t FromSize,uint8_t * To,size_t ToSize,size_t MaxToSize)3323cab2bb3Spatrick size_t MutationDispatcher::InsertPartOf(const uint8_t *From, size_t FromSize,
3333cab2bb3Spatrick                                         uint8_t *To, size_t ToSize,
3343cab2bb3Spatrick                                         size_t MaxToSize) {
3353cab2bb3Spatrick   if (ToSize >= MaxToSize) return 0;
3363cab2bb3Spatrick   size_t AvailableSpace = MaxToSize - ToSize;
3373cab2bb3Spatrick   size_t MaxCopySize = std::min(AvailableSpace, FromSize);
3383cab2bb3Spatrick   size_t CopySize = Rand(MaxCopySize) + 1;
3393cab2bb3Spatrick   size_t FromBeg = Rand(FromSize - CopySize + 1);
3403cab2bb3Spatrick   assert(FromBeg + CopySize <= FromSize);
3413cab2bb3Spatrick   size_t ToInsertPos = Rand(ToSize + 1);
3423cab2bb3Spatrick   assert(ToInsertPos + CopySize <= MaxToSize);
3433cab2bb3Spatrick   size_t TailSize = ToSize - ToInsertPos;
3443cab2bb3Spatrick   if (To == From) {
3453cab2bb3Spatrick     MutateInPlaceHere.resize(MaxToSize);
3463cab2bb3Spatrick     memcpy(MutateInPlaceHere.data(), From + FromBeg, CopySize);
3473cab2bb3Spatrick     memmove(To + ToInsertPos + CopySize, To + ToInsertPos, TailSize);
3483cab2bb3Spatrick     memmove(To + ToInsertPos, MutateInPlaceHere.data(), CopySize);
3493cab2bb3Spatrick   } else {
3503cab2bb3Spatrick     memmove(To + ToInsertPos + CopySize, To + ToInsertPos, TailSize);
3513cab2bb3Spatrick     memmove(To + ToInsertPos, From + FromBeg, CopySize);
3523cab2bb3Spatrick   }
3533cab2bb3Spatrick   return ToSize + CopySize;
3543cab2bb3Spatrick }
3553cab2bb3Spatrick 
Mutate_CopyPart(uint8_t * Data,size_t Size,size_t MaxSize)3563cab2bb3Spatrick size_t MutationDispatcher::Mutate_CopyPart(uint8_t *Data, size_t Size,
3573cab2bb3Spatrick                                            size_t MaxSize) {
3583cab2bb3Spatrick   if (Size > MaxSize || Size == 0) return 0;
3593cab2bb3Spatrick   // If Size == MaxSize, `InsertPartOf(...)` will
3603cab2bb3Spatrick   // fail so there's no point using it in this case.
3613cab2bb3Spatrick   if (Size == MaxSize || Rand.RandBool())
3623cab2bb3Spatrick     return CopyPartOf(Data, Size, Data, Size);
3633cab2bb3Spatrick   else
3643cab2bb3Spatrick     return InsertPartOf(Data, Size, Data, Size, MaxSize);
3653cab2bb3Spatrick }
3663cab2bb3Spatrick 
Mutate_ChangeASCIIInteger(uint8_t * Data,size_t Size,size_t MaxSize)3673cab2bb3Spatrick size_t MutationDispatcher::Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size,
3683cab2bb3Spatrick                                                      size_t MaxSize) {
3693cab2bb3Spatrick   if (Size > MaxSize) return 0;
3703cab2bb3Spatrick   size_t B = Rand(Size);
3713cab2bb3Spatrick   while (B < Size && !isdigit(Data[B])) B++;
3723cab2bb3Spatrick   if (B == Size) return 0;
3733cab2bb3Spatrick   size_t E = B;
3743cab2bb3Spatrick   while (E < Size && isdigit(Data[E])) E++;
3753cab2bb3Spatrick   assert(B < E);
3763cab2bb3Spatrick   // now we have digits in [B, E).
3773cab2bb3Spatrick   // strtol and friends don't accept non-zero-teminated data, parse it manually.
3783cab2bb3Spatrick   uint64_t Val = Data[B] - '0';
3793cab2bb3Spatrick   for (size_t i = B + 1; i < E; i++)
3803cab2bb3Spatrick     Val = Val * 10 + Data[i] - '0';
3813cab2bb3Spatrick 
3823cab2bb3Spatrick   // Mutate the integer value.
3833cab2bb3Spatrick   switch(Rand(5)) {
3843cab2bb3Spatrick     case 0: Val++; break;
3853cab2bb3Spatrick     case 1: Val--; break;
3863cab2bb3Spatrick     case 2: Val /= 2; break;
3873cab2bb3Spatrick     case 3: Val *= 2; break;
3883cab2bb3Spatrick     case 4: Val = Rand(Val * Val); break;
3893cab2bb3Spatrick     default: assert(0);
3903cab2bb3Spatrick   }
3913cab2bb3Spatrick   // Just replace the bytes with the new ones, don't bother moving bytes.
3923cab2bb3Spatrick   for (size_t i = B; i < E; i++) {
3933cab2bb3Spatrick     size_t Idx = E + B - i - 1;
3943cab2bb3Spatrick     assert(Idx >= B && Idx < E);
3953cab2bb3Spatrick     Data[Idx] = (Val % 10) + '0';
3963cab2bb3Spatrick     Val /= 10;
3973cab2bb3Spatrick   }
3983cab2bb3Spatrick   return Size;
3993cab2bb3Spatrick }
4003cab2bb3Spatrick 
4013cab2bb3Spatrick template<class T>
ChangeBinaryInteger(uint8_t * Data,size_t Size,Random & Rand)4023cab2bb3Spatrick size_t ChangeBinaryInteger(uint8_t *Data, size_t Size, Random &Rand) {
4033cab2bb3Spatrick   if (Size < sizeof(T)) return 0;
4043cab2bb3Spatrick   size_t Off = Rand(Size - sizeof(T) + 1);
4053cab2bb3Spatrick   assert(Off + sizeof(T) <= Size);
4063cab2bb3Spatrick   T Val;
4073cab2bb3Spatrick   if (Off < 64 && !Rand(4)) {
408d89ec533Spatrick     Val = static_cast<T>(Size);
4093cab2bb3Spatrick     if (Rand.RandBool())
4103cab2bb3Spatrick       Val = Bswap(Val);
4113cab2bb3Spatrick   } else {
4123cab2bb3Spatrick     memcpy(&Val, Data + Off, sizeof(Val));
413d89ec533Spatrick     T Add = static_cast<T>(Rand(21));
4143cab2bb3Spatrick     Add -= 10;
4153cab2bb3Spatrick     if (Rand.RandBool())
4163cab2bb3Spatrick       Val = Bswap(T(Bswap(Val) + Add)); // Add assuming different endiannes.
4173cab2bb3Spatrick     else
4183cab2bb3Spatrick       Val = Val + Add;               // Add assuming current endiannes.
4193cab2bb3Spatrick     if (Add == 0 || Rand.RandBool()) // Maybe negate.
4203cab2bb3Spatrick       Val = -Val;
4213cab2bb3Spatrick   }
4223cab2bb3Spatrick   memcpy(Data + Off, &Val, sizeof(Val));
4233cab2bb3Spatrick   return Size;
4243cab2bb3Spatrick }
4253cab2bb3Spatrick 
Mutate_ChangeBinaryInteger(uint8_t * Data,size_t Size,size_t MaxSize)4263cab2bb3Spatrick size_t MutationDispatcher::Mutate_ChangeBinaryInteger(uint8_t *Data,
4273cab2bb3Spatrick                                                       size_t Size,
4283cab2bb3Spatrick                                                       size_t MaxSize) {
4293cab2bb3Spatrick   if (Size > MaxSize) return 0;
4303cab2bb3Spatrick   switch (Rand(4)) {
4313cab2bb3Spatrick     case 3: return ChangeBinaryInteger<uint64_t>(Data, Size, Rand);
4323cab2bb3Spatrick     case 2: return ChangeBinaryInteger<uint32_t>(Data, Size, Rand);
4333cab2bb3Spatrick     case 1: return ChangeBinaryInteger<uint16_t>(Data, Size, Rand);
4343cab2bb3Spatrick     case 0: return ChangeBinaryInteger<uint8_t>(Data, Size, Rand);
4353cab2bb3Spatrick     default: assert(0);
4363cab2bb3Spatrick   }
4373cab2bb3Spatrick   return 0;
4383cab2bb3Spatrick }
4393cab2bb3Spatrick 
Mutate_CrossOver(uint8_t * Data,size_t Size,size_t MaxSize)4403cab2bb3Spatrick size_t MutationDispatcher::Mutate_CrossOver(uint8_t *Data, size_t Size,
4413cab2bb3Spatrick                                             size_t MaxSize) {
4423cab2bb3Spatrick   if (Size > MaxSize) return 0;
4433cab2bb3Spatrick   if (Size == 0) return 0;
4443cab2bb3Spatrick   if (!CrossOverWith) return 0;
4453cab2bb3Spatrick   const Unit &O = *CrossOverWith;
4463cab2bb3Spatrick   if (O.empty()) return 0;
4473cab2bb3Spatrick   size_t NewSize = 0;
4483cab2bb3Spatrick   switch(Rand(3)) {
4493cab2bb3Spatrick     case 0:
450d89ec533Spatrick       MutateInPlaceHere.resize(MaxSize);
451d89ec533Spatrick       NewSize = CrossOver(Data, Size, O.data(), O.size(),
452d89ec533Spatrick                           MutateInPlaceHere.data(), MaxSize);
453d89ec533Spatrick       memcpy(Data, MutateInPlaceHere.data(), NewSize);
4543cab2bb3Spatrick       break;
4553cab2bb3Spatrick     case 1:
456d89ec533Spatrick       NewSize = InsertPartOf(O.data(), O.size(), Data, Size, MaxSize);
4573cab2bb3Spatrick       if (!NewSize)
458d89ec533Spatrick         NewSize = CopyPartOf(O.data(), O.size(), Data, Size);
4593cab2bb3Spatrick       break;
4603cab2bb3Spatrick     case 2:
461d89ec533Spatrick       NewSize = CopyPartOf(O.data(), O.size(), Data, Size);
4623cab2bb3Spatrick       break;
4633cab2bb3Spatrick     default: assert(0);
4643cab2bb3Spatrick   }
4653cab2bb3Spatrick   assert(NewSize > 0 && "CrossOver returned empty unit");
4663cab2bb3Spatrick   assert(NewSize <= MaxSize && "CrossOver returned overisized unit");
4673cab2bb3Spatrick   return NewSize;
4683cab2bb3Spatrick }
4693cab2bb3Spatrick 
StartMutationSequence()4703cab2bb3Spatrick void MutationDispatcher::StartMutationSequence() {
4713cab2bb3Spatrick   CurrentMutatorSequence.clear();
4723cab2bb3Spatrick   CurrentDictionaryEntrySequence.clear();
4733cab2bb3Spatrick }
4743cab2bb3Spatrick 
4753cab2bb3Spatrick // Copy successful dictionary entries to PersistentAutoDictionary.
RecordSuccessfulMutationSequence()4763cab2bb3Spatrick void MutationDispatcher::RecordSuccessfulMutationSequence() {
4773cab2bb3Spatrick   for (auto DE : CurrentDictionaryEntrySequence) {
4783cab2bb3Spatrick     // PersistentAutoDictionary.AddWithSuccessCountOne(DE);
4793cab2bb3Spatrick     DE->IncSuccessCount();
4803cab2bb3Spatrick     assert(DE->GetW().size());
4813cab2bb3Spatrick     // Linear search is fine here as this happens seldom.
4823cab2bb3Spatrick     if (!PersistentAutoDictionary.ContainsWord(DE->GetW()))
483d89ec533Spatrick       PersistentAutoDictionary.push_back(*DE);
4843cab2bb3Spatrick   }
4853cab2bb3Spatrick }
4863cab2bb3Spatrick 
PrintRecommendedDictionary()4873cab2bb3Spatrick void MutationDispatcher::PrintRecommendedDictionary() {
488*810390e3Srobert   std::vector<DictionaryEntry> V;
4893cab2bb3Spatrick   for (auto &DE : PersistentAutoDictionary)
4903cab2bb3Spatrick     if (!ManualDictionary.ContainsWord(DE.GetW()))
4913cab2bb3Spatrick       V.push_back(DE);
4923cab2bb3Spatrick   if (V.empty()) return;
4933cab2bb3Spatrick   Printf("###### Recommended dictionary. ######\n");
4943cab2bb3Spatrick   for (auto &DE: V) {
4953cab2bb3Spatrick     assert(DE.GetW().size());
4963cab2bb3Spatrick     Printf("\"");
4973cab2bb3Spatrick     PrintASCII(DE.GetW(), "\"");
4983cab2bb3Spatrick     Printf(" # Uses: %zd\n", DE.GetUseCount());
4993cab2bb3Spatrick   }
5003cab2bb3Spatrick   Printf("###### End of recommended dictionary. ######\n");
5013cab2bb3Spatrick }
5023cab2bb3Spatrick 
PrintMutationSequence(bool Verbose)503d89ec533Spatrick void MutationDispatcher::PrintMutationSequence(bool Verbose) {
5043cab2bb3Spatrick   Printf("MS: %zd ", CurrentMutatorSequence.size());
505d89ec533Spatrick   size_t EntriesToPrint =
506d89ec533Spatrick       Verbose ? CurrentMutatorSequence.size()
507d89ec533Spatrick               : std::min(kMaxMutationsToPrint, CurrentMutatorSequence.size());
508d89ec533Spatrick   for (size_t i = 0; i < EntriesToPrint; i++)
509d89ec533Spatrick     Printf("%s-", CurrentMutatorSequence[i].Name);
5103cab2bb3Spatrick   if (!CurrentDictionaryEntrySequence.empty()) {
5113cab2bb3Spatrick     Printf(" DE: ");
512d89ec533Spatrick     EntriesToPrint = Verbose ? CurrentDictionaryEntrySequence.size()
513d89ec533Spatrick                              : std::min(kMaxMutationsToPrint,
514d89ec533Spatrick                                         CurrentDictionaryEntrySequence.size());
515d89ec533Spatrick     for (size_t i = 0; i < EntriesToPrint; i++) {
5163cab2bb3Spatrick       Printf("\"");
517d89ec533Spatrick       PrintASCII(CurrentDictionaryEntrySequence[i]->GetW(), "\"-");
5183cab2bb3Spatrick     }
5193cab2bb3Spatrick   }
5203cab2bb3Spatrick }
5213cab2bb3Spatrick 
MutationSequence()522d89ec533Spatrick std::string MutationDispatcher::MutationSequence() {
523d89ec533Spatrick   std::string MS;
524d89ec533Spatrick   for (auto M : CurrentMutatorSequence) {
525d89ec533Spatrick     MS += M.Name;
526d89ec533Spatrick     MS += "-";
527d89ec533Spatrick   }
528d89ec533Spatrick   return MS;
529d89ec533Spatrick }
530d89ec533Spatrick 
Mutate(uint8_t * Data,size_t Size,size_t MaxSize)5313cab2bb3Spatrick size_t MutationDispatcher::Mutate(uint8_t *Data, size_t Size, size_t MaxSize) {
5323cab2bb3Spatrick   return MutateImpl(Data, Size, MaxSize, Mutators);
5333cab2bb3Spatrick }
5343cab2bb3Spatrick 
DefaultMutate(uint8_t * Data,size_t Size,size_t MaxSize)5353cab2bb3Spatrick size_t MutationDispatcher::DefaultMutate(uint8_t *Data, size_t Size,
5363cab2bb3Spatrick                                          size_t MaxSize) {
5373cab2bb3Spatrick   return MutateImpl(Data, Size, MaxSize, DefaultMutators);
5383cab2bb3Spatrick }
5393cab2bb3Spatrick 
5403cab2bb3Spatrick // Mutates Data in place, returns new size.
MutateImpl(uint8_t * Data,size_t Size,size_t MaxSize,std::vector<Mutator> & Mutators)5413cab2bb3Spatrick size_t MutationDispatcher::MutateImpl(uint8_t *Data, size_t Size,
5423cab2bb3Spatrick                                       size_t MaxSize,
543*810390e3Srobert                                       std::vector<Mutator> &Mutators) {
5443cab2bb3Spatrick   assert(MaxSize > 0);
5453cab2bb3Spatrick   // Some mutations may fail (e.g. can't insert more bytes if Size == MaxSize),
5463cab2bb3Spatrick   // in which case they will return 0.
5473cab2bb3Spatrick   // Try several times before returning un-mutated data.
5483cab2bb3Spatrick   for (int Iter = 0; Iter < 100; Iter++) {
5493cab2bb3Spatrick     auto M = Mutators[Rand(Mutators.size())];
5503cab2bb3Spatrick     size_t NewSize = (this->*(M.Fn))(Data, Size, MaxSize);
5513cab2bb3Spatrick     if (NewSize && NewSize <= MaxSize) {
5523cab2bb3Spatrick       if (Options.OnlyASCII)
5533cab2bb3Spatrick         ToASCII(Data, NewSize);
5543cab2bb3Spatrick       CurrentMutatorSequence.push_back(M);
5553cab2bb3Spatrick       return NewSize;
5563cab2bb3Spatrick     }
5573cab2bb3Spatrick   }
5583cab2bb3Spatrick   *Data = ' ';
5593cab2bb3Spatrick   return 1;   // Fallback, should not happen frequently.
5603cab2bb3Spatrick }
5613cab2bb3Spatrick 
5623cab2bb3Spatrick // Mask represents the set of Data bytes that are worth mutating.
MutateWithMask(uint8_t * Data,size_t Size,size_t MaxSize,const std::vector<uint8_t> & Mask)5633cab2bb3Spatrick size_t MutationDispatcher::MutateWithMask(uint8_t *Data, size_t Size,
5643cab2bb3Spatrick                                           size_t MaxSize,
565*810390e3Srobert                                           const std::vector<uint8_t> &Mask) {
5663cab2bb3Spatrick   size_t MaskedSize = std::min(Size, Mask.size());
5673cab2bb3Spatrick   // * Copy the worthy bytes into a temporary array T
5683cab2bb3Spatrick   // * Mutate T
5693cab2bb3Spatrick   // * Copy T back.
5703cab2bb3Spatrick   // This is totally unoptimized.
5713cab2bb3Spatrick   auto &T = MutateWithMaskTemp;
5723cab2bb3Spatrick   if (T.size() < Size)
5733cab2bb3Spatrick     T.resize(Size);
5743cab2bb3Spatrick   size_t OneBits = 0;
5753cab2bb3Spatrick   for (size_t I = 0; I < MaskedSize; I++)
5763cab2bb3Spatrick     if (Mask[I])
5773cab2bb3Spatrick       T[OneBits++] = Data[I];
5783cab2bb3Spatrick 
5793cab2bb3Spatrick   if (!OneBits) return 0;
5803cab2bb3Spatrick   assert(!T.empty());
5813cab2bb3Spatrick   size_t NewSize = Mutate(T.data(), OneBits, OneBits);
5823cab2bb3Spatrick   assert(NewSize <= OneBits);
5833cab2bb3Spatrick   (void)NewSize;
5843cab2bb3Spatrick   // Even if NewSize < OneBits we still use all OneBits bytes.
5853cab2bb3Spatrick   for (size_t I = 0, J = 0; I < MaskedSize; I++)
5863cab2bb3Spatrick     if (Mask[I])
5873cab2bb3Spatrick       Data[I] = T[J++];
5883cab2bb3Spatrick   return Size;
5893cab2bb3Spatrick }
5903cab2bb3Spatrick 
AddWordToManualDictionary(const Word & W)5913cab2bb3Spatrick void MutationDispatcher::AddWordToManualDictionary(const Word &W) {
5923cab2bb3Spatrick   ManualDictionary.push_back(
5933cab2bb3Spatrick       {W, std::numeric_limits<size_t>::max()});
5943cab2bb3Spatrick }
5953cab2bb3Spatrick 
5963cab2bb3Spatrick }  // namespace fuzzer
597