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