From 596885b016d9e6f8c39a4d45fc9b35f8b854f2f4 Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Thu, 6 Aug 2015 01:29:13 +0000 Subject: [PATCH] [libFuzzer] add one more mutation strategy: byte shuffling git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@244188 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Fuzzer/FuzzerInterface.h | 2 +- lib/Fuzzer/FuzzerInternal.h | 2 ++ lib/Fuzzer/FuzzerMutate.cpp | 16 +++++++++++++++- lib/Fuzzer/test/FuzzerUnittest.cpp | 23 +++++++++++++++++++++++ 4 files changed, 41 insertions(+), 2 deletions(-) diff --git a/lib/Fuzzer/FuzzerInterface.h b/lib/Fuzzer/FuzzerInterface.h index 3be4b05e66c..6acae6c67af 100644 --- a/lib/Fuzzer/FuzzerInterface.h +++ b/lib/Fuzzer/FuzzerInterface.h @@ -50,7 +50,7 @@ class FuzzerRandomBase { // Return a random number. virtual size_t Rand() = 0; // Return a random number in range [0,n). - size_t operator()(size_t n) { return Rand() % n; } + size_t operator()(size_t n) { return n ? Rand() % n : 0; } bool RandBool() { return Rand() % 2; } }; diff --git a/lib/Fuzzer/FuzzerInternal.h b/lib/Fuzzer/FuzzerInternal.h index 610b4375f24..e33ab702178 100644 --- a/lib/Fuzzer/FuzzerInternal.h +++ b/lib/Fuzzer/FuzzerInternal.h @@ -33,6 +33,8 @@ void CopyFileToErr(const std::string &Path); std::string DirPlusFile(const std::string &DirPath, const std::string &FileName); +size_t Mutate_ShuffleBytes(uint8_t *Data, size_t Size, size_t MaxSize, + FuzzerRandomBase &Rand); size_t Mutate_EraseByte(uint8_t *Data, size_t Size, size_t MaxSize, FuzzerRandomBase &Rand); size_t Mutate_InsertByte(uint8_t *Data, size_t Size, size_t MaxSize, diff --git a/lib/Fuzzer/FuzzerMutate.cpp b/lib/Fuzzer/FuzzerMutate.cpp index fc3176299c9..c425ae0c1cd 100644 --- a/lib/Fuzzer/FuzzerMutate.cpp +++ b/lib/Fuzzer/FuzzerMutate.cpp @@ -13,6 +13,8 @@ #include "FuzzerInternal.h" +#include + namespace fuzzer { static char FlipRandomBit(char X, FuzzerRandomBase &Rand) { @@ -33,6 +35,17 @@ static char RandCh(FuzzerRandomBase &Rand) { return Special[Rand(sizeof(Special) - 1)]; } +size_t Mutate_ShuffleBytes(uint8_t *Data, size_t Size, size_t MaxSize, + FuzzerRandomBase &Rand) { + assert(Size); + size_t ShuffleAmount = Rand(std::min(Size, 8UL)) + 1; // [1,8] and <= Size. + size_t ShuffleStart = Rand(Size - ShuffleAmount); + assert(ShuffleStart + ShuffleAmount <= Size); + std::random_shuffle(Data + ShuffleStart, Data + ShuffleStart + ShuffleAmount, + Rand); + return Size; +} + size_t Mutate_EraseByte(uint8_t *Data, size_t Size, size_t MaxSize, FuzzerRandomBase &Rand) { assert(Size); @@ -78,11 +91,12 @@ size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize, return MaxSize; } assert(Size > 0); - switch (Rand(4)) { + switch (Rand(5)) { case 0: Size = Mutate_EraseByte(Data, Size, MaxSize, Rand); break; case 1: Size = Mutate_InsertByte(Data, Size, MaxSize, Rand); break; case 2: Size = Mutate_ChangeByte(Data, Size, MaxSize, Rand); break; case 3: Size = Mutate_ChangeBit(Data, Size, MaxSize, Rand); break; + case 4: Size = Mutate_ShuffleBytes(Data, Size, MaxSize, Rand); break; } assert(Size > 0); return Size; diff --git a/lib/Fuzzer/test/FuzzerUnittest.cpp b/lib/Fuzzer/test/FuzzerUnittest.cpp index a3e6a136b27..518cfab5d93 100644 --- a/lib/Fuzzer/test/FuzzerUnittest.cpp +++ b/lib/Fuzzer/test/FuzzerUnittest.cpp @@ -192,3 +192,26 @@ void TestChangeBit(Mutator M, int NumIter) { TEST(FuzzerMutate, ChangeBit1) { TestChangeBit(Mutate_ChangeBit, 1 << 16); } TEST(FuzzerMutate, ChangeBit2) { TestChangeBit(Mutate, 1 << 18); } + +void TestShuffleBytes(Mutator M, int NumIter) { + FuzzerRandomLibc Rand(0); + int FoundMask = 0; + uint8_t CH0[7] = {0x00, 0x22, 0x11, 0x33, 0x44, 0x55, 0x66}; + uint8_t CH1[7] = {0x11, 0x00, 0x33, 0x22, 0x44, 0x55, 0x66}; + uint8_t CH2[7] = {0x00, 0x33, 0x11, 0x22, 0x44, 0x55, 0x66}; + uint8_t CH3[7] = {0x00, 0x11, 0x22, 0x44, 0x55, 0x66, 0x33}; + uint8_t CH4[7] = {0x00, 0x11, 0x22, 0x33, 0x55, 0x44, 0x66}; + for (int i = 0; i < NumIter; i++) { + uint8_t T[7] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + size_t NewSize = M(T, 7, 7, Rand); + if (NewSize == 7 && !memcmp(CH0, T, 7)) FoundMask |= 1 << 0; + if (NewSize == 7 && !memcmp(CH1, T, 7)) FoundMask |= 1 << 1; + if (NewSize == 7 && !memcmp(CH2, T, 7)) FoundMask |= 1 << 2; + if (NewSize == 7 && !memcmp(CH3, T, 7)) FoundMask |= 1 << 3; + if (NewSize == 7 && !memcmp(CH4, T, 7)) FoundMask |= 1 << 4; + } + EXPECT_EQ(FoundMask, 31); +} + +TEST(FuzzerMutate, ShuffleBytes1) { TestShuffleBytes(Mutate_ShuffleBytes, 1 << 15); } +TEST(FuzzerMutate, ShuffleBytes2) { TestShuffleBytes(Mutate, 1 << 16); } -- 2.34.1