diff --git a/lib/Fuzzer/FuzzerInternal.h b/lib/Fuzzer/FuzzerInternal.h index 274fdf077a7..cc86c361460 100644 --- a/lib/Fuzzer/FuzzerInternal.h +++ b/lib/Fuzzer/FuzzerInternal.h @@ -33,8 +33,14 @@ void CopyFileToErr(const std::string &Path); std::string DirPlusFile(const std::string &DirPath, const std::string &FileName); -size_t Mutate_EraseByte(uint8_t *Data, size_t size, size_t MaxSize, +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, + FuzzerRandomBase &Rand); +size_t Mutate_ChangeByte(uint8_t *Data, size_t Size, size_t MaxSize, + FuzzerRandomBase &Rand); +size_t Mutate_ChangeBit(uint8_t *Data, size_t Size, size_t MaxSize, + FuzzerRandomBase &Rand); size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize, FuzzerRandomBase &Rand); diff --git a/lib/Fuzzer/FuzzerMutate.cpp b/lib/Fuzzer/FuzzerMutate.cpp index eec6475f9b8..fc3176299c9 100644 --- a/lib/Fuzzer/FuzzerMutate.cpp +++ b/lib/Fuzzer/FuzzerMutate.cpp @@ -43,6 +43,30 @@ size_t Mutate_EraseByte(uint8_t *Data, size_t Size, size_t MaxSize, return Size - 1; } +size_t Mutate_InsertByte(uint8_t *Data, size_t Size, size_t MaxSize, + FuzzerRandomBase &Rand) { + if (Size == MaxSize) return Size; + size_t Idx = Rand(Size + 1); + // Insert new value at Data[Idx]. + memmove(Data + Idx + 1, Data + Idx, Size - Idx); + Data[Idx] = RandCh(Rand); + return Size + 1; +} + +size_t Mutate_ChangeByte(uint8_t *Data, size_t Size, size_t MaxSize, + FuzzerRandomBase &Rand) { + size_t Idx = Rand(Size); + Data[Idx] = RandCh(Rand); + return Size; +} + +size_t Mutate_ChangeBit(uint8_t *Data, size_t Size, size_t MaxSize, + FuzzerRandomBase &Rand) { + size_t Idx = Rand(Size); + Data[Idx] = FlipRandomBit(Data[Idx], Rand); + return Size; +} + // Mutates Data in place, returns new size. size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize, FuzzerRandomBase &Rand) { @@ -54,20 +78,11 @@ size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize, return MaxSize; } assert(Size > 0); - size_t Idx = Rand(Size); - switch (Rand(3)) { + switch (Rand(4)) { case 0: Size = Mutate_EraseByte(Data, Size, MaxSize, Rand); break; - case 1: - if (Size < MaxSize) { - // Insert new value at Data[Idx]. - memmove(Data + Idx + 1, Data + Idx, Size - Idx); - Data[Idx] = RandCh(Rand); - } - Data[Idx] = RandCh(Rand); - break; - case 2: - Data[Idx] = FlipRandomBit(Data[Idx], 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; } assert(Size > 0); return Size; diff --git a/lib/Fuzzer/test/FuzzerUnittest.cpp b/lib/Fuzzer/test/FuzzerUnittest.cpp index a159e411404..a3e6a136b27 100644 --- a/lib/Fuzzer/test/FuzzerUnittest.cpp +++ b/lib/Fuzzer/test/FuzzerUnittest.cpp @@ -90,19 +90,105 @@ void TestEraseByte(Mutator M, int NumIter) { int FoundMask = 0; for (int i = 0; i < NumIter; i++) { uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; - size_t NewSize = Mutate_EraseByte(T, sizeof(T), sizeof(T), Rand); - EXPECT_EQ(7UL, NewSize); - if (!memcmp(REM0, T, 7)) FoundMask |= 1 << 0; - if (!memcmp(REM1, T, 7)) FoundMask |= 1 << 1; - if (!memcmp(REM2, T, 7)) FoundMask |= 1 << 2; - if (!memcmp(REM3, T, 7)) FoundMask |= 1 << 3; - if (!memcmp(REM4, T, 7)) FoundMask |= 1 << 4; - if (!memcmp(REM5, T, 7)) FoundMask |= 1 << 5; - if (!memcmp(REM6, T, 7)) FoundMask |= 1 << 6; - if (!memcmp(REM7, T, 7)) FoundMask |= 1 << 7; + size_t NewSize = M(T, sizeof(T), sizeof(T), Rand); + if (NewSize == 7 && !memcmp(REM0, T, 7)) FoundMask |= 1 << 0; + if (NewSize == 7 && !memcmp(REM1, T, 7)) FoundMask |= 1 << 1; + if (NewSize == 7 && !memcmp(REM2, T, 7)) FoundMask |= 1 << 2; + if (NewSize == 7 && !memcmp(REM3, T, 7)) FoundMask |= 1 << 3; + if (NewSize == 7 && !memcmp(REM4, T, 7)) FoundMask |= 1 << 4; + if (NewSize == 7 && !memcmp(REM5, T, 7)) FoundMask |= 1 << 5; + if (NewSize == 7 && !memcmp(REM6, T, 7)) FoundMask |= 1 << 6; + if (NewSize == 7 && !memcmp(REM7, T, 7)) FoundMask |= 1 << 7; } EXPECT_EQ(FoundMask, 255); } -TEST(FuzzerMutate, EraseByte1) { TestEraseByte(Mutate_EraseByte, 50); } -TEST(FuzzerMutate, EraseByte2) { TestEraseByte(Mutate, 100); } +TEST(FuzzerMutate, EraseByte1) { TestEraseByte(Mutate_EraseByte, 100); } +TEST(FuzzerMutate, EraseByte2) { TestEraseByte(Mutate, 1000); } + +void TestInsertByte(Mutator M, int NumIter) { + FuzzerRandomLibc Rand(0); + int FoundMask = 0; + uint8_t INS0[8] = {0xF1, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + uint8_t INS1[8] = {0x00, 0xF2, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + uint8_t INS2[8] = {0x00, 0x11, 0xF3, 0x22, 0x33, 0x44, 0x55, 0x66}; + uint8_t INS3[8] = {0x00, 0x11, 0x22, 0xF4, 0x33, 0x44, 0x55, 0x66}; + uint8_t INS4[8] = {0x00, 0x11, 0x22, 0x33, 0xF5, 0x44, 0x55, 0x66}; + uint8_t INS5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0xF6, 0x55, 0x66}; + uint8_t INS6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0xF7, 0x66}; + uint8_t INS7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xF8}; + for (int i = 0; i < NumIter; i++) { + uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + size_t NewSize = M(T, 7, 8, Rand); + if (NewSize == 8 && !memcmp(INS0, T, 8)) FoundMask |= 1 << 0; + if (NewSize == 8 && !memcmp(INS1, T, 8)) FoundMask |= 1 << 1; + if (NewSize == 8 && !memcmp(INS2, T, 8)) FoundMask |= 1 << 2; + if (NewSize == 8 && !memcmp(INS3, T, 8)) FoundMask |= 1 << 3; + if (NewSize == 8 && !memcmp(INS4, T, 8)) FoundMask |= 1 << 4; + if (NewSize == 8 && !memcmp(INS5, T, 8)) FoundMask |= 1 << 5; + if (NewSize == 8 && !memcmp(INS6, T, 8)) FoundMask |= 1 << 6; + if (NewSize == 8 && !memcmp(INS7, T, 8)) FoundMask |= 1 << 7; + } + EXPECT_EQ(FoundMask, 255); +} + +TEST(FuzzerMutate, InsertByte1) { TestInsertByte(Mutate_InsertByte, 1 << 15); } +TEST(FuzzerMutate, InsertByte2) { TestInsertByte(Mutate, 1 << 17); } + +void TestChangeByte(Mutator M, int NumIter) { + FuzzerRandomLibc Rand(0); + int FoundMask = 0; + uint8_t CH0[8] = {0xF0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + uint8_t CH1[8] = {0x00, 0xF1, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + uint8_t CH2[8] = {0x00, 0x11, 0xF2, 0x33, 0x44, 0x55, 0x66, 0x77}; + uint8_t CH3[8] = {0x00, 0x11, 0x22, 0xF3, 0x44, 0x55, 0x66, 0x77}; + uint8_t CH4[8] = {0x00, 0x11, 0x22, 0x33, 0xF4, 0x55, 0x66, 0x77}; + uint8_t CH5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0xF5, 0x66, 0x77}; + uint8_t CH6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0xF5, 0x77}; + uint8_t CH7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xF7}; + for (int i = 0; i < NumIter; i++) { + uint8_t T[9] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + size_t NewSize = M(T, 8, 9, Rand); + if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0; + if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1; + if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2; + if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3; + if (NewSize == 8 && !memcmp(CH4, T, 8)) FoundMask |= 1 << 4; + if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5; + if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6; + if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7; + } + EXPECT_EQ(FoundMask, 255); +} + +TEST(FuzzerMutate, ChangeByte1) { TestChangeByte(Mutate_ChangeByte, 1 << 15); } +TEST(FuzzerMutate, ChangeByte2) { TestChangeByte(Mutate, 1 << 17); } + +void TestChangeBit(Mutator M, int NumIter) { + FuzzerRandomLibc Rand(0); + int FoundMask = 0; + uint8_t CH0[8] = {0x01, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + uint8_t CH1[8] = {0x00, 0x13, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + uint8_t CH2[8] = {0x00, 0x11, 0x02, 0x33, 0x44, 0x55, 0x66, 0x77}; + uint8_t CH3[8] = {0x00, 0x11, 0x22, 0x37, 0x44, 0x55, 0x66, 0x77}; + uint8_t CH4[8] = {0x00, 0x11, 0x22, 0x33, 0x54, 0x55, 0x66, 0x77}; + uint8_t CH5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x54, 0x66, 0x77}; + uint8_t CH6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x76, 0x77}; + uint8_t CH7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xF7}; + for (int i = 0; i < NumIter; i++) { + uint8_t T[9] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + size_t NewSize = M(T, 8, 9, Rand); + if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0; + if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1; + if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2; + if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3; + if (NewSize == 8 && !memcmp(CH4, T, 8)) FoundMask |= 1 << 4; + if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5; + if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6; + if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7; + } + EXPECT_EQ(FoundMask, 255); +} + +TEST(FuzzerMutate, ChangeBit1) { TestChangeBit(Mutate_ChangeBit, 1 << 16); } +TEST(FuzzerMutate, ChangeBit2) { TestChangeBit(Mutate, 1 << 18); }