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