13cab2bb3Spatrick //===- FuzzerMutate.cpp - Mutate a test input -----------------------------===//
23cab2bb3Spatrick //
33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information.
53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63cab2bb3Spatrick //
73cab2bb3Spatrick //===----------------------------------------------------------------------===//
83cab2bb3Spatrick // Mutate a test input.
93cab2bb3Spatrick //===----------------------------------------------------------------------===//
103cab2bb3Spatrick
113cab2bb3Spatrick #include "FuzzerDefs.h"
123cab2bb3Spatrick #include "FuzzerExtFunctions.h"
133cab2bb3Spatrick #include "FuzzerIO.h"
143cab2bb3Spatrick #include "FuzzerMutate.h"
153cab2bb3Spatrick #include "FuzzerOptions.h"
163cab2bb3Spatrick #include "FuzzerTracePC.h"
173cab2bb3Spatrick
183cab2bb3Spatrick namespace fuzzer {
193cab2bb3Spatrick
203cab2bb3Spatrick const size_t Dictionary::kMaxDictSize;
21d89ec533Spatrick static const size_t kMaxMutationsToPrint = 10;
223cab2bb3Spatrick
PrintASCII(const Word & W,const char * PrintAfter)233cab2bb3Spatrick static void PrintASCII(const Word &W, const char *PrintAfter) {
243cab2bb3Spatrick PrintASCII(W.data(), W.size(), PrintAfter);
253cab2bb3Spatrick }
263cab2bb3Spatrick
MutationDispatcher(Random & Rand,const FuzzingOptions & Options)273cab2bb3Spatrick MutationDispatcher::MutationDispatcher(Random &Rand,
283cab2bb3Spatrick const FuzzingOptions &Options)
293cab2bb3Spatrick : Rand(Rand), Options(Options) {
303cab2bb3Spatrick DefaultMutators.insert(
313cab2bb3Spatrick DefaultMutators.begin(),
323cab2bb3Spatrick {
333cab2bb3Spatrick {&MutationDispatcher::Mutate_EraseBytes, "EraseBytes"},
343cab2bb3Spatrick {&MutationDispatcher::Mutate_InsertByte, "InsertByte"},
353cab2bb3Spatrick {&MutationDispatcher::Mutate_InsertRepeatedBytes,
363cab2bb3Spatrick "InsertRepeatedBytes"},
373cab2bb3Spatrick {&MutationDispatcher::Mutate_ChangeByte, "ChangeByte"},
383cab2bb3Spatrick {&MutationDispatcher::Mutate_ChangeBit, "ChangeBit"},
393cab2bb3Spatrick {&MutationDispatcher::Mutate_ShuffleBytes, "ShuffleBytes"},
403cab2bb3Spatrick {&MutationDispatcher::Mutate_ChangeASCIIInteger, "ChangeASCIIInt"},
413cab2bb3Spatrick {&MutationDispatcher::Mutate_ChangeBinaryInteger, "ChangeBinInt"},
423cab2bb3Spatrick {&MutationDispatcher::Mutate_CopyPart, "CopyPart"},
433cab2bb3Spatrick {&MutationDispatcher::Mutate_CrossOver, "CrossOver"},
443cab2bb3Spatrick {&MutationDispatcher::Mutate_AddWordFromManualDictionary,
453cab2bb3Spatrick "ManualDict"},
463cab2bb3Spatrick {&MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary,
473cab2bb3Spatrick "PersAutoDict"},
483cab2bb3Spatrick });
493cab2bb3Spatrick if(Options.UseCmp)
503cab2bb3Spatrick DefaultMutators.push_back(
513cab2bb3Spatrick {&MutationDispatcher::Mutate_AddWordFromTORC, "CMP"});
523cab2bb3Spatrick
533cab2bb3Spatrick if (EF->LLVMFuzzerCustomMutator)
543cab2bb3Spatrick Mutators.push_back({&MutationDispatcher::Mutate_Custom, "Custom"});
553cab2bb3Spatrick else
563cab2bb3Spatrick Mutators = DefaultMutators;
573cab2bb3Spatrick
583cab2bb3Spatrick if (EF->LLVMFuzzerCustomCrossOver)
593cab2bb3Spatrick Mutators.push_back(
603cab2bb3Spatrick {&MutationDispatcher::Mutate_CustomCrossOver, "CustomCrossOver"});
613cab2bb3Spatrick }
623cab2bb3Spatrick
RandCh(Random & Rand)633cab2bb3Spatrick static char RandCh(Random &Rand) {
64d89ec533Spatrick if (Rand.RandBool())
65d89ec533Spatrick return static_cast<char>(Rand(256));
663cab2bb3Spatrick const char Special[] = "!*'();:@&=+$,/?%#[]012Az-`~.\xff\x00";
673cab2bb3Spatrick return Special[Rand(sizeof(Special) - 1)];
683cab2bb3Spatrick }
693cab2bb3Spatrick
Mutate_Custom(uint8_t * Data,size_t Size,size_t MaxSize)703cab2bb3Spatrick size_t MutationDispatcher::Mutate_Custom(uint8_t *Data, size_t Size,
713cab2bb3Spatrick size_t MaxSize) {
72d89ec533Spatrick if (EF->__msan_unpoison)
73d89ec533Spatrick EF->__msan_unpoison(Data, Size);
74d89ec533Spatrick if (EF->__msan_unpoison_param)
75d89ec533Spatrick EF->__msan_unpoison_param(4);
76d89ec533Spatrick return EF->LLVMFuzzerCustomMutator(Data, Size, MaxSize,
77d89ec533Spatrick Rand.Rand<unsigned int>());
783cab2bb3Spatrick }
793cab2bb3Spatrick
Mutate_CustomCrossOver(uint8_t * Data,size_t Size,size_t MaxSize)803cab2bb3Spatrick size_t MutationDispatcher::Mutate_CustomCrossOver(uint8_t *Data, size_t Size,
813cab2bb3Spatrick size_t MaxSize) {
823cab2bb3Spatrick if (Size == 0)
833cab2bb3Spatrick return 0;
843cab2bb3Spatrick if (!CrossOverWith) return 0;
853cab2bb3Spatrick const Unit &Other = *CrossOverWith;
863cab2bb3Spatrick if (Other.empty())
873cab2bb3Spatrick return 0;
883cab2bb3Spatrick CustomCrossOverInPlaceHere.resize(MaxSize);
893cab2bb3Spatrick auto &U = CustomCrossOverInPlaceHere;
90d89ec533Spatrick
91d89ec533Spatrick if (EF->__msan_unpoison) {
92d89ec533Spatrick EF->__msan_unpoison(Data, Size);
93d89ec533Spatrick EF->__msan_unpoison(Other.data(), Other.size());
94d89ec533Spatrick EF->__msan_unpoison(U.data(), U.size());
95d89ec533Spatrick }
96d89ec533Spatrick if (EF->__msan_unpoison_param)
97d89ec533Spatrick EF->__msan_unpoison_param(7);
983cab2bb3Spatrick size_t NewSize = EF->LLVMFuzzerCustomCrossOver(
99d89ec533Spatrick Data, Size, Other.data(), Other.size(), U.data(), U.size(),
100d89ec533Spatrick Rand.Rand<unsigned int>());
101d89ec533Spatrick
1023cab2bb3Spatrick if (!NewSize)
1033cab2bb3Spatrick return 0;
1043cab2bb3Spatrick assert(NewSize <= MaxSize && "CustomCrossOver returned overisized unit");
1053cab2bb3Spatrick memcpy(Data, U.data(), NewSize);
1063cab2bb3Spatrick return NewSize;
1073cab2bb3Spatrick }
1083cab2bb3Spatrick
Mutate_ShuffleBytes(uint8_t * Data,size_t Size,size_t MaxSize)1093cab2bb3Spatrick size_t MutationDispatcher::Mutate_ShuffleBytes(uint8_t *Data, size_t Size,
1103cab2bb3Spatrick size_t MaxSize) {
1113cab2bb3Spatrick if (Size > MaxSize || Size == 0) return 0;
1123cab2bb3Spatrick size_t ShuffleAmount =
1133cab2bb3Spatrick Rand(std::min(Size, (size_t)8)) + 1; // [1,8] and <= Size.
1143cab2bb3Spatrick size_t ShuffleStart = Rand(Size - ShuffleAmount);
1153cab2bb3Spatrick assert(ShuffleStart + ShuffleAmount <= Size);
1163cab2bb3Spatrick std::shuffle(Data + ShuffleStart, Data + ShuffleStart + ShuffleAmount, Rand);
1173cab2bb3Spatrick return Size;
1183cab2bb3Spatrick }
1193cab2bb3Spatrick
Mutate_EraseBytes(uint8_t * Data,size_t Size,size_t MaxSize)1203cab2bb3Spatrick size_t MutationDispatcher::Mutate_EraseBytes(uint8_t *Data, size_t Size,
1213cab2bb3Spatrick size_t MaxSize) {
1223cab2bb3Spatrick if (Size <= 1) return 0;
1233cab2bb3Spatrick size_t N = Rand(Size / 2) + 1;
1243cab2bb3Spatrick assert(N < Size);
1253cab2bb3Spatrick size_t Idx = Rand(Size - N + 1);
1263cab2bb3Spatrick // Erase Data[Idx:Idx+N].
1273cab2bb3Spatrick memmove(Data + Idx, Data + Idx + N, Size - Idx - N);
1283cab2bb3Spatrick // Printf("Erase: %zd %zd => %zd; Idx %zd\n", N, Size, Size - N, Idx);
1293cab2bb3Spatrick return Size - N;
1303cab2bb3Spatrick }
1313cab2bb3Spatrick
Mutate_InsertByte(uint8_t * Data,size_t Size,size_t MaxSize)1323cab2bb3Spatrick size_t MutationDispatcher::Mutate_InsertByte(uint8_t *Data, size_t Size,
1333cab2bb3Spatrick size_t MaxSize) {
1343cab2bb3Spatrick if (Size >= MaxSize) return 0;
1353cab2bb3Spatrick size_t Idx = Rand(Size + 1);
1363cab2bb3Spatrick // Insert new value at Data[Idx].
1373cab2bb3Spatrick memmove(Data + Idx + 1, Data + Idx, Size - Idx);
1383cab2bb3Spatrick Data[Idx] = RandCh(Rand);
1393cab2bb3Spatrick return Size + 1;
1403cab2bb3Spatrick }
1413cab2bb3Spatrick
Mutate_InsertRepeatedBytes(uint8_t * Data,size_t Size,size_t MaxSize)1423cab2bb3Spatrick size_t MutationDispatcher::Mutate_InsertRepeatedBytes(uint8_t *Data,
1433cab2bb3Spatrick size_t Size,
1443cab2bb3Spatrick size_t MaxSize) {
1453cab2bb3Spatrick const size_t kMinBytesToInsert = 3;
1463cab2bb3Spatrick if (Size + kMinBytesToInsert >= MaxSize) return 0;
1473cab2bb3Spatrick size_t MaxBytesToInsert = std::min(MaxSize - Size, (size_t)128);
1483cab2bb3Spatrick size_t N = Rand(MaxBytesToInsert - kMinBytesToInsert + 1) + kMinBytesToInsert;
1493cab2bb3Spatrick assert(Size + N <= MaxSize && N);
1503cab2bb3Spatrick size_t Idx = Rand(Size + 1);
1513cab2bb3Spatrick // Insert new values at Data[Idx].
1523cab2bb3Spatrick memmove(Data + Idx + N, Data + Idx, Size - Idx);
1533cab2bb3Spatrick // Give preference to 0x00 and 0xff.
154d89ec533Spatrick uint8_t Byte = static_cast<uint8_t>(
155d89ec533Spatrick Rand.RandBool() ? Rand(256) : (Rand.RandBool() ? 0 : 255));
1563cab2bb3Spatrick for (size_t i = 0; i < N; i++)
1573cab2bb3Spatrick Data[Idx + i] = Byte;
1583cab2bb3Spatrick return Size + N;
1593cab2bb3Spatrick }
1603cab2bb3Spatrick
Mutate_ChangeByte(uint8_t * Data,size_t Size,size_t MaxSize)1613cab2bb3Spatrick size_t MutationDispatcher::Mutate_ChangeByte(uint8_t *Data, size_t Size,
1623cab2bb3Spatrick size_t MaxSize) {
1633cab2bb3Spatrick if (Size > MaxSize) return 0;
1643cab2bb3Spatrick size_t Idx = Rand(Size);
1653cab2bb3Spatrick Data[Idx] = RandCh(Rand);
1663cab2bb3Spatrick return Size;
1673cab2bb3Spatrick }
1683cab2bb3Spatrick
Mutate_ChangeBit(uint8_t * Data,size_t Size,size_t MaxSize)1693cab2bb3Spatrick size_t MutationDispatcher::Mutate_ChangeBit(uint8_t *Data, size_t Size,
1703cab2bb3Spatrick size_t MaxSize) {
1713cab2bb3Spatrick if (Size > MaxSize) return 0;
1723cab2bb3Spatrick size_t Idx = Rand(Size);
1733cab2bb3Spatrick Data[Idx] ^= 1 << Rand(8);
1743cab2bb3Spatrick return Size;
1753cab2bb3Spatrick }
1763cab2bb3Spatrick
Mutate_AddWordFromManualDictionary(uint8_t * Data,size_t Size,size_t MaxSize)1773cab2bb3Spatrick size_t MutationDispatcher::Mutate_AddWordFromManualDictionary(uint8_t *Data,
1783cab2bb3Spatrick size_t Size,
1793cab2bb3Spatrick size_t MaxSize) {
1803cab2bb3Spatrick return AddWordFromDictionary(ManualDictionary, Data, Size, MaxSize);
1813cab2bb3Spatrick }
1823cab2bb3Spatrick
ApplyDictionaryEntry(uint8_t * Data,size_t Size,size_t MaxSize,DictionaryEntry & DE)1833cab2bb3Spatrick size_t MutationDispatcher::ApplyDictionaryEntry(uint8_t *Data, size_t Size,
1843cab2bb3Spatrick size_t MaxSize,
1853cab2bb3Spatrick DictionaryEntry &DE) {
1863cab2bb3Spatrick const Word &W = DE.GetW();
1873cab2bb3Spatrick bool UsePositionHint = DE.HasPositionHint() &&
1883cab2bb3Spatrick DE.GetPositionHint() + W.size() < Size &&
1893cab2bb3Spatrick Rand.RandBool();
1903cab2bb3Spatrick if (Rand.RandBool()) { // Insert W.
1913cab2bb3Spatrick if (Size + W.size() > MaxSize) return 0;
1923cab2bb3Spatrick size_t Idx = UsePositionHint ? DE.GetPositionHint() : Rand(Size + 1);
1933cab2bb3Spatrick memmove(Data + Idx + W.size(), Data + Idx, Size - Idx);
1943cab2bb3Spatrick memcpy(Data + Idx, W.data(), W.size());
1953cab2bb3Spatrick Size += W.size();
1963cab2bb3Spatrick } else { // Overwrite some bytes with W.
1973cab2bb3Spatrick if (W.size() > Size) return 0;
198d89ec533Spatrick size_t Idx =
199d89ec533Spatrick UsePositionHint ? DE.GetPositionHint() : Rand(Size + 1 - W.size());
2003cab2bb3Spatrick memcpy(Data + Idx, W.data(), W.size());
2013cab2bb3Spatrick }
2023cab2bb3Spatrick return Size;
2033cab2bb3Spatrick }
2043cab2bb3Spatrick
2053cab2bb3Spatrick // Somewhere in the past we have observed a comparison instructions
2063cab2bb3Spatrick // with arguments Arg1 Arg2. This function tries to guess a dictionary
2073cab2bb3Spatrick // entry that will satisfy that comparison.
2083cab2bb3Spatrick // It first tries to find one of the arguments (possibly swapped) in the
2093cab2bb3Spatrick // input and if it succeeds it creates a DE with a position hint.
2103cab2bb3Spatrick // Otherwise it creates a DE with one of the arguments w/o a position hint.
MakeDictionaryEntryFromCMP(const void * Arg1,const void * Arg2,const void * Arg1Mutation,const void * Arg2Mutation,size_t ArgSize,const uint8_t * Data,size_t Size)2113cab2bb3Spatrick DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP(
2123cab2bb3Spatrick const void *Arg1, const void *Arg2,
2133cab2bb3Spatrick const void *Arg1Mutation, const void *Arg2Mutation,
2143cab2bb3Spatrick size_t ArgSize, const uint8_t *Data,
2153cab2bb3Spatrick size_t Size) {
2163cab2bb3Spatrick bool HandleFirst = Rand.RandBool();
2173cab2bb3Spatrick const void *ExistingBytes, *DesiredBytes;
2183cab2bb3Spatrick Word W;
2193cab2bb3Spatrick const uint8_t *End = Data + Size;
2203cab2bb3Spatrick for (int Arg = 0; Arg < 2; Arg++) {
2213cab2bb3Spatrick ExistingBytes = HandleFirst ? Arg1 : Arg2;
2223cab2bb3Spatrick DesiredBytes = HandleFirst ? Arg2Mutation : Arg1Mutation;
2233cab2bb3Spatrick HandleFirst = !HandleFirst;
2243cab2bb3Spatrick W.Set(reinterpret_cast<const uint8_t*>(DesiredBytes), ArgSize);
2253cab2bb3Spatrick const size_t kMaxNumPositions = 8;
2263cab2bb3Spatrick size_t Positions[kMaxNumPositions];
2273cab2bb3Spatrick size_t NumPositions = 0;
2283cab2bb3Spatrick for (const uint8_t *Cur = Data;
2293cab2bb3Spatrick Cur < End && NumPositions < kMaxNumPositions; Cur++) {
2303cab2bb3Spatrick Cur =
2313cab2bb3Spatrick (const uint8_t *)SearchMemory(Cur, End - Cur, ExistingBytes, ArgSize);
2323cab2bb3Spatrick if (!Cur) break;
2333cab2bb3Spatrick Positions[NumPositions++] = Cur - Data;
2343cab2bb3Spatrick }
2353cab2bb3Spatrick if (!NumPositions) continue;
2363cab2bb3Spatrick return DictionaryEntry(W, Positions[Rand(NumPositions)]);
2373cab2bb3Spatrick }
2383cab2bb3Spatrick DictionaryEntry DE(W);
2393cab2bb3Spatrick return DE;
2403cab2bb3Spatrick }
2413cab2bb3Spatrick
2423cab2bb3Spatrick
2433cab2bb3Spatrick template <class T>
MakeDictionaryEntryFromCMP(T Arg1,T Arg2,const uint8_t * Data,size_t Size)2443cab2bb3Spatrick DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP(
2453cab2bb3Spatrick T Arg1, T Arg2, const uint8_t *Data, size_t Size) {
2463cab2bb3Spatrick if (Rand.RandBool()) Arg1 = Bswap(Arg1);
2473cab2bb3Spatrick if (Rand.RandBool()) Arg2 = Bswap(Arg2);
248d89ec533Spatrick T Arg1Mutation = static_cast<T>(Arg1 + Rand(-1, 1));
249d89ec533Spatrick T Arg2Mutation = static_cast<T>(Arg2 + Rand(-1, 1));
2503cab2bb3Spatrick return MakeDictionaryEntryFromCMP(&Arg1, &Arg2, &Arg1Mutation, &Arg2Mutation,
2513cab2bb3Spatrick sizeof(Arg1), Data, Size);
2523cab2bb3Spatrick }
2533cab2bb3Spatrick
MakeDictionaryEntryFromCMP(const Word & Arg1,const Word & Arg2,const uint8_t * Data,size_t Size)2543cab2bb3Spatrick DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP(
2553cab2bb3Spatrick const Word &Arg1, const Word &Arg2, const uint8_t *Data, size_t Size) {
2563cab2bb3Spatrick return MakeDictionaryEntryFromCMP(Arg1.data(), Arg2.data(), Arg1.data(),
2573cab2bb3Spatrick Arg2.data(), Arg1.size(), Data, Size);
2583cab2bb3Spatrick }
2593cab2bb3Spatrick
Mutate_AddWordFromTORC(uint8_t * Data,size_t Size,size_t MaxSize)2603cab2bb3Spatrick size_t MutationDispatcher::Mutate_AddWordFromTORC(
2613cab2bb3Spatrick uint8_t *Data, size_t Size, size_t MaxSize) {
2623cab2bb3Spatrick Word W;
2633cab2bb3Spatrick DictionaryEntry DE;
2643cab2bb3Spatrick switch (Rand(4)) {
2653cab2bb3Spatrick case 0: {
266d89ec533Spatrick auto X = TPC.TORC8.Get(Rand.Rand<size_t>());
2673cab2bb3Spatrick DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size);
2683cab2bb3Spatrick } break;
2693cab2bb3Spatrick case 1: {
270d89ec533Spatrick auto X = TPC.TORC4.Get(Rand.Rand<size_t>());
2713cab2bb3Spatrick if ((X.A >> 16) == 0 && (X.B >> 16) == 0 && Rand.RandBool())
2723cab2bb3Spatrick DE = MakeDictionaryEntryFromCMP((uint16_t)X.A, (uint16_t)X.B, Data, Size);
2733cab2bb3Spatrick else
2743cab2bb3Spatrick DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size);
2753cab2bb3Spatrick } break;
2763cab2bb3Spatrick case 2: {
277d89ec533Spatrick auto X = TPC.TORCW.Get(Rand.Rand<size_t>());
2783cab2bb3Spatrick DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size);
2793cab2bb3Spatrick } break;
2803cab2bb3Spatrick case 3: if (Options.UseMemmem) {
281d89ec533Spatrick auto X = TPC.MMT.Get(Rand.Rand<size_t>());
2823cab2bb3Spatrick DE = DictionaryEntry(X);
2833cab2bb3Spatrick } break;
2843cab2bb3Spatrick default:
2853cab2bb3Spatrick assert(0);
2863cab2bb3Spatrick }
2873cab2bb3Spatrick if (!DE.GetW().size()) return 0;
2883cab2bb3Spatrick Size = ApplyDictionaryEntry(Data, Size, MaxSize, DE);
2893cab2bb3Spatrick if (!Size) return 0;
2903cab2bb3Spatrick DictionaryEntry &DERef =
2913cab2bb3Spatrick CmpDictionaryEntriesDeque[CmpDictionaryEntriesDequeIdx++ %
2923cab2bb3Spatrick kCmpDictionaryEntriesDequeSize];
2933cab2bb3Spatrick DERef = DE;
2943cab2bb3Spatrick CurrentDictionaryEntrySequence.push_back(&DERef);
2953cab2bb3Spatrick return Size;
2963cab2bb3Spatrick }
2973cab2bb3Spatrick
Mutate_AddWordFromPersistentAutoDictionary(uint8_t * Data,size_t Size,size_t MaxSize)2983cab2bb3Spatrick size_t MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary(
2993cab2bb3Spatrick uint8_t *Data, size_t Size, size_t MaxSize) {
3003cab2bb3Spatrick return AddWordFromDictionary(PersistentAutoDictionary, Data, Size, MaxSize);
3013cab2bb3Spatrick }
3023cab2bb3Spatrick
AddWordFromDictionary(Dictionary & D,uint8_t * Data,size_t Size,size_t MaxSize)3033cab2bb3Spatrick size_t MutationDispatcher::AddWordFromDictionary(Dictionary &D, uint8_t *Data,
3043cab2bb3Spatrick size_t Size, size_t MaxSize) {
3053cab2bb3Spatrick if (Size > MaxSize) return 0;
3063cab2bb3Spatrick if (D.empty()) return 0;
3073cab2bb3Spatrick DictionaryEntry &DE = D[Rand(D.size())];
3083cab2bb3Spatrick Size = ApplyDictionaryEntry(Data, Size, MaxSize, DE);
3093cab2bb3Spatrick if (!Size) return 0;
3103cab2bb3Spatrick DE.IncUseCount();
3113cab2bb3Spatrick CurrentDictionaryEntrySequence.push_back(&DE);
3123cab2bb3Spatrick return Size;
3133cab2bb3Spatrick }
3143cab2bb3Spatrick
3153cab2bb3Spatrick // Overwrites part of To[0,ToSize) with a part of From[0,FromSize).
3163cab2bb3Spatrick // Returns ToSize.
CopyPartOf(const uint8_t * From,size_t FromSize,uint8_t * To,size_t ToSize)3173cab2bb3Spatrick size_t MutationDispatcher::CopyPartOf(const uint8_t *From, size_t FromSize,
3183cab2bb3Spatrick uint8_t *To, size_t ToSize) {
3193cab2bb3Spatrick // Copy From[FromBeg, FromBeg + CopySize) into To[ToBeg, ToBeg + CopySize).
3203cab2bb3Spatrick size_t ToBeg = Rand(ToSize);
3213cab2bb3Spatrick size_t CopySize = Rand(ToSize - ToBeg) + 1;
3223cab2bb3Spatrick assert(ToBeg + CopySize <= ToSize);
3233cab2bb3Spatrick CopySize = std::min(CopySize, FromSize);
3243cab2bb3Spatrick size_t FromBeg = Rand(FromSize - CopySize + 1);
3253cab2bb3Spatrick assert(FromBeg + CopySize <= FromSize);
3263cab2bb3Spatrick memmove(To + ToBeg, From + FromBeg, CopySize);
3273cab2bb3Spatrick return ToSize;
3283cab2bb3Spatrick }
3293cab2bb3Spatrick
3303cab2bb3Spatrick // Inserts part of From[0,ToSize) into To.
3313cab2bb3Spatrick // Returns new size of To on success or 0 on failure.
InsertPartOf(const uint8_t * From,size_t FromSize,uint8_t * To,size_t ToSize,size_t MaxToSize)3323cab2bb3Spatrick size_t MutationDispatcher::InsertPartOf(const uint8_t *From, size_t FromSize,
3333cab2bb3Spatrick uint8_t *To, size_t ToSize,
3343cab2bb3Spatrick size_t MaxToSize) {
3353cab2bb3Spatrick if (ToSize >= MaxToSize) return 0;
3363cab2bb3Spatrick size_t AvailableSpace = MaxToSize - ToSize;
3373cab2bb3Spatrick size_t MaxCopySize = std::min(AvailableSpace, FromSize);
3383cab2bb3Spatrick size_t CopySize = Rand(MaxCopySize) + 1;
3393cab2bb3Spatrick size_t FromBeg = Rand(FromSize - CopySize + 1);
3403cab2bb3Spatrick assert(FromBeg + CopySize <= FromSize);
3413cab2bb3Spatrick size_t ToInsertPos = Rand(ToSize + 1);
3423cab2bb3Spatrick assert(ToInsertPos + CopySize <= MaxToSize);
3433cab2bb3Spatrick size_t TailSize = ToSize - ToInsertPos;
3443cab2bb3Spatrick if (To == From) {
3453cab2bb3Spatrick MutateInPlaceHere.resize(MaxToSize);
3463cab2bb3Spatrick memcpy(MutateInPlaceHere.data(), From + FromBeg, CopySize);
3473cab2bb3Spatrick memmove(To + ToInsertPos + CopySize, To + ToInsertPos, TailSize);
3483cab2bb3Spatrick memmove(To + ToInsertPos, MutateInPlaceHere.data(), CopySize);
3493cab2bb3Spatrick } else {
3503cab2bb3Spatrick memmove(To + ToInsertPos + CopySize, To + ToInsertPos, TailSize);
3513cab2bb3Spatrick memmove(To + ToInsertPos, From + FromBeg, CopySize);
3523cab2bb3Spatrick }
3533cab2bb3Spatrick return ToSize + CopySize;
3543cab2bb3Spatrick }
3553cab2bb3Spatrick
Mutate_CopyPart(uint8_t * Data,size_t Size,size_t MaxSize)3563cab2bb3Spatrick size_t MutationDispatcher::Mutate_CopyPart(uint8_t *Data, size_t Size,
3573cab2bb3Spatrick size_t MaxSize) {
3583cab2bb3Spatrick if (Size > MaxSize || Size == 0) return 0;
3593cab2bb3Spatrick // If Size == MaxSize, `InsertPartOf(...)` will
3603cab2bb3Spatrick // fail so there's no point using it in this case.
3613cab2bb3Spatrick if (Size == MaxSize || Rand.RandBool())
3623cab2bb3Spatrick return CopyPartOf(Data, Size, Data, Size);
3633cab2bb3Spatrick else
3643cab2bb3Spatrick return InsertPartOf(Data, Size, Data, Size, MaxSize);
3653cab2bb3Spatrick }
3663cab2bb3Spatrick
Mutate_ChangeASCIIInteger(uint8_t * Data,size_t Size,size_t MaxSize)3673cab2bb3Spatrick size_t MutationDispatcher::Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size,
3683cab2bb3Spatrick size_t MaxSize) {
3693cab2bb3Spatrick if (Size > MaxSize) return 0;
3703cab2bb3Spatrick size_t B = Rand(Size);
3713cab2bb3Spatrick while (B < Size && !isdigit(Data[B])) B++;
3723cab2bb3Spatrick if (B == Size) return 0;
3733cab2bb3Spatrick size_t E = B;
3743cab2bb3Spatrick while (E < Size && isdigit(Data[E])) E++;
3753cab2bb3Spatrick assert(B < E);
3763cab2bb3Spatrick // now we have digits in [B, E).
3773cab2bb3Spatrick // strtol and friends don't accept non-zero-teminated data, parse it manually.
3783cab2bb3Spatrick uint64_t Val = Data[B] - '0';
3793cab2bb3Spatrick for (size_t i = B + 1; i < E; i++)
3803cab2bb3Spatrick Val = Val * 10 + Data[i] - '0';
3813cab2bb3Spatrick
3823cab2bb3Spatrick // Mutate the integer value.
3833cab2bb3Spatrick switch(Rand(5)) {
3843cab2bb3Spatrick case 0: Val++; break;
3853cab2bb3Spatrick case 1: Val--; break;
3863cab2bb3Spatrick case 2: Val /= 2; break;
3873cab2bb3Spatrick case 3: Val *= 2; break;
3883cab2bb3Spatrick case 4: Val = Rand(Val * Val); break;
3893cab2bb3Spatrick default: assert(0);
3903cab2bb3Spatrick }
3913cab2bb3Spatrick // Just replace the bytes with the new ones, don't bother moving bytes.
3923cab2bb3Spatrick for (size_t i = B; i < E; i++) {
3933cab2bb3Spatrick size_t Idx = E + B - i - 1;
3943cab2bb3Spatrick assert(Idx >= B && Idx < E);
3953cab2bb3Spatrick Data[Idx] = (Val % 10) + '0';
3963cab2bb3Spatrick Val /= 10;
3973cab2bb3Spatrick }
3983cab2bb3Spatrick return Size;
3993cab2bb3Spatrick }
4003cab2bb3Spatrick
4013cab2bb3Spatrick template<class T>
ChangeBinaryInteger(uint8_t * Data,size_t Size,Random & Rand)4023cab2bb3Spatrick size_t ChangeBinaryInteger(uint8_t *Data, size_t Size, Random &Rand) {
4033cab2bb3Spatrick if (Size < sizeof(T)) return 0;
4043cab2bb3Spatrick size_t Off = Rand(Size - sizeof(T) + 1);
4053cab2bb3Spatrick assert(Off + sizeof(T) <= Size);
4063cab2bb3Spatrick T Val;
4073cab2bb3Spatrick if (Off < 64 && !Rand(4)) {
408d89ec533Spatrick Val = static_cast<T>(Size);
4093cab2bb3Spatrick if (Rand.RandBool())
4103cab2bb3Spatrick Val = Bswap(Val);
4113cab2bb3Spatrick } else {
4123cab2bb3Spatrick memcpy(&Val, Data + Off, sizeof(Val));
413d89ec533Spatrick T Add = static_cast<T>(Rand(21));
4143cab2bb3Spatrick Add -= 10;
4153cab2bb3Spatrick if (Rand.RandBool())
4163cab2bb3Spatrick Val = Bswap(T(Bswap(Val) + Add)); // Add assuming different endiannes.
4173cab2bb3Spatrick else
4183cab2bb3Spatrick Val = Val + Add; // Add assuming current endiannes.
4193cab2bb3Spatrick if (Add == 0 || Rand.RandBool()) // Maybe negate.
4203cab2bb3Spatrick Val = -Val;
4213cab2bb3Spatrick }
4223cab2bb3Spatrick memcpy(Data + Off, &Val, sizeof(Val));
4233cab2bb3Spatrick return Size;
4243cab2bb3Spatrick }
4253cab2bb3Spatrick
Mutate_ChangeBinaryInteger(uint8_t * Data,size_t Size,size_t MaxSize)4263cab2bb3Spatrick size_t MutationDispatcher::Mutate_ChangeBinaryInteger(uint8_t *Data,
4273cab2bb3Spatrick size_t Size,
4283cab2bb3Spatrick size_t MaxSize) {
4293cab2bb3Spatrick if (Size > MaxSize) return 0;
4303cab2bb3Spatrick switch (Rand(4)) {
4313cab2bb3Spatrick case 3: return ChangeBinaryInteger<uint64_t>(Data, Size, Rand);
4323cab2bb3Spatrick case 2: return ChangeBinaryInteger<uint32_t>(Data, Size, Rand);
4333cab2bb3Spatrick case 1: return ChangeBinaryInteger<uint16_t>(Data, Size, Rand);
4343cab2bb3Spatrick case 0: return ChangeBinaryInteger<uint8_t>(Data, Size, Rand);
4353cab2bb3Spatrick default: assert(0);
4363cab2bb3Spatrick }
4373cab2bb3Spatrick return 0;
4383cab2bb3Spatrick }
4393cab2bb3Spatrick
Mutate_CrossOver(uint8_t * Data,size_t Size,size_t MaxSize)4403cab2bb3Spatrick size_t MutationDispatcher::Mutate_CrossOver(uint8_t *Data, size_t Size,
4413cab2bb3Spatrick size_t MaxSize) {
4423cab2bb3Spatrick if (Size > MaxSize) return 0;
4433cab2bb3Spatrick if (Size == 0) return 0;
4443cab2bb3Spatrick if (!CrossOverWith) return 0;
4453cab2bb3Spatrick const Unit &O = *CrossOverWith;
4463cab2bb3Spatrick if (O.empty()) return 0;
4473cab2bb3Spatrick size_t NewSize = 0;
4483cab2bb3Spatrick switch(Rand(3)) {
4493cab2bb3Spatrick case 0:
450d89ec533Spatrick MutateInPlaceHere.resize(MaxSize);
451d89ec533Spatrick NewSize = CrossOver(Data, Size, O.data(), O.size(),
452d89ec533Spatrick MutateInPlaceHere.data(), MaxSize);
453d89ec533Spatrick memcpy(Data, MutateInPlaceHere.data(), NewSize);
4543cab2bb3Spatrick break;
4553cab2bb3Spatrick case 1:
456d89ec533Spatrick NewSize = InsertPartOf(O.data(), O.size(), Data, Size, MaxSize);
4573cab2bb3Spatrick if (!NewSize)
458d89ec533Spatrick NewSize = CopyPartOf(O.data(), O.size(), Data, Size);
4593cab2bb3Spatrick break;
4603cab2bb3Spatrick case 2:
461d89ec533Spatrick NewSize = CopyPartOf(O.data(), O.size(), Data, Size);
4623cab2bb3Spatrick break;
4633cab2bb3Spatrick default: assert(0);
4643cab2bb3Spatrick }
4653cab2bb3Spatrick assert(NewSize > 0 && "CrossOver returned empty unit");
4663cab2bb3Spatrick assert(NewSize <= MaxSize && "CrossOver returned overisized unit");
4673cab2bb3Spatrick return NewSize;
4683cab2bb3Spatrick }
4693cab2bb3Spatrick
StartMutationSequence()4703cab2bb3Spatrick void MutationDispatcher::StartMutationSequence() {
4713cab2bb3Spatrick CurrentMutatorSequence.clear();
4723cab2bb3Spatrick CurrentDictionaryEntrySequence.clear();
4733cab2bb3Spatrick }
4743cab2bb3Spatrick
4753cab2bb3Spatrick // Copy successful dictionary entries to PersistentAutoDictionary.
RecordSuccessfulMutationSequence()4763cab2bb3Spatrick void MutationDispatcher::RecordSuccessfulMutationSequence() {
4773cab2bb3Spatrick for (auto DE : CurrentDictionaryEntrySequence) {
4783cab2bb3Spatrick // PersistentAutoDictionary.AddWithSuccessCountOne(DE);
4793cab2bb3Spatrick DE->IncSuccessCount();
4803cab2bb3Spatrick assert(DE->GetW().size());
4813cab2bb3Spatrick // Linear search is fine here as this happens seldom.
4823cab2bb3Spatrick if (!PersistentAutoDictionary.ContainsWord(DE->GetW()))
483d89ec533Spatrick PersistentAutoDictionary.push_back(*DE);
4843cab2bb3Spatrick }
4853cab2bb3Spatrick }
4863cab2bb3Spatrick
PrintRecommendedDictionary()4873cab2bb3Spatrick void MutationDispatcher::PrintRecommendedDictionary() {
488*810390e3Srobert std::vector<DictionaryEntry> V;
4893cab2bb3Spatrick for (auto &DE : PersistentAutoDictionary)
4903cab2bb3Spatrick if (!ManualDictionary.ContainsWord(DE.GetW()))
4913cab2bb3Spatrick V.push_back(DE);
4923cab2bb3Spatrick if (V.empty()) return;
4933cab2bb3Spatrick Printf("###### Recommended dictionary. ######\n");
4943cab2bb3Spatrick for (auto &DE: V) {
4953cab2bb3Spatrick assert(DE.GetW().size());
4963cab2bb3Spatrick Printf("\"");
4973cab2bb3Spatrick PrintASCII(DE.GetW(), "\"");
4983cab2bb3Spatrick Printf(" # Uses: %zd\n", DE.GetUseCount());
4993cab2bb3Spatrick }
5003cab2bb3Spatrick Printf("###### End of recommended dictionary. ######\n");
5013cab2bb3Spatrick }
5023cab2bb3Spatrick
PrintMutationSequence(bool Verbose)503d89ec533Spatrick void MutationDispatcher::PrintMutationSequence(bool Verbose) {
5043cab2bb3Spatrick Printf("MS: %zd ", CurrentMutatorSequence.size());
505d89ec533Spatrick size_t EntriesToPrint =
506d89ec533Spatrick Verbose ? CurrentMutatorSequence.size()
507d89ec533Spatrick : std::min(kMaxMutationsToPrint, CurrentMutatorSequence.size());
508d89ec533Spatrick for (size_t i = 0; i < EntriesToPrint; i++)
509d89ec533Spatrick Printf("%s-", CurrentMutatorSequence[i].Name);
5103cab2bb3Spatrick if (!CurrentDictionaryEntrySequence.empty()) {
5113cab2bb3Spatrick Printf(" DE: ");
512d89ec533Spatrick EntriesToPrint = Verbose ? CurrentDictionaryEntrySequence.size()
513d89ec533Spatrick : std::min(kMaxMutationsToPrint,
514d89ec533Spatrick CurrentDictionaryEntrySequence.size());
515d89ec533Spatrick for (size_t i = 0; i < EntriesToPrint; i++) {
5163cab2bb3Spatrick Printf("\"");
517d89ec533Spatrick PrintASCII(CurrentDictionaryEntrySequence[i]->GetW(), "\"-");
5183cab2bb3Spatrick }
5193cab2bb3Spatrick }
5203cab2bb3Spatrick }
5213cab2bb3Spatrick
MutationSequence()522d89ec533Spatrick std::string MutationDispatcher::MutationSequence() {
523d89ec533Spatrick std::string MS;
524d89ec533Spatrick for (auto M : CurrentMutatorSequence) {
525d89ec533Spatrick MS += M.Name;
526d89ec533Spatrick MS += "-";
527d89ec533Spatrick }
528d89ec533Spatrick return MS;
529d89ec533Spatrick }
530d89ec533Spatrick
Mutate(uint8_t * Data,size_t Size,size_t MaxSize)5313cab2bb3Spatrick size_t MutationDispatcher::Mutate(uint8_t *Data, size_t Size, size_t MaxSize) {
5323cab2bb3Spatrick return MutateImpl(Data, Size, MaxSize, Mutators);
5333cab2bb3Spatrick }
5343cab2bb3Spatrick
DefaultMutate(uint8_t * Data,size_t Size,size_t MaxSize)5353cab2bb3Spatrick size_t MutationDispatcher::DefaultMutate(uint8_t *Data, size_t Size,
5363cab2bb3Spatrick size_t MaxSize) {
5373cab2bb3Spatrick return MutateImpl(Data, Size, MaxSize, DefaultMutators);
5383cab2bb3Spatrick }
5393cab2bb3Spatrick
5403cab2bb3Spatrick // Mutates Data in place, returns new size.
MutateImpl(uint8_t * Data,size_t Size,size_t MaxSize,std::vector<Mutator> & Mutators)5413cab2bb3Spatrick size_t MutationDispatcher::MutateImpl(uint8_t *Data, size_t Size,
5423cab2bb3Spatrick size_t MaxSize,
543*810390e3Srobert std::vector<Mutator> &Mutators) {
5443cab2bb3Spatrick assert(MaxSize > 0);
5453cab2bb3Spatrick // Some mutations may fail (e.g. can't insert more bytes if Size == MaxSize),
5463cab2bb3Spatrick // in which case they will return 0.
5473cab2bb3Spatrick // Try several times before returning un-mutated data.
5483cab2bb3Spatrick for (int Iter = 0; Iter < 100; Iter++) {
5493cab2bb3Spatrick auto M = Mutators[Rand(Mutators.size())];
5503cab2bb3Spatrick size_t NewSize = (this->*(M.Fn))(Data, Size, MaxSize);
5513cab2bb3Spatrick if (NewSize && NewSize <= MaxSize) {
5523cab2bb3Spatrick if (Options.OnlyASCII)
5533cab2bb3Spatrick ToASCII(Data, NewSize);
5543cab2bb3Spatrick CurrentMutatorSequence.push_back(M);
5553cab2bb3Spatrick return NewSize;
5563cab2bb3Spatrick }
5573cab2bb3Spatrick }
5583cab2bb3Spatrick *Data = ' ';
5593cab2bb3Spatrick return 1; // Fallback, should not happen frequently.
5603cab2bb3Spatrick }
5613cab2bb3Spatrick
5623cab2bb3Spatrick // Mask represents the set of Data bytes that are worth mutating.
MutateWithMask(uint8_t * Data,size_t Size,size_t MaxSize,const std::vector<uint8_t> & Mask)5633cab2bb3Spatrick size_t MutationDispatcher::MutateWithMask(uint8_t *Data, size_t Size,
5643cab2bb3Spatrick size_t MaxSize,
565*810390e3Srobert const std::vector<uint8_t> &Mask) {
5663cab2bb3Spatrick size_t MaskedSize = std::min(Size, Mask.size());
5673cab2bb3Spatrick // * Copy the worthy bytes into a temporary array T
5683cab2bb3Spatrick // * Mutate T
5693cab2bb3Spatrick // * Copy T back.
5703cab2bb3Spatrick // This is totally unoptimized.
5713cab2bb3Spatrick auto &T = MutateWithMaskTemp;
5723cab2bb3Spatrick if (T.size() < Size)
5733cab2bb3Spatrick T.resize(Size);
5743cab2bb3Spatrick size_t OneBits = 0;
5753cab2bb3Spatrick for (size_t I = 0; I < MaskedSize; I++)
5763cab2bb3Spatrick if (Mask[I])
5773cab2bb3Spatrick T[OneBits++] = Data[I];
5783cab2bb3Spatrick
5793cab2bb3Spatrick if (!OneBits) return 0;
5803cab2bb3Spatrick assert(!T.empty());
5813cab2bb3Spatrick size_t NewSize = Mutate(T.data(), OneBits, OneBits);
5823cab2bb3Spatrick assert(NewSize <= OneBits);
5833cab2bb3Spatrick (void)NewSize;
5843cab2bb3Spatrick // Even if NewSize < OneBits we still use all OneBits bytes.
5853cab2bb3Spatrick for (size_t I = 0, J = 0; I < MaskedSize; I++)
5863cab2bb3Spatrick if (Mask[I])
5873cab2bb3Spatrick Data[I] = T[J++];
5883cab2bb3Spatrick return Size;
5893cab2bb3Spatrick }
5903cab2bb3Spatrick
AddWordToManualDictionary(const Word & W)5913cab2bb3Spatrick void MutationDispatcher::AddWordToManualDictionary(const Word &W) {
5923cab2bb3Spatrick ManualDictionary.push_back(
5933cab2bb3Spatrick {W, std::numeric_limits<size_t>::max()});
5943cab2bb3Spatrick }
5953cab2bb3Spatrick
5963cab2bb3Spatrick } // namespace fuzzer
597