xref: /freebsd-src/contrib/llvm-project/compiler-rt/lib/fuzzer/FuzzerMutate.h (revision 349cc55c9796c4596a5b9904cd3281af295f878f)
10b57cec5SDimitry Andric //===- FuzzerMutate.h - Internal header for the Fuzzer ----------*- C++ -* ===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric // fuzzer::MutationDispatcher
90b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #ifndef LLVM_FUZZER_MUTATE_H
120b57cec5SDimitry Andric #define LLVM_FUZZER_MUTATE_H
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "FuzzerDefs.h"
150b57cec5SDimitry Andric #include "FuzzerDictionary.h"
160b57cec5SDimitry Andric #include "FuzzerOptions.h"
170b57cec5SDimitry Andric #include "FuzzerRandom.h"
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric namespace fuzzer {
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric class MutationDispatcher {
220b57cec5SDimitry Andric public:
230b57cec5SDimitry Andric   MutationDispatcher(Random &Rand, const FuzzingOptions &Options);
~MutationDispatcher()240b57cec5SDimitry Andric   ~MutationDispatcher() {}
250b57cec5SDimitry Andric   /// Indicate that we are about to start a new sequence of mutations.
260b57cec5SDimitry Andric   void StartMutationSequence();
27e8d8bef9SDimitry Andric   /// Print the current sequence of mutations. Only prints the full sequence
28e8d8bef9SDimitry Andric   /// when Verbose is true.
29e8d8bef9SDimitry Andric   void PrintMutationSequence(bool Verbose = true);
30e8d8bef9SDimitry Andric   /// Return the current sequence of mutations.
31e8d8bef9SDimitry Andric   std::string MutationSequence();
320b57cec5SDimitry Andric   /// Indicate that the current sequence of mutations was successful.
330b57cec5SDimitry Andric   void RecordSuccessfulMutationSequence();
340b57cec5SDimitry Andric   /// Mutates data by invoking user-provided mutator.
350b57cec5SDimitry Andric   size_t Mutate_Custom(uint8_t *Data, size_t Size, size_t MaxSize);
360b57cec5SDimitry Andric   /// Mutates data by invoking user-provided crossover.
370b57cec5SDimitry Andric   size_t Mutate_CustomCrossOver(uint8_t *Data, size_t Size, size_t MaxSize);
380b57cec5SDimitry Andric   /// Mutates data by shuffling bytes.
390b57cec5SDimitry Andric   size_t Mutate_ShuffleBytes(uint8_t *Data, size_t Size, size_t MaxSize);
400b57cec5SDimitry Andric   /// Mutates data by erasing bytes.
410b57cec5SDimitry Andric   size_t Mutate_EraseBytes(uint8_t *Data, size_t Size, size_t MaxSize);
420b57cec5SDimitry Andric   /// Mutates data by inserting a byte.
430b57cec5SDimitry Andric   size_t Mutate_InsertByte(uint8_t *Data, size_t Size, size_t MaxSize);
440b57cec5SDimitry Andric   /// Mutates data by inserting several repeated bytes.
450b57cec5SDimitry Andric   size_t Mutate_InsertRepeatedBytes(uint8_t *Data, size_t Size, size_t MaxSize);
46e8d8bef9SDimitry Andric   /// Mutates data by changing one byte.
470b57cec5SDimitry Andric   size_t Mutate_ChangeByte(uint8_t *Data, size_t Size, size_t MaxSize);
48e8d8bef9SDimitry Andric   /// Mutates data by changing one bit.
490b57cec5SDimitry Andric   size_t Mutate_ChangeBit(uint8_t *Data, size_t Size, size_t MaxSize);
500b57cec5SDimitry Andric   /// Mutates data by copying/inserting a part of data into a different place.
510b57cec5SDimitry Andric   size_t Mutate_CopyPart(uint8_t *Data, size_t Size, size_t MaxSize);
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric   /// Mutates data by adding a word from the manual dictionary.
540b57cec5SDimitry Andric   size_t Mutate_AddWordFromManualDictionary(uint8_t *Data, size_t Size,
550b57cec5SDimitry Andric                                             size_t MaxSize);
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric   /// Mutates data by adding a word from the TORC.
580b57cec5SDimitry Andric   size_t Mutate_AddWordFromTORC(uint8_t *Data, size_t Size, size_t MaxSize);
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric   /// Mutates data by adding a word from the persistent automatic dictionary.
610b57cec5SDimitry Andric   size_t Mutate_AddWordFromPersistentAutoDictionary(uint8_t *Data, size_t Size,
620b57cec5SDimitry Andric                                                     size_t MaxSize);
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric   /// Tries to find an ASCII integer in Data, changes it to another ASCII int.
650b57cec5SDimitry Andric   size_t Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size, size_t MaxSize);
660b57cec5SDimitry Andric   /// Change a 1-, 2-, 4-, or 8-byte integer in interesting ways.
670b57cec5SDimitry Andric   size_t Mutate_ChangeBinaryInteger(uint8_t *Data, size_t Size, size_t MaxSize);
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric   /// CrossOver Data with CrossOverWith.
700b57cec5SDimitry Andric   size_t Mutate_CrossOver(uint8_t *Data, size_t Size, size_t MaxSize);
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric   /// Applies one of the configured mutations.
730b57cec5SDimitry Andric   /// Returns the new size of data which could be up to MaxSize.
740b57cec5SDimitry Andric   size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize);
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric   /// Applies one of the configured mutations to the bytes of Data
770b57cec5SDimitry Andric   /// that have '1' in Mask.
780b57cec5SDimitry Andric   /// Mask.size() should be >= Size.
790b57cec5SDimitry Andric   size_t MutateWithMask(uint8_t *Data, size_t Size, size_t MaxSize,
80*349cc55cSDimitry Andric                         const std::vector<uint8_t> &Mask);
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric   /// Applies one of the default mutations. Provided as a service
830b57cec5SDimitry Andric   /// to mutation authors.
840b57cec5SDimitry Andric   size_t DefaultMutate(uint8_t *Data, size_t Size, size_t MaxSize);
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric   /// Creates a cross-over of two pieces of Data, returns its size.
870b57cec5SDimitry Andric   size_t CrossOver(const uint8_t *Data1, size_t Size1, const uint8_t *Data2,
880b57cec5SDimitry Andric                    size_t Size2, uint8_t *Out, size_t MaxOutSize);
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric   void AddWordToManualDictionary(const Word &W);
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric   void PrintRecommendedDictionary();
930b57cec5SDimitry Andric 
SetCrossOverWith(const Unit * U)940b57cec5SDimitry Andric   void SetCrossOverWith(const Unit *U) { CrossOverWith = U; }
950b57cec5SDimitry Andric 
GetRand()960b57cec5SDimitry Andric   Random &GetRand() { return Rand; }
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric  private:
990b57cec5SDimitry Andric   struct Mutator {
1000b57cec5SDimitry Andric     size_t (MutationDispatcher::*Fn)(uint8_t *Data, size_t Size, size_t Max);
1010b57cec5SDimitry Andric     const char *Name;
1020b57cec5SDimitry Andric   };
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric   size_t AddWordFromDictionary(Dictionary &D, uint8_t *Data, size_t Size,
1050b57cec5SDimitry Andric                                size_t MaxSize);
1060b57cec5SDimitry Andric   size_t MutateImpl(uint8_t *Data, size_t Size, size_t MaxSize,
107*349cc55cSDimitry Andric                     std::vector<Mutator> &Mutators);
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric   size_t InsertPartOf(const uint8_t *From, size_t FromSize, uint8_t *To,
1100b57cec5SDimitry Andric                       size_t ToSize, size_t MaxToSize);
1110b57cec5SDimitry Andric   size_t CopyPartOf(const uint8_t *From, size_t FromSize, uint8_t *To,
1120b57cec5SDimitry Andric                     size_t ToSize);
1130b57cec5SDimitry Andric   size_t ApplyDictionaryEntry(uint8_t *Data, size_t Size, size_t MaxSize,
1140b57cec5SDimitry Andric                               DictionaryEntry &DE);
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric   template <class T>
1170b57cec5SDimitry Andric   DictionaryEntry MakeDictionaryEntryFromCMP(T Arg1, T Arg2,
1180b57cec5SDimitry Andric                                              const uint8_t *Data, size_t Size);
1190b57cec5SDimitry Andric   DictionaryEntry MakeDictionaryEntryFromCMP(const Word &Arg1, const Word &Arg2,
1200b57cec5SDimitry Andric                                              const uint8_t *Data, size_t Size);
1210b57cec5SDimitry Andric   DictionaryEntry MakeDictionaryEntryFromCMP(const void *Arg1, const void *Arg2,
1220b57cec5SDimitry Andric                                              const void *Arg1Mutation,
1230b57cec5SDimitry Andric                                              const void *Arg2Mutation,
1240b57cec5SDimitry Andric                                              size_t ArgSize,
1250b57cec5SDimitry Andric                                              const uint8_t *Data, size_t Size);
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric   Random &Rand;
1280b57cec5SDimitry Andric   const FuzzingOptions Options;
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric   // Dictionary provided by the user via -dict=DICT_FILE.
1310b57cec5SDimitry Andric   Dictionary ManualDictionary;
1320b57cec5SDimitry Andric   // Persistent dictionary modified by the fuzzer, consists of
1330b57cec5SDimitry Andric   // entries that led to successful discoveries in the past mutations.
1340b57cec5SDimitry Andric   Dictionary PersistentAutoDictionary;
1350b57cec5SDimitry Andric 
136*349cc55cSDimitry Andric   std::vector<DictionaryEntry *> CurrentDictionaryEntrySequence;
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric   static const size_t kCmpDictionaryEntriesDequeSize = 16;
1390b57cec5SDimitry Andric   DictionaryEntry CmpDictionaryEntriesDeque[kCmpDictionaryEntriesDequeSize];
1400b57cec5SDimitry Andric   size_t CmpDictionaryEntriesDequeIdx = 0;
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric   const Unit *CrossOverWith = nullptr;
143*349cc55cSDimitry Andric   std::vector<uint8_t> MutateInPlaceHere;
144*349cc55cSDimitry Andric   std::vector<uint8_t> MutateWithMaskTemp;
1450b57cec5SDimitry Andric   // CustomCrossOver needs its own buffer as a custom implementation may call
1460b57cec5SDimitry Andric   // LLVMFuzzerMutate, which in turn may resize MutateInPlaceHere.
147*349cc55cSDimitry Andric   std::vector<uint8_t> CustomCrossOverInPlaceHere;
1480b57cec5SDimitry Andric 
149*349cc55cSDimitry Andric   std::vector<Mutator> Mutators;
150*349cc55cSDimitry Andric   std::vector<Mutator> DefaultMutators;
151*349cc55cSDimitry Andric   std::vector<Mutator> CurrentMutatorSequence;
1520b57cec5SDimitry Andric };
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric }  // namespace fuzzer
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric #endif  // LLVM_FUZZER_MUTATE_H
157