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