Skip to content
This repository was archived by the owner on Apr 23, 2020. It is now read-only.

Commit 79d1008

Browse files
committed
[libFuzzer] more mutations
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@278950 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent d9052e8 commit 79d1008

File tree

3 files changed

+124
-18
lines changed

3 files changed

+124
-18
lines changed

lib/Fuzzer/FuzzerInternal.h

+7
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,8 @@ class MutationDispatcher {
272272
size_t Mutate_ChangeByte(uint8_t *Data, size_t Size, size_t MaxSize);
273273
/// Mutates data by chanding one bit.
274274
size_t Mutate_ChangeBit(uint8_t *Data, size_t Size, size_t MaxSize);
275+
/// Mutates data by copying/inserting a part of data into a different place.
276+
size_t Mutate_CopyPart(uint8_t *Data, size_t Size, size_t MaxSize);
275277

276278
/// Mutates data by adding a word from the manual dictionary.
277279
size_t Mutate_AddWordFromManualDictionary(uint8_t *Data, size_t Size,
@@ -324,6 +326,11 @@ class MutationDispatcher {
324326
size_t MutateImpl(uint8_t *Data, size_t Size, size_t MaxSize,
325327
const std::vector<Mutator> &Mutators);
326328

329+
size_t InsertPartOf(const uint8_t *From, size_t FromSize, uint8_t *To,
330+
size_t ToSize, size_t MaxToSize);
331+
size_t CopyPartOf(const uint8_t *From, size_t FromSize, uint8_t *To,
332+
size_t ToSize);
333+
327334
Random &Rand;
328335
const FuzzingOptions Options;
329336

lib/Fuzzer/FuzzerMutate.cpp

+69-18
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ MutationDispatcher::MutationDispatcher(Random &Rand,
3232
{&MutationDispatcher::Mutate_ChangeBit, "ChangeBit"},
3333
{&MutationDispatcher::Mutate_ShuffleBytes, "ShuffleBytes"},
3434
{&MutationDispatcher::Mutate_ChangeASCIIInteger, "ChangeASCIIInt"},
35+
{&MutationDispatcher::Mutate_CopyPart, "CopyPart"},
3536
{&MutationDispatcher::Mutate_CrossOver, "CrossOver"},
3637
{&MutationDispatcher::Mutate_AddWordFromManualDictionary,
3738
"AddFromManualDict"},
@@ -51,21 +52,9 @@ MutationDispatcher::MutationDispatcher(Random &Rand,
5152
{&MutationDispatcher::Mutate_CustomCrossOver, "CustomCrossOver"});
5253
}
5354

54-
static char FlipRandomBit(char X, Random &Rand) {
55-
int Bit = Rand(8);
56-
char Mask = 1 << Bit;
57-
char R;
58-
if (X & (1 << Bit))
59-
R = X & ~Mask;
60-
else
61-
R = X | Mask;
62-
assert(R != X);
63-
return R;
64-
}
65-
6655
static char RandCh(Random &Rand) {
6756
if (Rand.RandBool()) return Rand(256);
68-
const char *Special = "!*'();:@&=+$,/?%#[]123ABCxyz-`~.";
57+
const char *Special = "!*'();:@&=+$,/?%#[]012Az-`~.\xff\x00";
6958
return Special[Rand(sizeof(Special) - 1)];
7059
}
7160

@@ -155,7 +144,7 @@ size_t MutationDispatcher::Mutate_ChangeByte(uint8_t *Data, size_t Size,
155144
size_t MutationDispatcher::Mutate_ChangeBit(uint8_t *Data, size_t Size,
156145
size_t MaxSize) {
157146
size_t Idx = Rand(Size);
158-
Data[Idx] = FlipRandomBit(Data[Idx], Rand);
147+
Data[Idx] ^= 1 << Rand(8);
159148
return Size;
160149
}
161150

@@ -198,6 +187,55 @@ size_t MutationDispatcher::AddWordFromDictionary(Dictionary &D, uint8_t *Data,
198187
return Size;
199188
}
200189

190+
// Overwrites part of To[0,ToSize) with a part of From[0,FromSize).
191+
// Returns ToSize.
192+
size_t MutationDispatcher::CopyPartOf(const uint8_t *From, size_t FromSize,
193+
uint8_t *To, size_t ToSize) {
194+
// Copy From[FromBeg, FromBeg + CopySize) into To[ToBeg, ToBeg + CopySize).
195+
size_t ToBeg = Rand(ToSize);
196+
size_t CopySize = Rand(ToSize - ToBeg) + 1;
197+
assert(ToBeg + CopySize <= ToSize);
198+
CopySize = std::min(CopySize, FromSize);
199+
size_t FromBeg = Rand(FromSize - CopySize + 1);
200+
assert(FromBeg + CopySize <= FromSize);
201+
memmove(To + ToBeg, From + FromBeg, CopySize);
202+
return ToSize;
203+
}
204+
205+
// Inserts part of From[0,ToSize) into To.
206+
// Returns new size of To on success or 0 on failure.
207+
size_t MutationDispatcher::InsertPartOf(const uint8_t *From, size_t FromSize,
208+
uint8_t *To, size_t ToSize,
209+
size_t MaxToSize) {
210+
if (ToSize >= MaxToSize) return 0;
211+
size_t AvailableSpace = MaxToSize - ToSize;
212+
size_t MaxCopySize = std::min(AvailableSpace, FromSize);
213+
size_t CopySize = Rand(MaxCopySize) + 1;
214+
size_t FromBeg = Rand(FromSize - CopySize + 1);
215+
assert(FromBeg + CopySize <= FromSize);
216+
size_t ToInsertPos = Rand(ToSize + 1);
217+
assert(ToInsertPos + CopySize <= MaxToSize);
218+
size_t TailSize = ToSize - ToInsertPos;
219+
if (To == From) {
220+
MutateInPlaceHere.resize(MaxToSize);
221+
memcpy(MutateInPlaceHere.data(), From + FromBeg, CopySize);
222+
memmove(To + ToInsertPos + CopySize, To + ToInsertPos, TailSize);
223+
memmove(To + ToInsertPos, MutateInPlaceHere.data(), CopySize);
224+
} else {
225+
memmove(To + ToInsertPos + CopySize, To + ToInsertPos, TailSize);
226+
memmove(To + ToInsertPos, From + FromBeg, CopySize);
227+
}
228+
return ToSize + CopySize;
229+
}
230+
231+
size_t MutationDispatcher::Mutate_CopyPart(uint8_t *Data, size_t Size,
232+
size_t MaxSize) {
233+
if (Rand.RandBool())
234+
return CopyPartOf(Data, Size, Data, Size);
235+
else
236+
return InsertPartOf(Data, Size, Data, Size, MaxSize);
237+
}
238+
201239
size_t MutationDispatcher::Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size,
202240
size_t MaxSize) {
203241
size_t B = Rand(Size);
@@ -235,12 +273,25 @@ size_t MutationDispatcher::Mutate_CrossOver(uint8_t *Data, size_t Size,
235273
size_t MaxSize) {
236274
if (!Corpus || Corpus->size() < 2 || Size == 0) return 0;
237275
size_t Idx = Rand(Corpus->size());
238-
const Unit &Other = (*Corpus)[Idx];
239-
if (Other.empty()) return 0;
276+
const Unit &O = (*Corpus)[Idx];
277+
if (O.empty()) return 0;
240278
MutateInPlaceHere.resize(MaxSize);
241279
auto &U = MutateInPlaceHere;
242-
size_t NewSize =
243-
CrossOver(Data, Size, Other.data(), Other.size(), U.data(), U.size());
280+
size_t NewSize;
281+
switch(Rand(3)) {
282+
case 0:
283+
NewSize = CrossOver(Data, Size, O.data(), O.size(), U.data(), U.size());
284+
break;
285+
case 1:
286+
NewSize = InsertPartOf(O.data(), O.size(), U.data(), U.size(), MaxSize);
287+
if (NewSize)
288+
break;
289+
// Fallthrough
290+
case 2:
291+
NewSize = CopyPartOf(O.data(), O.size(), U.data(), U.size());
292+
break;
293+
default: assert(0);
294+
}
244295
assert(NewSize > 0 && "CrossOver returned empty unit");
245296
assert(NewSize <= MaxSize && "CrossOver returned overisized unit");
246297
memcpy(Data, U.data(), NewSize);

lib/Fuzzer/test/FuzzerUnittest.cpp

+48
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,54 @@ TEST(FuzzerMutate, ShuffleBytes2) {
324324
TestShuffleBytes(&MutationDispatcher::Mutate, 1 << 20);
325325
}
326326

327+
void TestCopyPart(Mutator M, int NumIter) {
328+
std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
329+
fuzzer::EF = t.get();
330+
Random Rand(0);
331+
MutationDispatcher MD(Rand, {});
332+
int FoundMask = 0;
333+
uint8_t CH0[7] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x11};
334+
uint8_t CH1[7] = {0x55, 0x66, 0x22, 0x33, 0x44, 0x55, 0x66};
335+
uint8_t CH2[7] = {0x00, 0x55, 0x66, 0x33, 0x44, 0x55, 0x66};
336+
uint8_t CH3[7] = {0x00, 0x11, 0x22, 0x00, 0x11, 0x22, 0x66};
337+
uint8_t CH4[7] = {0x00, 0x11, 0x11, 0x22, 0x33, 0x55, 0x66};
338+
339+
for (int i = 0; i < NumIter; i++) {
340+
uint8_t T[7] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
341+
size_t NewSize = (MD.*M)(T, 7, 7);
342+
if (NewSize == 7 && !memcmp(CH0, T, 7)) FoundMask |= 1 << 0;
343+
if (NewSize == 7 && !memcmp(CH1, T, 7)) FoundMask |= 1 << 1;
344+
if (NewSize == 7 && !memcmp(CH2, T, 7)) FoundMask |= 1 << 2;
345+
if (NewSize == 7 && !memcmp(CH3, T, 7)) FoundMask |= 1 << 3;
346+
if (NewSize == 7 && !memcmp(CH4, T, 7)) FoundMask |= 1 << 4;
347+
}
348+
349+
uint8_t CH5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x11, 0x22};
350+
uint8_t CH6[8] = {0x22, 0x33, 0x44, 0x00, 0x11, 0x22, 0x33, 0x44};
351+
uint8_t CH7[8] = {0x00, 0x11, 0x22, 0x00, 0x11, 0x22, 0x33, 0x44};
352+
uint8_t CH8[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x22, 0x33, 0x44};
353+
uint8_t CH9[8] = {0x00, 0x11, 0x22, 0x22, 0x33, 0x44, 0x33, 0x44};
354+
355+
for (int i = 0; i < NumIter; i++) {
356+
uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
357+
size_t NewSize = (MD.*M)(T, 5, 8);
358+
if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5;
359+
if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6;
360+
if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7;
361+
if (NewSize == 8 && !memcmp(CH8, T, 8)) FoundMask |= 1 << 8;
362+
if (NewSize == 8 && !memcmp(CH9, T, 8)) FoundMask |= 1 << 9;
363+
}
364+
365+
EXPECT_EQ(FoundMask, 1023);
366+
}
367+
368+
TEST(FuzzerMutate, CopyPart1) {
369+
TestCopyPart(&MutationDispatcher::Mutate_CopyPart, 1 << 10);
370+
}
371+
TEST(FuzzerMutate, CopyPart2) {
372+
TestCopyPart(&MutationDispatcher::Mutate, 1 << 13);
373+
}
374+
327375
void TestAddWordFromDictionary(Mutator M, int NumIter) {
328376
std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
329377
fuzzer::EF = t.get();

0 commit comments

Comments
 (0)