1 //===- FuzzerMutate.cpp - Mutate a test input -----------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
9 // Mutate a test input.
10 //===----------------------------------------------------------------------===//
14 #include "FuzzerInternal.h"
20 typedef size_t (MutationDispatcher::*Mutator)(uint8_t *Data, size_t Size,
23 struct MutationDispatcher::Impl {
24 std::vector<Unit> Dictionary;
25 std::vector<Mutator> Mutators;
27 Mutators.push_back(&MutationDispatcher::Mutate_EraseByte);
28 Mutators.push_back(&MutationDispatcher::Mutate_InsertByte);
29 Mutators.push_back(&MutationDispatcher::Mutate_ChangeByte);
30 Mutators.push_back(&MutationDispatcher::Mutate_ChangeBit);
31 Mutators.push_back(&MutationDispatcher::Mutate_ShuffleBytes);
33 void AddWordToDictionary(const uint8_t *Word, size_t Size) {
34 if (Dictionary.empty()) {
35 Mutators.push_back(&MutationDispatcher::Mutate_AddWordFromDictionary);
37 Dictionary.push_back(Unit(Word, Word + Size));
42 static char FlipRandomBit(char X, FuzzerRandomBase &Rand) {
54 static char RandCh(FuzzerRandomBase &Rand) {
55 if (Rand.RandBool()) return Rand(256);
56 const char *Special = "!*'();:@&=+$,/?%#[]123ABCxyz-`~.";
57 return Special[Rand(sizeof(Special) - 1)];
60 size_t MutationDispatcher::Mutate_ShuffleBytes(uint8_t *Data, size_t Size,
63 size_t ShuffleAmount = Rand(std::min(Size, 8UL)) + 1; // [1,8] and <= Size.
64 size_t ShuffleStart = Rand(Size - ShuffleAmount);
65 assert(ShuffleStart + ShuffleAmount <= Size);
66 std::random_shuffle(Data + ShuffleStart, Data + ShuffleStart + ShuffleAmount,
71 size_t MutationDispatcher::Mutate_EraseByte(uint8_t *Data, size_t Size,
74 if (Size == 1) return 0;
75 size_t Idx = Rand(Size);
77 memmove(Data + Idx, Data + Idx + 1, Size - Idx - 1);
81 size_t MutationDispatcher::Mutate_InsertByte(uint8_t *Data, size_t Size,
83 if (Size == MaxSize) return 0;
84 size_t Idx = Rand(Size + 1);
85 // Insert new value at Data[Idx].
86 memmove(Data + Idx + 1, Data + Idx, Size - Idx);
87 Data[Idx] = RandCh(Rand);
91 size_t MutationDispatcher::Mutate_ChangeByte(uint8_t *Data, size_t Size,
93 size_t Idx = Rand(Size);
94 Data[Idx] = RandCh(Rand);
98 size_t MutationDispatcher::Mutate_ChangeBit(uint8_t *Data, size_t Size,
100 size_t Idx = Rand(Size);
101 Data[Idx] = FlipRandomBit(Data[Idx], Rand);
105 size_t MutationDispatcher::Mutate_AddWordFromDictionary(uint8_t *Data,
108 auto &D = MDImpl->Dictionary;
110 if (D.empty()) return 0;
111 const Unit &Word = D[Rand(D.size())];
112 if (Size + Word.size() > MaxSize) return 0;
113 size_t Idx = Rand(Size + 1);
114 memmove(Data + Idx + Word.size(), Data + Idx, Size - Idx);
115 memcpy(Data + Idx, Word.data(), Word.size());
116 return Size + Word.size();
119 // Mutates Data in place, returns new size.
120 size_t MutationDispatcher::Mutate(uint8_t *Data, size_t Size, size_t MaxSize) {
122 assert(Size <= MaxSize);
124 for (size_t i = 0; i < MaxSize; i++)
125 Data[i] = RandCh(Rand);
129 // Some mutations may fail (e.g. can't insert more bytes if Size == MaxSize),
130 // in which case they will return 0.
131 // Try several times before returning un-mutated data.
132 for (int Iter = 0; Iter < 10; Iter++) {
133 size_t MutatorIdx = Rand(MDImpl->Mutators.size());
135 (this->*(MDImpl->Mutators[MutatorIdx]))(Data, Size, MaxSize);
136 if (NewSize) return NewSize;
141 void MutationDispatcher::AddWordToDictionary(const uint8_t *Word, size_t Size) {
142 MDImpl->AddWordToDictionary(Word, Size);
145 MutationDispatcher::MutationDispatcher(FuzzerRandomBase &Rand) : Rand(Rand) {
149 MutationDispatcher::~MutationDispatcher() { delete MDImpl; }
151 } // namespace fuzzer