10b57cec5SDimitry Andric //===- FuzzerMutate.cpp - Mutate a test input -----------------------------===//
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 // Mutate a test input.
90b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
100b57cec5SDimitry Andric
110b57cec5SDimitry Andric #include "FuzzerDefs.h"
120b57cec5SDimitry Andric #include "FuzzerExtFunctions.h"
130b57cec5SDimitry Andric #include "FuzzerIO.h"
140b57cec5SDimitry Andric #include "FuzzerMutate.h"
150b57cec5SDimitry Andric #include "FuzzerOptions.h"
160b57cec5SDimitry Andric #include "FuzzerTracePC.h"
170b57cec5SDimitry Andric
180b57cec5SDimitry Andric namespace fuzzer {
190b57cec5SDimitry Andric
200b57cec5SDimitry Andric const size_t Dictionary::kMaxDictSize;
21e8d8bef9SDimitry Andric static const size_t kMaxMutationsToPrint = 10;
220b57cec5SDimitry Andric
PrintASCII(const Word & W,const char * PrintAfter)230b57cec5SDimitry Andric static void PrintASCII(const Word &W, const char *PrintAfter) {
240b57cec5SDimitry Andric PrintASCII(W.data(), W.size(), PrintAfter);
250b57cec5SDimitry Andric }
260b57cec5SDimitry Andric
MutationDispatcher(Random & Rand,const FuzzingOptions & Options)270b57cec5SDimitry Andric MutationDispatcher::MutationDispatcher(Random &Rand,
280b57cec5SDimitry Andric const FuzzingOptions &Options)
290b57cec5SDimitry Andric : Rand(Rand), Options(Options) {
300b57cec5SDimitry Andric DefaultMutators.insert(
310b57cec5SDimitry Andric DefaultMutators.begin(),
320b57cec5SDimitry Andric {
330b57cec5SDimitry Andric {&MutationDispatcher::Mutate_EraseBytes, "EraseBytes"},
340b57cec5SDimitry Andric {&MutationDispatcher::Mutate_InsertByte, "InsertByte"},
350b57cec5SDimitry Andric {&MutationDispatcher::Mutate_InsertRepeatedBytes,
360b57cec5SDimitry Andric "InsertRepeatedBytes"},
370b57cec5SDimitry Andric {&MutationDispatcher::Mutate_ChangeByte, "ChangeByte"},
380b57cec5SDimitry Andric {&MutationDispatcher::Mutate_ChangeBit, "ChangeBit"},
390b57cec5SDimitry Andric {&MutationDispatcher::Mutate_ShuffleBytes, "ShuffleBytes"},
400b57cec5SDimitry Andric {&MutationDispatcher::Mutate_ChangeASCIIInteger, "ChangeASCIIInt"},
410b57cec5SDimitry Andric {&MutationDispatcher::Mutate_ChangeBinaryInteger, "ChangeBinInt"},
420b57cec5SDimitry Andric {&MutationDispatcher::Mutate_CopyPart, "CopyPart"},
430b57cec5SDimitry Andric {&MutationDispatcher::Mutate_CrossOver, "CrossOver"},
440b57cec5SDimitry Andric {&MutationDispatcher::Mutate_AddWordFromManualDictionary,
450b57cec5SDimitry Andric "ManualDict"},
460b57cec5SDimitry Andric {&MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary,
470b57cec5SDimitry Andric "PersAutoDict"},
480b57cec5SDimitry Andric });
490b57cec5SDimitry Andric if(Options.UseCmp)
500b57cec5SDimitry Andric DefaultMutators.push_back(
510b57cec5SDimitry Andric {&MutationDispatcher::Mutate_AddWordFromTORC, "CMP"});
520b57cec5SDimitry Andric
530b57cec5SDimitry Andric if (EF->LLVMFuzzerCustomMutator)
540b57cec5SDimitry Andric Mutators.push_back({&MutationDispatcher::Mutate_Custom, "Custom"});
550b57cec5SDimitry Andric else
560b57cec5SDimitry Andric Mutators = DefaultMutators;
570b57cec5SDimitry Andric
580b57cec5SDimitry Andric if (EF->LLVMFuzzerCustomCrossOver)
590b57cec5SDimitry Andric Mutators.push_back(
600b57cec5SDimitry Andric {&MutationDispatcher::Mutate_CustomCrossOver, "CustomCrossOver"});
610b57cec5SDimitry Andric }
620b57cec5SDimitry Andric
RandCh(Random & Rand)630b57cec5SDimitry Andric static char RandCh(Random &Rand) {
64fe6060f1SDimitry Andric if (Rand.RandBool())
65fe6060f1SDimitry Andric return static_cast<char>(Rand(256));
660b57cec5SDimitry Andric const char Special[] = "!*'();:@&=+$,/?%#[]012Az-`~.\xff\x00";
670b57cec5SDimitry Andric return Special[Rand(sizeof(Special) - 1)];
680b57cec5SDimitry Andric }
690b57cec5SDimitry Andric
Mutate_Custom(uint8_t * Data,size_t Size,size_t MaxSize)700b57cec5SDimitry Andric size_t MutationDispatcher::Mutate_Custom(uint8_t *Data, size_t Size,
710b57cec5SDimitry Andric size_t MaxSize) {
72fe6060f1SDimitry Andric if (EF->__msan_unpoison)
73fe6060f1SDimitry Andric EF->__msan_unpoison(Data, Size);
74fe6060f1SDimitry Andric if (EF->__msan_unpoison_param)
75fe6060f1SDimitry Andric EF->__msan_unpoison_param(4);
76fe6060f1SDimitry Andric return EF->LLVMFuzzerCustomMutator(Data, Size, MaxSize,
77fe6060f1SDimitry Andric Rand.Rand<unsigned int>());
780b57cec5SDimitry Andric }
790b57cec5SDimitry Andric
Mutate_CustomCrossOver(uint8_t * Data,size_t Size,size_t MaxSize)800b57cec5SDimitry Andric size_t MutationDispatcher::Mutate_CustomCrossOver(uint8_t *Data, size_t Size,
810b57cec5SDimitry Andric size_t MaxSize) {
820b57cec5SDimitry Andric if (Size == 0)
830b57cec5SDimitry Andric return 0;
840b57cec5SDimitry Andric if (!CrossOverWith) return 0;
850b57cec5SDimitry Andric const Unit &Other = *CrossOverWith;
860b57cec5SDimitry Andric if (Other.empty())
870b57cec5SDimitry Andric return 0;
880b57cec5SDimitry Andric CustomCrossOverInPlaceHere.resize(MaxSize);
890b57cec5SDimitry Andric auto &U = CustomCrossOverInPlaceHere;
90fe6060f1SDimitry Andric
91fe6060f1SDimitry Andric if (EF->__msan_unpoison) {
92fe6060f1SDimitry Andric EF->__msan_unpoison(Data, Size);
93fe6060f1SDimitry Andric EF->__msan_unpoison(Other.data(), Other.size());
94fe6060f1SDimitry Andric EF->__msan_unpoison(U.data(), U.size());
95fe6060f1SDimitry Andric }
96fe6060f1SDimitry Andric if (EF->__msan_unpoison_param)
97fe6060f1SDimitry Andric EF->__msan_unpoison_param(7);
980b57cec5SDimitry Andric size_t NewSize = EF->LLVMFuzzerCustomCrossOver(
99fe6060f1SDimitry Andric Data, Size, Other.data(), Other.size(), U.data(), U.size(),
100fe6060f1SDimitry Andric Rand.Rand<unsigned int>());
101fe6060f1SDimitry Andric
1020b57cec5SDimitry Andric if (!NewSize)
1030b57cec5SDimitry Andric return 0;
1040b57cec5SDimitry Andric assert(NewSize <= MaxSize && "CustomCrossOver returned overisized unit");
1050b57cec5SDimitry Andric memcpy(Data, U.data(), NewSize);
1060b57cec5SDimitry Andric return NewSize;
1070b57cec5SDimitry Andric }
1080b57cec5SDimitry Andric
Mutate_ShuffleBytes(uint8_t * Data,size_t Size,size_t MaxSize)1090b57cec5SDimitry Andric size_t MutationDispatcher::Mutate_ShuffleBytes(uint8_t *Data, size_t Size,
1100b57cec5SDimitry Andric size_t MaxSize) {
1110b57cec5SDimitry Andric if (Size > MaxSize || Size == 0) return 0;
1120b57cec5SDimitry Andric size_t ShuffleAmount =
1130b57cec5SDimitry Andric Rand(std::min(Size, (size_t)8)) + 1; // [1,8] and <= Size.
1140b57cec5SDimitry Andric size_t ShuffleStart = Rand(Size - ShuffleAmount);
1150b57cec5SDimitry Andric assert(ShuffleStart + ShuffleAmount <= Size);
1160b57cec5SDimitry Andric std::shuffle(Data + ShuffleStart, Data + ShuffleStart + ShuffleAmount, Rand);
1170b57cec5SDimitry Andric return Size;
1180b57cec5SDimitry Andric }
1190b57cec5SDimitry Andric
Mutate_EraseBytes(uint8_t * Data,size_t Size,size_t MaxSize)1200b57cec5SDimitry Andric size_t MutationDispatcher::Mutate_EraseBytes(uint8_t *Data, size_t Size,
1210b57cec5SDimitry Andric size_t MaxSize) {
1220b57cec5SDimitry Andric if (Size <= 1) return 0;
1230b57cec5SDimitry Andric size_t N = Rand(Size / 2) + 1;
1240b57cec5SDimitry Andric assert(N < Size);
1250b57cec5SDimitry Andric size_t Idx = Rand(Size - N + 1);
1260b57cec5SDimitry Andric // Erase Data[Idx:Idx+N].
1270b57cec5SDimitry Andric memmove(Data + Idx, Data + Idx + N, Size - Idx - N);
1280b57cec5SDimitry Andric // Printf("Erase: %zd %zd => %zd; Idx %zd\n", N, Size, Size - N, Idx);
1290b57cec5SDimitry Andric return Size - N;
1300b57cec5SDimitry Andric }
1310b57cec5SDimitry Andric
Mutate_InsertByte(uint8_t * Data,size_t Size,size_t MaxSize)1320b57cec5SDimitry Andric size_t MutationDispatcher::Mutate_InsertByte(uint8_t *Data, size_t Size,
1330b57cec5SDimitry Andric size_t MaxSize) {
1340b57cec5SDimitry Andric if (Size >= MaxSize) return 0;
1350b57cec5SDimitry Andric size_t Idx = Rand(Size + 1);
1360b57cec5SDimitry Andric // Insert new value at Data[Idx].
1370b57cec5SDimitry Andric memmove(Data + Idx + 1, Data + Idx, Size - Idx);
1380b57cec5SDimitry Andric Data[Idx] = RandCh(Rand);
1390b57cec5SDimitry Andric return Size + 1;
1400b57cec5SDimitry Andric }
1410b57cec5SDimitry Andric
Mutate_InsertRepeatedBytes(uint8_t * Data,size_t Size,size_t MaxSize)1420b57cec5SDimitry Andric size_t MutationDispatcher::Mutate_InsertRepeatedBytes(uint8_t *Data,
1430b57cec5SDimitry Andric size_t Size,
1440b57cec5SDimitry Andric size_t MaxSize) {
1450b57cec5SDimitry Andric const size_t kMinBytesToInsert = 3;
1460b57cec5SDimitry Andric if (Size + kMinBytesToInsert >= MaxSize) return 0;
1470b57cec5SDimitry Andric size_t MaxBytesToInsert = std::min(MaxSize - Size, (size_t)128);
1480b57cec5SDimitry Andric size_t N = Rand(MaxBytesToInsert - kMinBytesToInsert + 1) + kMinBytesToInsert;
1490b57cec5SDimitry Andric assert(Size + N <= MaxSize && N);
1500b57cec5SDimitry Andric size_t Idx = Rand(Size + 1);
1510b57cec5SDimitry Andric // Insert new values at Data[Idx].
1520b57cec5SDimitry Andric memmove(Data + Idx + N, Data + Idx, Size - Idx);
1530b57cec5SDimitry Andric // Give preference to 0x00 and 0xff.
154fe6060f1SDimitry Andric uint8_t Byte = static_cast<uint8_t>(
155fe6060f1SDimitry Andric Rand.RandBool() ? Rand(256) : (Rand.RandBool() ? 0 : 255));
1560b57cec5SDimitry Andric for (size_t i = 0; i < N; i++)
1570b57cec5SDimitry Andric Data[Idx + i] = Byte;
1580b57cec5SDimitry Andric return Size + N;
1590b57cec5SDimitry Andric }
1600b57cec5SDimitry Andric
Mutate_ChangeByte(uint8_t * Data,size_t Size,size_t MaxSize)1610b57cec5SDimitry Andric size_t MutationDispatcher::Mutate_ChangeByte(uint8_t *Data, size_t Size,
1620b57cec5SDimitry Andric size_t MaxSize) {
1630b57cec5SDimitry Andric if (Size > MaxSize) return 0;
1640b57cec5SDimitry Andric size_t Idx = Rand(Size);
1650b57cec5SDimitry Andric Data[Idx] = RandCh(Rand);
1660b57cec5SDimitry Andric return Size;
1670b57cec5SDimitry Andric }
1680b57cec5SDimitry Andric
Mutate_ChangeBit(uint8_t * Data,size_t Size,size_t MaxSize)1690b57cec5SDimitry Andric size_t MutationDispatcher::Mutate_ChangeBit(uint8_t *Data, size_t Size,
1700b57cec5SDimitry Andric size_t MaxSize) {
1710b57cec5SDimitry Andric if (Size > MaxSize) return 0;
1720b57cec5SDimitry Andric size_t Idx = Rand(Size);
1730b57cec5SDimitry Andric Data[Idx] ^= 1 << Rand(8);
1740b57cec5SDimitry Andric return Size;
1750b57cec5SDimitry Andric }
1760b57cec5SDimitry Andric
Mutate_AddWordFromManualDictionary(uint8_t * Data,size_t Size,size_t MaxSize)1770b57cec5SDimitry Andric size_t MutationDispatcher::Mutate_AddWordFromManualDictionary(uint8_t *Data,
1780b57cec5SDimitry Andric size_t Size,
1790b57cec5SDimitry Andric size_t MaxSize) {
1800b57cec5SDimitry Andric return AddWordFromDictionary(ManualDictionary, Data, Size, MaxSize);
1810b57cec5SDimitry Andric }
1820b57cec5SDimitry Andric
ApplyDictionaryEntry(uint8_t * Data,size_t Size,size_t MaxSize,DictionaryEntry & DE)1830b57cec5SDimitry Andric size_t MutationDispatcher::ApplyDictionaryEntry(uint8_t *Data, size_t Size,
1840b57cec5SDimitry Andric size_t MaxSize,
1850b57cec5SDimitry Andric DictionaryEntry &DE) {
1860b57cec5SDimitry Andric const Word &W = DE.GetW();
1870b57cec5SDimitry Andric bool UsePositionHint = DE.HasPositionHint() &&
1880b57cec5SDimitry Andric DE.GetPositionHint() + W.size() < Size &&
1890b57cec5SDimitry Andric Rand.RandBool();
1900b57cec5SDimitry Andric if (Rand.RandBool()) { // Insert W.
1910b57cec5SDimitry Andric if (Size + W.size() > MaxSize) return 0;
1920b57cec5SDimitry Andric size_t Idx = UsePositionHint ? DE.GetPositionHint() : Rand(Size + 1);
1930b57cec5SDimitry Andric memmove(Data + Idx + W.size(), Data + Idx, Size - Idx);
1940b57cec5SDimitry Andric memcpy(Data + Idx, W.data(), W.size());
1950b57cec5SDimitry Andric Size += W.size();
1960b57cec5SDimitry Andric } else { // Overwrite some bytes with W.
1970b57cec5SDimitry Andric if (W.size() > Size) return 0;
198fe6060f1SDimitry Andric size_t Idx =
199fe6060f1SDimitry Andric UsePositionHint ? DE.GetPositionHint() : Rand(Size + 1 - W.size());
2000b57cec5SDimitry Andric memcpy(Data + Idx, W.data(), W.size());
2010b57cec5SDimitry Andric }
2020b57cec5SDimitry Andric return Size;
2030b57cec5SDimitry Andric }
2040b57cec5SDimitry Andric
2050b57cec5SDimitry Andric // Somewhere in the past we have observed a comparison instructions
2060b57cec5SDimitry Andric // with arguments Arg1 Arg2. This function tries to guess a dictionary
2070b57cec5SDimitry Andric // entry that will satisfy that comparison.
2080b57cec5SDimitry Andric // It first tries to find one of the arguments (possibly swapped) in the
2090b57cec5SDimitry Andric // input and if it succeeds it creates a DE with a position hint.
2100b57cec5SDimitry Andric // 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)2110b57cec5SDimitry Andric DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP(
2120b57cec5SDimitry Andric const void *Arg1, const void *Arg2,
2130b57cec5SDimitry Andric const void *Arg1Mutation, const void *Arg2Mutation,
2140b57cec5SDimitry Andric size_t ArgSize, const uint8_t *Data,
2150b57cec5SDimitry Andric size_t Size) {
2160b57cec5SDimitry Andric bool HandleFirst = Rand.RandBool();
2170b57cec5SDimitry Andric const void *ExistingBytes, *DesiredBytes;
2180b57cec5SDimitry Andric Word W;
2190b57cec5SDimitry Andric const uint8_t *End = Data + Size;
2200b57cec5SDimitry Andric for (int Arg = 0; Arg < 2; Arg++) {
2210b57cec5SDimitry Andric ExistingBytes = HandleFirst ? Arg1 : Arg2;
2220b57cec5SDimitry Andric DesiredBytes = HandleFirst ? Arg2Mutation : Arg1Mutation;
2230b57cec5SDimitry Andric HandleFirst = !HandleFirst;
2240b57cec5SDimitry Andric W.Set(reinterpret_cast<const uint8_t*>(DesiredBytes), ArgSize);
2250b57cec5SDimitry Andric const size_t kMaxNumPositions = 8;
2260b57cec5SDimitry Andric size_t Positions[kMaxNumPositions];
2270b57cec5SDimitry Andric size_t NumPositions = 0;
2280b57cec5SDimitry Andric for (const uint8_t *Cur = Data;
2290b57cec5SDimitry Andric Cur < End && NumPositions < kMaxNumPositions; Cur++) {
2300b57cec5SDimitry Andric Cur =
2310b57cec5SDimitry Andric (const uint8_t *)SearchMemory(Cur, End - Cur, ExistingBytes, ArgSize);
2320b57cec5SDimitry Andric if (!Cur) break;
2330b57cec5SDimitry Andric Positions[NumPositions++] = Cur - Data;
2340b57cec5SDimitry Andric }
2350b57cec5SDimitry Andric if (!NumPositions) continue;
2360b57cec5SDimitry Andric return DictionaryEntry(W, Positions[Rand(NumPositions)]);
2370b57cec5SDimitry Andric }
2380b57cec5SDimitry Andric DictionaryEntry DE(W);
2390b57cec5SDimitry Andric return DE;
2400b57cec5SDimitry Andric }
2410b57cec5SDimitry Andric
2420b57cec5SDimitry Andric
2430b57cec5SDimitry Andric template <class T>
MakeDictionaryEntryFromCMP(T Arg1,T Arg2,const uint8_t * Data,size_t Size)2440b57cec5SDimitry Andric DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP(
2450b57cec5SDimitry Andric T Arg1, T Arg2, const uint8_t *Data, size_t Size) {
2460b57cec5SDimitry Andric if (Rand.RandBool()) Arg1 = Bswap(Arg1);
2470b57cec5SDimitry Andric if (Rand.RandBool()) Arg2 = Bswap(Arg2);
248fe6060f1SDimitry Andric T Arg1Mutation = static_cast<T>(Arg1 + Rand(-1, 1));
249fe6060f1SDimitry Andric T Arg2Mutation = static_cast<T>(Arg2 + Rand(-1, 1));
2500b57cec5SDimitry Andric return MakeDictionaryEntryFromCMP(&Arg1, &Arg2, &Arg1Mutation, &Arg2Mutation,
2510b57cec5SDimitry Andric sizeof(Arg1), Data, Size);
2520b57cec5SDimitry Andric }
2530b57cec5SDimitry Andric
MakeDictionaryEntryFromCMP(const Word & Arg1,const Word & Arg2,const uint8_t * Data,size_t Size)2540b57cec5SDimitry Andric DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP(
2550b57cec5SDimitry Andric const Word &Arg1, const Word &Arg2, const uint8_t *Data, size_t Size) {
2560b57cec5SDimitry Andric return MakeDictionaryEntryFromCMP(Arg1.data(), Arg2.data(), Arg1.data(),
2570b57cec5SDimitry Andric Arg2.data(), Arg1.size(), Data, Size);
2580b57cec5SDimitry Andric }
2590b57cec5SDimitry Andric
Mutate_AddWordFromTORC(uint8_t * Data,size_t Size,size_t MaxSize)2600b57cec5SDimitry Andric size_t MutationDispatcher::Mutate_AddWordFromTORC(
2610b57cec5SDimitry Andric uint8_t *Data, size_t Size, size_t MaxSize) {
2620b57cec5SDimitry Andric Word W;
2630b57cec5SDimitry Andric DictionaryEntry DE;
2640b57cec5SDimitry Andric switch (Rand(4)) {
2650b57cec5SDimitry Andric case 0: {
266fe6060f1SDimitry Andric auto X = TPC.TORC8.Get(Rand.Rand<size_t>());
2670b57cec5SDimitry Andric DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size);
2680b57cec5SDimitry Andric } break;
2690b57cec5SDimitry Andric case 1: {
270fe6060f1SDimitry Andric auto X = TPC.TORC4.Get(Rand.Rand<size_t>());
2710b57cec5SDimitry Andric if ((X.A >> 16) == 0 && (X.B >> 16) == 0 && Rand.RandBool())
2720b57cec5SDimitry Andric DE = MakeDictionaryEntryFromCMP((uint16_t)X.A, (uint16_t)X.B, Data, Size);
2730b57cec5SDimitry Andric else
2740b57cec5SDimitry Andric DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size);
2750b57cec5SDimitry Andric } break;
2760b57cec5SDimitry Andric case 2: {
277fe6060f1SDimitry Andric auto X = TPC.TORCW.Get(Rand.Rand<size_t>());
2780b57cec5SDimitry Andric DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size);
2790b57cec5SDimitry Andric } break;
2800b57cec5SDimitry Andric case 3: if (Options.UseMemmem) {
281fe6060f1SDimitry Andric auto X = TPC.MMT.Get(Rand.Rand<size_t>());
2820b57cec5SDimitry Andric DE = DictionaryEntry(X);
2830b57cec5SDimitry Andric } break;
2840b57cec5SDimitry Andric default:
2850b57cec5SDimitry Andric assert(0);
2860b57cec5SDimitry Andric }
2870b57cec5SDimitry Andric if (!DE.GetW().size()) return 0;
2880b57cec5SDimitry Andric Size = ApplyDictionaryEntry(Data, Size, MaxSize, DE);
2890b57cec5SDimitry Andric if (!Size) return 0;
2900b57cec5SDimitry Andric DictionaryEntry &DERef =
2910b57cec5SDimitry Andric CmpDictionaryEntriesDeque[CmpDictionaryEntriesDequeIdx++ %
2920b57cec5SDimitry Andric kCmpDictionaryEntriesDequeSize];
2930b57cec5SDimitry Andric DERef = DE;
2940b57cec5SDimitry Andric CurrentDictionaryEntrySequence.push_back(&DERef);
2950b57cec5SDimitry Andric return Size;
2960b57cec5SDimitry Andric }
2970b57cec5SDimitry Andric
Mutate_AddWordFromPersistentAutoDictionary(uint8_t * Data,size_t Size,size_t MaxSize)2980b57cec5SDimitry Andric size_t MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary(
2990b57cec5SDimitry Andric uint8_t *Data, size_t Size, size_t MaxSize) {
3000b57cec5SDimitry Andric return AddWordFromDictionary(PersistentAutoDictionary, Data, Size, MaxSize);
3010b57cec5SDimitry Andric }
3020b57cec5SDimitry Andric
AddWordFromDictionary(Dictionary & D,uint8_t * Data,size_t Size,size_t MaxSize)3030b57cec5SDimitry Andric size_t MutationDispatcher::AddWordFromDictionary(Dictionary &D, uint8_t *Data,
3040b57cec5SDimitry Andric size_t Size, size_t MaxSize) {
3050b57cec5SDimitry Andric if (Size > MaxSize) return 0;
3060b57cec5SDimitry Andric if (D.empty()) return 0;
3070b57cec5SDimitry Andric DictionaryEntry &DE = D[Rand(D.size())];
3080b57cec5SDimitry Andric Size = ApplyDictionaryEntry(Data, Size, MaxSize, DE);
3090b57cec5SDimitry Andric if (!Size) return 0;
3100b57cec5SDimitry Andric DE.IncUseCount();
3110b57cec5SDimitry Andric CurrentDictionaryEntrySequence.push_back(&DE);
3120b57cec5SDimitry Andric return Size;
3130b57cec5SDimitry Andric }
3140b57cec5SDimitry Andric
3150b57cec5SDimitry Andric // Overwrites part of To[0,ToSize) with a part of From[0,FromSize).
3160b57cec5SDimitry Andric // Returns ToSize.
CopyPartOf(const uint8_t * From,size_t FromSize,uint8_t * To,size_t ToSize)3170b57cec5SDimitry Andric size_t MutationDispatcher::CopyPartOf(const uint8_t *From, size_t FromSize,
3180b57cec5SDimitry Andric uint8_t *To, size_t ToSize) {
3190b57cec5SDimitry Andric // Copy From[FromBeg, FromBeg + CopySize) into To[ToBeg, ToBeg + CopySize).
3200b57cec5SDimitry Andric size_t ToBeg = Rand(ToSize);
3210b57cec5SDimitry Andric size_t CopySize = Rand(ToSize - ToBeg) + 1;
3220b57cec5SDimitry Andric assert(ToBeg + CopySize <= ToSize);
3230b57cec5SDimitry Andric CopySize = std::min(CopySize, FromSize);
3240b57cec5SDimitry Andric size_t FromBeg = Rand(FromSize - CopySize + 1);
3250b57cec5SDimitry Andric assert(FromBeg + CopySize <= FromSize);
3260b57cec5SDimitry Andric memmove(To + ToBeg, From + FromBeg, CopySize);
3270b57cec5SDimitry Andric return ToSize;
3280b57cec5SDimitry Andric }
3290b57cec5SDimitry Andric
3300b57cec5SDimitry Andric // Inserts part of From[0,ToSize) into To.
3310b57cec5SDimitry Andric // 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)3320b57cec5SDimitry Andric size_t MutationDispatcher::InsertPartOf(const uint8_t *From, size_t FromSize,
3330b57cec5SDimitry Andric uint8_t *To, size_t ToSize,
3340b57cec5SDimitry Andric size_t MaxToSize) {
3350b57cec5SDimitry Andric if (ToSize >= MaxToSize) return 0;
3360b57cec5SDimitry Andric size_t AvailableSpace = MaxToSize - ToSize;
3370b57cec5SDimitry Andric size_t MaxCopySize = std::min(AvailableSpace, FromSize);
3380b57cec5SDimitry Andric size_t CopySize = Rand(MaxCopySize) + 1;
3390b57cec5SDimitry Andric size_t FromBeg = Rand(FromSize - CopySize + 1);
3400b57cec5SDimitry Andric assert(FromBeg + CopySize <= FromSize);
3410b57cec5SDimitry Andric size_t ToInsertPos = Rand(ToSize + 1);
3420b57cec5SDimitry Andric assert(ToInsertPos + CopySize <= MaxToSize);
3430b57cec5SDimitry Andric size_t TailSize = ToSize - ToInsertPos;
3440b57cec5SDimitry Andric if (To == From) {
3450b57cec5SDimitry Andric MutateInPlaceHere.resize(MaxToSize);
3460b57cec5SDimitry Andric memcpy(MutateInPlaceHere.data(), From + FromBeg, CopySize);
3470b57cec5SDimitry Andric memmove(To + ToInsertPos + CopySize, To + ToInsertPos, TailSize);
3480b57cec5SDimitry Andric memmove(To + ToInsertPos, MutateInPlaceHere.data(), CopySize);
3490b57cec5SDimitry Andric } else {
3500b57cec5SDimitry Andric memmove(To + ToInsertPos + CopySize, To + ToInsertPos, TailSize);
3510b57cec5SDimitry Andric memmove(To + ToInsertPos, From + FromBeg, CopySize);
3520b57cec5SDimitry Andric }
3530b57cec5SDimitry Andric return ToSize + CopySize;
3540b57cec5SDimitry Andric }
3550b57cec5SDimitry Andric
Mutate_CopyPart(uint8_t * Data,size_t Size,size_t MaxSize)3560b57cec5SDimitry Andric size_t MutationDispatcher::Mutate_CopyPart(uint8_t *Data, size_t Size,
3570b57cec5SDimitry Andric size_t MaxSize) {
3580b57cec5SDimitry Andric if (Size > MaxSize || Size == 0) return 0;
3590b57cec5SDimitry Andric // If Size == MaxSize, `InsertPartOf(...)` will
3600b57cec5SDimitry Andric // fail so there's no point using it in this case.
3610b57cec5SDimitry Andric if (Size == MaxSize || Rand.RandBool())
3620b57cec5SDimitry Andric return CopyPartOf(Data, Size, Data, Size);
3630b57cec5SDimitry Andric else
3640b57cec5SDimitry Andric return InsertPartOf(Data, Size, Data, Size, MaxSize);
3650b57cec5SDimitry Andric }
3660b57cec5SDimitry Andric
Mutate_ChangeASCIIInteger(uint8_t * Data,size_t Size,size_t MaxSize)3670b57cec5SDimitry Andric size_t MutationDispatcher::Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size,
3680b57cec5SDimitry Andric size_t MaxSize) {
3690b57cec5SDimitry Andric if (Size > MaxSize) return 0;
3700b57cec5SDimitry Andric size_t B = Rand(Size);
3710b57cec5SDimitry Andric while (B < Size && !isdigit(Data[B])) B++;
3720b57cec5SDimitry Andric if (B == Size) return 0;
3730b57cec5SDimitry Andric size_t E = B;
3740b57cec5SDimitry Andric while (E < Size && isdigit(Data[E])) E++;
3750b57cec5SDimitry Andric assert(B < E);
3760b57cec5SDimitry Andric // now we have digits in [B, E).
3770b57cec5SDimitry Andric // strtol and friends don't accept non-zero-teminated data, parse it manually.
3780b57cec5SDimitry Andric uint64_t Val = Data[B] - '0';
3790b57cec5SDimitry Andric for (size_t i = B + 1; i < E; i++)
3800b57cec5SDimitry Andric Val = Val * 10 + Data[i] - '0';
3810b57cec5SDimitry Andric
3820b57cec5SDimitry Andric // Mutate the integer value.
3830b57cec5SDimitry Andric switch(Rand(5)) {
3840b57cec5SDimitry Andric case 0: Val++; break;
3850b57cec5SDimitry Andric case 1: Val--; break;
3860b57cec5SDimitry Andric case 2: Val /= 2; break;
3870b57cec5SDimitry Andric case 3: Val *= 2; break;
3880b57cec5SDimitry Andric case 4: Val = Rand(Val * Val); break;
3890b57cec5SDimitry Andric default: assert(0);
3900b57cec5SDimitry Andric }
3910b57cec5SDimitry Andric // Just replace the bytes with the new ones, don't bother moving bytes.
3920b57cec5SDimitry Andric for (size_t i = B; i < E; i++) {
3930b57cec5SDimitry Andric size_t Idx = E + B - i - 1;
3940b57cec5SDimitry Andric assert(Idx >= B && Idx < E);
3950b57cec5SDimitry Andric Data[Idx] = (Val % 10) + '0';
3960b57cec5SDimitry Andric Val /= 10;
3970b57cec5SDimitry Andric }
3980b57cec5SDimitry Andric return Size;
3990b57cec5SDimitry Andric }
4000b57cec5SDimitry Andric
4010b57cec5SDimitry Andric template<class T>
ChangeBinaryInteger(uint8_t * Data,size_t Size,Random & Rand)4020b57cec5SDimitry Andric size_t ChangeBinaryInteger(uint8_t *Data, size_t Size, Random &Rand) {
4030b57cec5SDimitry Andric if (Size < sizeof(T)) return 0;
4040b57cec5SDimitry Andric size_t Off = Rand(Size - sizeof(T) + 1);
4050b57cec5SDimitry Andric assert(Off + sizeof(T) <= Size);
4060b57cec5SDimitry Andric T Val;
4070b57cec5SDimitry Andric if (Off < 64 && !Rand(4)) {
408fe6060f1SDimitry Andric Val = static_cast<T>(Size);
4090b57cec5SDimitry Andric if (Rand.RandBool())
4100b57cec5SDimitry Andric Val = Bswap(Val);
4110b57cec5SDimitry Andric } else {
4120b57cec5SDimitry Andric memcpy(&Val, Data + Off, sizeof(Val));
413fe6060f1SDimitry Andric T Add = static_cast<T>(Rand(21));
4140b57cec5SDimitry Andric Add -= 10;
4150b57cec5SDimitry Andric if (Rand.RandBool())
4160b57cec5SDimitry Andric Val = Bswap(T(Bswap(Val) + Add)); // Add assuming different endiannes.
4170b57cec5SDimitry Andric else
4180b57cec5SDimitry Andric Val = Val + Add; // Add assuming current endiannes.
4190b57cec5SDimitry Andric if (Add == 0 || Rand.RandBool()) // Maybe negate.
4200b57cec5SDimitry Andric Val = -Val;
4210b57cec5SDimitry Andric }
4220b57cec5SDimitry Andric memcpy(Data + Off, &Val, sizeof(Val));
4230b57cec5SDimitry Andric return Size;
4240b57cec5SDimitry Andric }
4250b57cec5SDimitry Andric
Mutate_ChangeBinaryInteger(uint8_t * Data,size_t Size,size_t MaxSize)4260b57cec5SDimitry Andric size_t MutationDispatcher::Mutate_ChangeBinaryInteger(uint8_t *Data,
4270b57cec5SDimitry Andric size_t Size,
4280b57cec5SDimitry Andric size_t MaxSize) {
4290b57cec5SDimitry Andric if (Size > MaxSize) return 0;
4300b57cec5SDimitry Andric switch (Rand(4)) {
4310b57cec5SDimitry Andric case 3: return ChangeBinaryInteger<uint64_t>(Data, Size, Rand);
4320b57cec5SDimitry Andric case 2: return ChangeBinaryInteger<uint32_t>(Data, Size, Rand);
4330b57cec5SDimitry Andric case 1: return ChangeBinaryInteger<uint16_t>(Data, Size, Rand);
4340b57cec5SDimitry Andric case 0: return ChangeBinaryInteger<uint8_t>(Data, Size, Rand);
4350b57cec5SDimitry Andric default: assert(0);
4360b57cec5SDimitry Andric }
4370b57cec5SDimitry Andric return 0;
4380b57cec5SDimitry Andric }
4390b57cec5SDimitry Andric
Mutate_CrossOver(uint8_t * Data,size_t Size,size_t MaxSize)4400b57cec5SDimitry Andric size_t MutationDispatcher::Mutate_CrossOver(uint8_t *Data, size_t Size,
4410b57cec5SDimitry Andric size_t MaxSize) {
4420b57cec5SDimitry Andric if (Size > MaxSize) return 0;
4430b57cec5SDimitry Andric if (Size == 0) return 0;
4440b57cec5SDimitry Andric if (!CrossOverWith) return 0;
4450b57cec5SDimitry Andric const Unit &O = *CrossOverWith;
4460b57cec5SDimitry Andric if (O.empty()) return 0;
4470b57cec5SDimitry Andric size_t NewSize = 0;
4480b57cec5SDimitry Andric switch(Rand(3)) {
4490b57cec5SDimitry Andric case 0:
450e8d8bef9SDimitry Andric MutateInPlaceHere.resize(MaxSize);
451e8d8bef9SDimitry Andric NewSize = CrossOver(Data, Size, O.data(), O.size(),
452e8d8bef9SDimitry Andric MutateInPlaceHere.data(), MaxSize);
453e8d8bef9SDimitry Andric memcpy(Data, MutateInPlaceHere.data(), NewSize);
4540b57cec5SDimitry Andric break;
4550b57cec5SDimitry Andric case 1:
456e8d8bef9SDimitry Andric NewSize = InsertPartOf(O.data(), O.size(), Data, Size, MaxSize);
4570b57cec5SDimitry Andric if (!NewSize)
458e8d8bef9SDimitry Andric NewSize = CopyPartOf(O.data(), O.size(), Data, Size);
4590b57cec5SDimitry Andric break;
4600b57cec5SDimitry Andric case 2:
461e8d8bef9SDimitry Andric NewSize = CopyPartOf(O.data(), O.size(), Data, Size);
4620b57cec5SDimitry Andric break;
4630b57cec5SDimitry Andric default: assert(0);
4640b57cec5SDimitry Andric }
4650b57cec5SDimitry Andric assert(NewSize > 0 && "CrossOver returned empty unit");
4660b57cec5SDimitry Andric assert(NewSize <= MaxSize && "CrossOver returned overisized unit");
4670b57cec5SDimitry Andric return NewSize;
4680b57cec5SDimitry Andric }
4690b57cec5SDimitry Andric
StartMutationSequence()4700b57cec5SDimitry Andric void MutationDispatcher::StartMutationSequence() {
4710b57cec5SDimitry Andric CurrentMutatorSequence.clear();
4720b57cec5SDimitry Andric CurrentDictionaryEntrySequence.clear();
4730b57cec5SDimitry Andric }
4740b57cec5SDimitry Andric
4750b57cec5SDimitry Andric // Copy successful dictionary entries to PersistentAutoDictionary.
RecordSuccessfulMutationSequence()4760b57cec5SDimitry Andric void MutationDispatcher::RecordSuccessfulMutationSequence() {
4770b57cec5SDimitry Andric for (auto DE : CurrentDictionaryEntrySequence) {
4780b57cec5SDimitry Andric // PersistentAutoDictionary.AddWithSuccessCountOne(DE);
4790b57cec5SDimitry Andric DE->IncSuccessCount();
4800b57cec5SDimitry Andric assert(DE->GetW().size());
4810b57cec5SDimitry Andric // Linear search is fine here as this happens seldom.
4820b57cec5SDimitry Andric if (!PersistentAutoDictionary.ContainsWord(DE->GetW()))
483fe6060f1SDimitry Andric PersistentAutoDictionary.push_back(*DE);
4840b57cec5SDimitry Andric }
4850b57cec5SDimitry Andric }
4860b57cec5SDimitry Andric
PrintRecommendedDictionary()4870b57cec5SDimitry Andric void MutationDispatcher::PrintRecommendedDictionary() {
488349cc55cSDimitry Andric std::vector<DictionaryEntry> V;
4890b57cec5SDimitry Andric for (auto &DE : PersistentAutoDictionary)
4900b57cec5SDimitry Andric if (!ManualDictionary.ContainsWord(DE.GetW()))
4910b57cec5SDimitry Andric V.push_back(DE);
4920b57cec5SDimitry Andric if (V.empty()) return;
4930b57cec5SDimitry Andric Printf("###### Recommended dictionary. ######\n");
4940b57cec5SDimitry Andric for (auto &DE: V) {
4950b57cec5SDimitry Andric assert(DE.GetW().size());
4960b57cec5SDimitry Andric Printf("\"");
4970b57cec5SDimitry Andric PrintASCII(DE.GetW(), "\"");
4980b57cec5SDimitry Andric Printf(" # Uses: %zd\n", DE.GetUseCount());
4990b57cec5SDimitry Andric }
5000b57cec5SDimitry Andric Printf("###### End of recommended dictionary. ######\n");
5010b57cec5SDimitry Andric }
5020b57cec5SDimitry Andric
PrintMutationSequence(bool Verbose)503e8d8bef9SDimitry Andric void MutationDispatcher::PrintMutationSequence(bool Verbose) {
5040b57cec5SDimitry Andric Printf("MS: %zd ", CurrentMutatorSequence.size());
505e8d8bef9SDimitry Andric size_t EntriesToPrint =
506e8d8bef9SDimitry Andric Verbose ? CurrentMutatorSequence.size()
507e8d8bef9SDimitry Andric : std::min(kMaxMutationsToPrint, CurrentMutatorSequence.size());
508e8d8bef9SDimitry Andric for (size_t i = 0; i < EntriesToPrint; i++)
509e8d8bef9SDimitry Andric Printf("%s-", CurrentMutatorSequence[i].Name);
5100b57cec5SDimitry Andric if (!CurrentDictionaryEntrySequence.empty()) {
5110b57cec5SDimitry Andric Printf(" DE: ");
512e8d8bef9SDimitry Andric EntriesToPrint = Verbose ? CurrentDictionaryEntrySequence.size()
513e8d8bef9SDimitry Andric : std::min(kMaxMutationsToPrint,
514e8d8bef9SDimitry Andric CurrentDictionaryEntrySequence.size());
515e8d8bef9SDimitry Andric for (size_t i = 0; i < EntriesToPrint; i++) {
5160b57cec5SDimitry Andric Printf("\"");
517e8d8bef9SDimitry Andric PrintASCII(CurrentDictionaryEntrySequence[i]->GetW(), "\"-");
5180b57cec5SDimitry Andric }
5190b57cec5SDimitry Andric }
5200b57cec5SDimitry Andric }
5210b57cec5SDimitry Andric
MutationSequence()522e8d8bef9SDimitry Andric std::string MutationDispatcher::MutationSequence() {
523e8d8bef9SDimitry Andric std::string MS;
524*06c3fb27SDimitry Andric for (const auto &M : CurrentMutatorSequence) {
525e8d8bef9SDimitry Andric MS += M.Name;
526e8d8bef9SDimitry Andric MS += "-";
527e8d8bef9SDimitry Andric }
528e8d8bef9SDimitry Andric return MS;
529e8d8bef9SDimitry Andric }
530e8d8bef9SDimitry Andric
Mutate(uint8_t * Data,size_t Size,size_t MaxSize)5310b57cec5SDimitry Andric size_t MutationDispatcher::Mutate(uint8_t *Data, size_t Size, size_t MaxSize) {
5320b57cec5SDimitry Andric return MutateImpl(Data, Size, MaxSize, Mutators);
5330b57cec5SDimitry Andric }
5340b57cec5SDimitry Andric
DefaultMutate(uint8_t * Data,size_t Size,size_t MaxSize)5350b57cec5SDimitry Andric size_t MutationDispatcher::DefaultMutate(uint8_t *Data, size_t Size,
5360b57cec5SDimitry Andric size_t MaxSize) {
5370b57cec5SDimitry Andric return MutateImpl(Data, Size, MaxSize, DefaultMutators);
5380b57cec5SDimitry Andric }
5390b57cec5SDimitry Andric
5400b57cec5SDimitry Andric // Mutates Data in place, returns new size.
MutateImpl(uint8_t * Data,size_t Size,size_t MaxSize,std::vector<Mutator> & Mutators)5410b57cec5SDimitry Andric size_t MutationDispatcher::MutateImpl(uint8_t *Data, size_t Size,
5420b57cec5SDimitry Andric size_t MaxSize,
543349cc55cSDimitry Andric std::vector<Mutator> &Mutators) {
5440b57cec5SDimitry Andric assert(MaxSize > 0);
5450b57cec5SDimitry Andric // Some mutations may fail (e.g. can't insert more bytes if Size == MaxSize),
5460b57cec5SDimitry Andric // in which case they will return 0.
5470b57cec5SDimitry Andric // Try several times before returning un-mutated data.
5480b57cec5SDimitry Andric for (int Iter = 0; Iter < 100; Iter++) {
5490b57cec5SDimitry Andric auto M = Mutators[Rand(Mutators.size())];
5500b57cec5SDimitry Andric size_t NewSize = (this->*(M.Fn))(Data, Size, MaxSize);
5510b57cec5SDimitry Andric if (NewSize && NewSize <= MaxSize) {
5520b57cec5SDimitry Andric if (Options.OnlyASCII)
5530b57cec5SDimitry Andric ToASCII(Data, NewSize);
5540b57cec5SDimitry Andric CurrentMutatorSequence.push_back(M);
5550b57cec5SDimitry Andric return NewSize;
5560b57cec5SDimitry Andric }
5570b57cec5SDimitry Andric }
5580b57cec5SDimitry Andric *Data = ' ';
5590b57cec5SDimitry Andric return 1; // Fallback, should not happen frequently.
5600b57cec5SDimitry Andric }
5610b57cec5SDimitry Andric
5620b57cec5SDimitry Andric // 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)5630b57cec5SDimitry Andric size_t MutationDispatcher::MutateWithMask(uint8_t *Data, size_t Size,
5640b57cec5SDimitry Andric size_t MaxSize,
565349cc55cSDimitry Andric const std::vector<uint8_t> &Mask) {
5660b57cec5SDimitry Andric size_t MaskedSize = std::min(Size, Mask.size());
5670b57cec5SDimitry Andric // * Copy the worthy bytes into a temporary array T
5680b57cec5SDimitry Andric // * Mutate T
5690b57cec5SDimitry Andric // * Copy T back.
5700b57cec5SDimitry Andric // This is totally unoptimized.
5710b57cec5SDimitry Andric auto &T = MutateWithMaskTemp;
5720b57cec5SDimitry Andric if (T.size() < Size)
5730b57cec5SDimitry Andric T.resize(Size);
5740b57cec5SDimitry Andric size_t OneBits = 0;
5750b57cec5SDimitry Andric for (size_t I = 0; I < MaskedSize; I++)
5760b57cec5SDimitry Andric if (Mask[I])
5770b57cec5SDimitry Andric T[OneBits++] = Data[I];
5780b57cec5SDimitry Andric
5790b57cec5SDimitry Andric if (!OneBits) return 0;
5800b57cec5SDimitry Andric assert(!T.empty());
5810b57cec5SDimitry Andric size_t NewSize = Mutate(T.data(), OneBits, OneBits);
5820b57cec5SDimitry Andric assert(NewSize <= OneBits);
5830b57cec5SDimitry Andric (void)NewSize;
5840b57cec5SDimitry Andric // Even if NewSize < OneBits we still use all OneBits bytes.
5850b57cec5SDimitry Andric for (size_t I = 0, J = 0; I < MaskedSize; I++)
5860b57cec5SDimitry Andric if (Mask[I])
5870b57cec5SDimitry Andric Data[I] = T[J++];
5880b57cec5SDimitry Andric return Size;
5890b57cec5SDimitry Andric }
5900b57cec5SDimitry Andric
AddWordToManualDictionary(const Word & W)5910b57cec5SDimitry Andric void MutationDispatcher::AddWordToManualDictionary(const Word &W) {
5920b57cec5SDimitry Andric ManualDictionary.push_back(
5930b57cec5SDimitry Andric {W, std::numeric_limits<size_t>::max()});
5940b57cec5SDimitry Andric }
5950b57cec5SDimitry Andric
5960b57cec5SDimitry Andric } // namespace fuzzer
597