xref: /llvm-project/compiler-rt/lib/fuzzer/FuzzerMutate.h (revision 7c921753e0f5e95aadee8728ddbcb843a272b48a)
110ab2aceSGeorge Karpenkov //===- FuzzerMutate.h - Internal header for the Fuzzer ----------*- C++ -* ===//
210ab2aceSGeorge Karpenkov //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
610ab2aceSGeorge Karpenkov //
710ab2aceSGeorge Karpenkov //===----------------------------------------------------------------------===//
810ab2aceSGeorge Karpenkov // fuzzer::MutationDispatcher
910ab2aceSGeorge Karpenkov //===----------------------------------------------------------------------===//
1010ab2aceSGeorge Karpenkov 
1110ab2aceSGeorge Karpenkov #ifndef LLVM_FUZZER_MUTATE_H
1210ab2aceSGeorge Karpenkov #define LLVM_FUZZER_MUTATE_H
1310ab2aceSGeorge Karpenkov 
14c5d72517SMarco Vanotti #include "FuzzerDefs.h"
15c5d72517SMarco Vanotti #include "FuzzerDictionary.h"
1610ab2aceSGeorge Karpenkov #include "FuzzerOptions.h"
17c5d72517SMarco Vanotti #include "FuzzerRandom.h"
1810ab2aceSGeorge Karpenkov 
1910ab2aceSGeorge Karpenkov namespace fuzzer {
2010ab2aceSGeorge Karpenkov 
21c5d72517SMarco Vanotti class MutationDispatcher {
22c5d72517SMarco Vanotti public:
23c5d72517SMarco Vanotti   MutationDispatcher(Random &Rand, const FuzzingOptions &Options);
~MutationDispatcher()24c5d72517SMarco Vanotti   ~MutationDispatcher() {}
25c5d72517SMarco Vanotti   /// Indicate that we are about to start a new sequence of mutations.
26c5d72517SMarco Vanotti   void StartMutationSequence();
27c5d72517SMarco Vanotti   /// Print the current sequence of mutations. Only prints the full sequence
28c5d72517SMarco Vanotti   /// when Verbose is true.
29c5d72517SMarco Vanotti   void PrintMutationSequence(bool Verbose = true);
30c5d72517SMarco Vanotti   /// Return the current sequence of mutations.
31c5d72517SMarco Vanotti   std::string MutationSequence();
32c5d72517SMarco Vanotti   /// Indicate that the current sequence of mutations was successful.
33c5d72517SMarco Vanotti   void RecordSuccessfulMutationSequence();
34c5d72517SMarco Vanotti   /// Mutates data by invoking user-provided mutator.
35c5d72517SMarco Vanotti   size_t Mutate_Custom(uint8_t *Data, size_t Size, size_t MaxSize);
36c5d72517SMarco Vanotti   /// Mutates data by invoking user-provided crossover.
37c5d72517SMarco Vanotti   size_t Mutate_CustomCrossOver(uint8_t *Data, size_t Size, size_t MaxSize);
38c5d72517SMarco Vanotti   /// Mutates data by shuffling bytes.
39c5d72517SMarco Vanotti   size_t Mutate_ShuffleBytes(uint8_t *Data, size_t Size, size_t MaxSize);
40c5d72517SMarco Vanotti   /// Mutates data by erasing bytes.
41c5d72517SMarco Vanotti   size_t Mutate_EraseBytes(uint8_t *Data, size_t Size, size_t MaxSize);
42c5d72517SMarco Vanotti   /// Mutates data by inserting a byte.
43c5d72517SMarco Vanotti   size_t Mutate_InsertByte(uint8_t *Data, size_t Size, size_t MaxSize);
44c5d72517SMarco Vanotti   /// Mutates data by inserting several repeated bytes.
45c5d72517SMarco Vanotti   size_t Mutate_InsertRepeatedBytes(uint8_t *Data, size_t Size, size_t MaxSize);
46c5d72517SMarco Vanotti   /// Mutates data by changing one byte.
47c5d72517SMarco Vanotti   size_t Mutate_ChangeByte(uint8_t *Data, size_t Size, size_t MaxSize);
48c5d72517SMarco Vanotti   /// Mutates data by changing one bit.
49c5d72517SMarco Vanotti   size_t Mutate_ChangeBit(uint8_t *Data, size_t Size, size_t MaxSize);
50c5d72517SMarco Vanotti   /// Mutates data by copying/inserting a part of data into a different place.
51c5d72517SMarco Vanotti   size_t Mutate_CopyPart(uint8_t *Data, size_t Size, size_t MaxSize);
5210ab2aceSGeorge Karpenkov 
53c5d72517SMarco Vanotti   /// Mutates data by adding a word from the manual dictionary.
54c5d72517SMarco Vanotti   size_t Mutate_AddWordFromManualDictionary(uint8_t *Data, size_t Size,
55c5d72517SMarco Vanotti                                             size_t MaxSize);
5610ab2aceSGeorge Karpenkov 
57c5d72517SMarco Vanotti   /// Mutates data by adding a word from the TORC.
58c5d72517SMarco Vanotti   size_t Mutate_AddWordFromTORC(uint8_t *Data, size_t Size, size_t MaxSize);
5910ab2aceSGeorge Karpenkov 
60c5d72517SMarco Vanotti   /// Mutates data by adding a word from the persistent automatic dictionary.
61c5d72517SMarco Vanotti   size_t Mutate_AddWordFromPersistentAutoDictionary(uint8_t *Data, size_t Size,
62c5d72517SMarco Vanotti                                                     size_t MaxSize);
6310ab2aceSGeorge Karpenkov 
64c5d72517SMarco Vanotti   /// Tries to find an ASCII integer in Data, changes it to another ASCII int.
65c5d72517SMarco Vanotti   size_t Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size, size_t MaxSize);
66c5d72517SMarco Vanotti   /// Change a 1-, 2-, 4-, or 8-byte integer in interesting ways.
67c5d72517SMarco Vanotti   size_t Mutate_ChangeBinaryInteger(uint8_t *Data, size_t Size, size_t MaxSize);
68c5d72517SMarco Vanotti 
69c5d72517SMarco Vanotti   /// CrossOver Data with CrossOverWith.
70c5d72517SMarco Vanotti   size_t Mutate_CrossOver(uint8_t *Data, size_t Size, size_t MaxSize);
71c5d72517SMarco Vanotti 
72c5d72517SMarco Vanotti   /// Applies one of the configured mutations.
73c5d72517SMarco Vanotti   /// Returns the new size of data which could be up to MaxSize.
74c5d72517SMarco Vanotti   size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize);
75c5d72517SMarco Vanotti 
76c5d72517SMarco Vanotti   /// Applies one of the configured mutations to the bytes of Data
77c5d72517SMarco Vanotti   /// that have '1' in Mask.
78c5d72517SMarco Vanotti   /// Mask.size() should be >= Size.
79c5d72517SMarco Vanotti   size_t MutateWithMask(uint8_t *Data, size_t Size, size_t MaxSize,
80*7c921753SKostya Serebryany                         const std::vector<uint8_t> &Mask);
81c5d72517SMarco Vanotti 
82c5d72517SMarco Vanotti   /// Applies one of the default mutations. Provided as a service
83c5d72517SMarco Vanotti   /// to mutation authors.
84c5d72517SMarco Vanotti   size_t DefaultMutate(uint8_t *Data, size_t Size, size_t MaxSize);
85c5d72517SMarco Vanotti 
86c5d72517SMarco Vanotti   /// Creates a cross-over of two pieces of Data, returns its size.
87c5d72517SMarco Vanotti   size_t CrossOver(const uint8_t *Data1, size_t Size1, const uint8_t *Data2,
88c5d72517SMarco Vanotti                    size_t Size2, uint8_t *Out, size_t MaxOutSize);
89c5d72517SMarco Vanotti 
90c5d72517SMarco Vanotti   void AddWordToManualDictionary(const Word &W);
91c5d72517SMarco Vanotti 
92c5d72517SMarco Vanotti   void PrintRecommendedDictionary();
93c5d72517SMarco Vanotti 
SetCrossOverWith(const Unit * U)94c5d72517SMarco Vanotti   void SetCrossOverWith(const Unit *U) { CrossOverWith = U; }
95c5d72517SMarco Vanotti 
GetRand()96c5d72517SMarco Vanotti   Random &GetRand() { return Rand; }
97c5d72517SMarco Vanotti 
98c5d72517SMarco Vanotti  private:
99c5d72517SMarco Vanotti   struct Mutator {
100c5d72517SMarco Vanotti     size_t (MutationDispatcher::*Fn)(uint8_t *Data, size_t Size, size_t Max);
101c5d72517SMarco Vanotti     const char *Name;
102c5d72517SMarco Vanotti   };
103c5d72517SMarco Vanotti 
104c5d72517SMarco Vanotti   size_t AddWordFromDictionary(Dictionary &D, uint8_t *Data, size_t Size,
105c5d72517SMarco Vanotti                                size_t MaxSize);
106c5d72517SMarco Vanotti   size_t MutateImpl(uint8_t *Data, size_t Size, size_t MaxSize,
107*7c921753SKostya Serebryany                     std::vector<Mutator> &Mutators);
108c5d72517SMarco Vanotti 
109c5d72517SMarco Vanotti   size_t InsertPartOf(const uint8_t *From, size_t FromSize, uint8_t *To,
110c5d72517SMarco Vanotti                       size_t ToSize, size_t MaxToSize);
111c5d72517SMarco Vanotti   size_t CopyPartOf(const uint8_t *From, size_t FromSize, uint8_t *To,
112c5d72517SMarco Vanotti                     size_t ToSize);
113c5d72517SMarco Vanotti   size_t ApplyDictionaryEntry(uint8_t *Data, size_t Size, size_t MaxSize,
114c5d72517SMarco Vanotti                               DictionaryEntry &DE);
115c5d72517SMarco Vanotti 
116c5d72517SMarco Vanotti   template <class T>
117c5d72517SMarco Vanotti   DictionaryEntry MakeDictionaryEntryFromCMP(T Arg1, T Arg2,
118c5d72517SMarco Vanotti                                              const uint8_t *Data, size_t Size);
119c5d72517SMarco Vanotti   DictionaryEntry MakeDictionaryEntryFromCMP(const Word &Arg1, const Word &Arg2,
120c5d72517SMarco Vanotti                                              const uint8_t *Data, size_t Size);
121c5d72517SMarco Vanotti   DictionaryEntry MakeDictionaryEntryFromCMP(const void *Arg1, const void *Arg2,
122c5d72517SMarco Vanotti                                              const void *Arg1Mutation,
123c5d72517SMarco Vanotti                                              const void *Arg2Mutation,
124c5d72517SMarco Vanotti                                              size_t ArgSize,
125c5d72517SMarco Vanotti                                              const uint8_t *Data, size_t Size);
126c5d72517SMarco Vanotti 
127c5d72517SMarco Vanotti   Random &Rand;
128c5d72517SMarco Vanotti   const FuzzingOptions Options;
129c5d72517SMarco Vanotti 
130c5d72517SMarco Vanotti   // Dictionary provided by the user via -dict=DICT_FILE.
131c5d72517SMarco Vanotti   Dictionary ManualDictionary;
132c5d72517SMarco Vanotti   // Persistent dictionary modified by the fuzzer, consists of
133c5d72517SMarco Vanotti   // entries that led to successful discoveries in the past mutations.
134c5d72517SMarco Vanotti   Dictionary PersistentAutoDictionary;
135c5d72517SMarco Vanotti 
136*7c921753SKostya Serebryany   std::vector<DictionaryEntry *> CurrentDictionaryEntrySequence;
137c5d72517SMarco Vanotti 
138c5d72517SMarco Vanotti   static const size_t kCmpDictionaryEntriesDequeSize = 16;
139c5d72517SMarco Vanotti   DictionaryEntry CmpDictionaryEntriesDeque[kCmpDictionaryEntriesDequeSize];
140c5d72517SMarco Vanotti   size_t CmpDictionaryEntriesDequeIdx = 0;
141c5d72517SMarco Vanotti 
142c5d72517SMarco Vanotti   const Unit *CrossOverWith = nullptr;
143*7c921753SKostya Serebryany   std::vector<uint8_t> MutateInPlaceHere;
144*7c921753SKostya Serebryany   std::vector<uint8_t> MutateWithMaskTemp;
145c5d72517SMarco Vanotti   // CustomCrossOver needs its own buffer as a custom implementation may call
146c5d72517SMarco Vanotti   // LLVMFuzzerMutate, which in turn may resize MutateInPlaceHere.
147*7c921753SKostya Serebryany   std::vector<uint8_t> CustomCrossOverInPlaceHere;
148c5d72517SMarco Vanotti 
149*7c921753SKostya Serebryany   std::vector<Mutator> Mutators;
150*7c921753SKostya Serebryany   std::vector<Mutator> DefaultMutators;
151*7c921753SKostya Serebryany   std::vector<Mutator> CurrentMutatorSequence;
152c5d72517SMarco Vanotti };
15310ab2aceSGeorge Karpenkov 
15410ab2aceSGeorge Karpenkov }  // namespace fuzzer
15510ab2aceSGeorge Karpenkov 
15610ab2aceSGeorge Karpenkov #endif  // LLVM_FUZZER_MUTATE_H
157