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