[llvm] r278687 - [libFuzzer] add InsertRepeatedBytes and EraseBytes.
Kostya Serebryany via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 15 10:48:28 PDT 2016
Author: kcc
Date: Mon Aug 15 12:48:28 2016
New Revision: 278687
URL: http://llvm.org/viewvc/llvm-project?rev=278687&view=rev
Log:
[libFuzzer] add InsertRepeatedBytes and EraseBytes.
New mutation: InsertRepeatedBytes.
Updated mutation: EraseByte => EraseBytes.
This helps https://github.com/google/sanitizers/issues/710
where libFuzzer was not able to find a known bug.
Now it finds it in minutes.
Hopefully, the change is general enough to help other targets.
Added:
llvm/trunk/lib/Fuzzer/test/RepeatedBytesTest.cpp
llvm/trunk/lib/Fuzzer/test/repeated-bytes.test
Modified:
llvm/trunk/lib/Fuzzer/FuzzerInternal.h
llvm/trunk/lib/Fuzzer/FuzzerMutate.cpp
llvm/trunk/lib/Fuzzer/test/CMakeLists.txt
llvm/trunk/lib/Fuzzer/test/FuzzerUnittest.cpp
llvm/trunk/lib/Fuzzer/test/StrcmpTest.cpp
llvm/trunk/lib/Fuzzer/test/fuzzer-traces.test
Modified: llvm/trunk/lib/Fuzzer/FuzzerInternal.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerInternal.h?rev=278687&r1=278686&r2=278687&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerInternal.h (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerInternal.h Mon Aug 15 12:48:28 2016
@@ -255,10 +255,12 @@ public:
size_t Mutate_CustomCrossOver(uint8_t *Data, size_t Size, size_t MaxSize);
/// Mutates data by shuffling bytes.
size_t Mutate_ShuffleBytes(uint8_t *Data, size_t Size, size_t MaxSize);
- /// Mutates data by erasing a byte.
- size_t Mutate_EraseByte(uint8_t *Data, size_t Size, size_t MaxSize);
+ /// Mutates data by erasing bytes.
+ size_t Mutate_EraseBytes(uint8_t *Data, size_t Size, size_t MaxSize);
/// Mutates data by inserting a byte.
size_t Mutate_InsertByte(uint8_t *Data, size_t Size, size_t MaxSize);
+ /// Mutates data by inserting several repeated bytes.
+ size_t Mutate_InsertRepeatedBytes(uint8_t *Data, size_t Size, size_t MaxSize);
/// Mutates data by chanding one byte.
size_t Mutate_ChangeByte(uint8_t *Data, size_t Size, size_t MaxSize);
/// Mutates data by chanding one bit.
Modified: llvm/trunk/lib/Fuzzer/FuzzerMutate.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerMutate.cpp?rev=278687&r1=278686&r2=278687&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerMutate.cpp (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerMutate.cpp Mon Aug 15 12:48:28 2016
@@ -24,8 +24,10 @@ MutationDispatcher::MutationDispatcher(R
DefaultMutators.insert(
DefaultMutators.begin(),
{
- {&MutationDispatcher::Mutate_EraseByte, "EraseByte"},
+ {&MutationDispatcher::Mutate_EraseBytes, "EraseBytes"},
{&MutationDispatcher::Mutate_InsertByte, "InsertByte"},
+ {&MutationDispatcher::Mutate_InsertRepeatedBytes,
+ "InsertRepeatedBytes"},
{&MutationDispatcher::Mutate_ChangeByte, "ChangeByte"},
{&MutationDispatcher::Mutate_ChangeBit, "ChangeBit"},
{&MutationDispatcher::Mutate_ShuffleBytes, "ShuffleBytes"},
@@ -103,14 +105,17 @@ size_t MutationDispatcher::Mutate_Shuffl
return Size;
}
-size_t MutationDispatcher::Mutate_EraseByte(uint8_t *Data, size_t Size,
- size_t MaxSize) {
+size_t MutationDispatcher::Mutate_EraseBytes(uint8_t *Data, size_t Size,
+ size_t MaxSize) {
assert(Size);
if (Size == 1) return 0;
- size_t Idx = Rand(Size);
- // Erase Data[Idx].
- memmove(Data + Idx, Data + Idx + 1, Size - Idx - 1);
- return Size - 1;
+ size_t N = Rand(Size / 2) + 1;
+ assert(N < Size);
+ size_t Idx = Rand(Size - N + 1);
+ // Erase Data[Idx:Idx+N].
+ memmove(Data + Idx, Data + Idx + N, Size - Idx - N);
+ // Printf("Erase: %zd %zd => %zd; Idx %zd\n", N, Size, Size - N, Idx);
+ return Size - N;
}
size_t MutationDispatcher::Mutate_InsertByte(uint8_t *Data, size_t Size,
@@ -123,6 +128,23 @@ size_t MutationDispatcher::Mutate_Insert
return Size + 1;
}
+size_t MutationDispatcher::Mutate_InsertRepeatedBytes(uint8_t *Data,
+ size_t Size,
+ size_t MaxSize) {
+ const size_t kMinBytesToInsert = 3;
+ if (Size + kMinBytesToInsert >= MaxSize) return 0;
+ size_t MaxBytesToInsert = std::min(MaxSize - Size, (size_t)128);
+ size_t N = Rand(MaxBytesToInsert - kMinBytesToInsert + 1) + kMinBytesToInsert;
+ assert(Size + N <= MaxSize && N);
+ size_t Idx = Rand(Size + 1);
+ // Insert new values at Data[Idx].
+ memmove(Data + Idx + N, Data + Idx, Size - Idx);
+ uint8_t Byte = RandCh(Rand);
+ for (size_t i = 0; i < N; i++)
+ Data[Idx + i] = Byte;
+ return Size + N;
+}
+
size_t MutationDispatcher::Mutate_ChangeByte(uint8_t *Data, size_t Size,
size_t MaxSize) {
size_t Idx = Rand(Size);
Modified: llvm/trunk/lib/Fuzzer/test/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/test/CMakeLists.txt?rev=278687&r1=278686&r2=278687&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/test/CMakeLists.txt (original)
+++ llvm/trunk/lib/Fuzzer/test/CMakeLists.txt Mon Aug 15 12:48:28 2016
@@ -81,6 +81,7 @@ set(Tests
OneHugeAllocTest
OutOfMemoryTest
RepeatedMemcmp
+ RepeatedBytesTest
SimpleCmpTest
SimpleDictionaryTest
SimpleFnAdapterTest
Modified: llvm/trunk/lib/Fuzzer/test/FuzzerUnittest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/test/FuzzerUnittest.cpp?rev=278687&r1=278686&r2=278687&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/test/FuzzerUnittest.cpp (original)
+++ llvm/trunk/lib/Fuzzer/test/FuzzerUnittest.cpp Mon Aug 15 12:48:28 2016
@@ -88,7 +88,7 @@ TEST(Fuzzer, Hash) {
typedef size_t (MutationDispatcher::*Mutator)(uint8_t *Data, size_t Size,
size_t MaxSize);
-void TestEraseByte(Mutator M, int NumIter) {
+void TestEraseBytes(Mutator M, int NumIter) {
std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
fuzzer::EF = t.get();
uint8_t REM0[8] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
@@ -99,6 +99,16 @@ void TestEraseByte(Mutator M, int NumIte
uint8_t REM5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x66, 0x77};
uint8_t REM6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x77};
uint8_t REM7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
+
+ uint8_t REM8[6] = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
+ uint8_t REM9[6] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55};
+ uint8_t REM10[6] = {0x00, 0x11, 0x22, 0x55, 0x66, 0x77};
+
+ uint8_t REM11[5] = {0x33, 0x44, 0x55, 0x66, 0x77};
+ uint8_t REM12[5] = {0x00, 0x11, 0x22, 0x33, 0x44};
+ uint8_t REM13[5] = {0x00, 0x44, 0x55, 0x66, 0x77};
+
+
Random Rand(0);
MutationDispatcher MD(Rand, {});
int FoundMask = 0;
@@ -113,15 +123,23 @@ void TestEraseByte(Mutator M, int NumIte
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;
+
+ if (NewSize == 6 && !memcmp(REM8, T, 6)) FoundMask |= 1 << 8;
+ if (NewSize == 6 && !memcmp(REM9, T, 6)) FoundMask |= 1 << 9;
+ if (NewSize == 6 && !memcmp(REM10, T, 6)) FoundMask |= 1 << 10;
+
+ if (NewSize == 5 && !memcmp(REM11, T, 5)) FoundMask |= 1 << 11;
+ if (NewSize == 5 && !memcmp(REM12, T, 5)) FoundMask |= 1 << 12;
+ if (NewSize == 5 && !memcmp(REM13, T, 5)) FoundMask |= 1 << 13;
}
- EXPECT_EQ(FoundMask, 255);
+ EXPECT_EQ(FoundMask, (1 << 14) - 1);
}
-TEST(FuzzerMutate, EraseByte1) {
- TestEraseByte(&MutationDispatcher::Mutate_EraseByte, 100);
+TEST(FuzzerMutate, EraseBytes1) {
+ TestEraseBytes(&MutationDispatcher::Mutate_EraseBytes, 200);
}
-TEST(FuzzerMutate, EraseByte2) {
- TestEraseByte(&MutationDispatcher::Mutate, 1000);
+TEST(FuzzerMutate, EraseBytes2) {
+ TestEraseBytes(&MutationDispatcher::Mutate, 2000);
}
void TestInsertByte(Mutator M, int NumIter) {
@@ -160,6 +178,50 @@ TEST(FuzzerMutate, InsertByte2) {
TestInsertByte(&MutationDispatcher::Mutate, 1 << 17);
}
+void TestInsertRepeatedBytes(Mutator M, int NumIter) {
+ std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
+ fuzzer::EF = t.get();
+ Random Rand(0);
+ MutationDispatcher MD(Rand, {});
+ int FoundMask = 0;
+ uint8_t INS0[7] = {0x00, 0x11, 0x22, 0x33, 'a', 'a', 'a'};
+ uint8_t INS1[7] = {0x00, 0x11, 0x22, 'a', 'a', 'a', 0x33};
+ uint8_t INS2[7] = {0x00, 0x11, 'a', 'a', 'a', 0x22, 0x33};
+ uint8_t INS3[7] = {0x00, 'a', 'a', 'a', 0x11, 0x22, 0x33};
+ uint8_t INS4[7] = {'a', 'a', 'a', 0x00, 0x11, 0x22, 0x33};
+
+ uint8_t INS5[8] = {0x00, 0x11, 0x22, 0x33, 'b', 'b', 'b', 'b'};
+ uint8_t INS6[8] = {0x00, 0x11, 0x22, 'b', 'b', 'b', 'b', 0x33};
+ uint8_t INS7[8] = {0x00, 0x11, 'b', 'b', 'b', 'b', 0x22, 0x33};
+ uint8_t INS8[8] = {0x00, 'b', 'b', 'b', 'b', 0x11, 0x22, 0x33};
+ uint8_t INS9[8] = {'b', 'b', 'b', 'b', 0x00, 0x11, 0x22, 0x33};
+
+ for (int i = 0; i < NumIter; i++) {
+ uint8_t T[8] = {0x00, 0x11, 0x22, 0x33};
+ size_t NewSize = (MD.*M)(T, 4, 8);
+ if (NewSize == 7 && !memcmp(INS0, T, 7)) FoundMask |= 1 << 0;
+ if (NewSize == 7 && !memcmp(INS1, T, 7)) FoundMask |= 1 << 1;
+ if (NewSize == 7 && !memcmp(INS2, T, 7)) FoundMask |= 1 << 2;
+ if (NewSize == 7 && !memcmp(INS3, T, 7)) FoundMask |= 1 << 3;
+ if (NewSize == 7 && !memcmp(INS4, T, 7)) 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;
+ if (NewSize == 8 && !memcmp(INS8, T, 8)) FoundMask |= 1 << 8;
+ if (NewSize == 8 && !memcmp(INS9, T, 8)) FoundMask |= 1 << 9;
+
+ }
+ EXPECT_EQ(FoundMask, (1 << 10) - 1);
+}
+
+TEST(FuzzerMutate, InsertRepeatedBytes1) {
+ TestInsertRepeatedBytes(&MutationDispatcher::Mutate_InsertRepeatedBytes, 10000);
+}
+TEST(FuzzerMutate, InsertRepeatedBytes2) {
+ TestInsertRepeatedBytes(&MutationDispatcher::Mutate, 200000);
+}
+
void TestChangeByte(Mutator M, int NumIter) {
std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
fuzzer::EF = t.get();
Added: llvm/trunk/lib/Fuzzer/test/RepeatedBytesTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/test/RepeatedBytesTest.cpp?rev=278687&view=auto
==============================================================================
--- llvm/trunk/lib/Fuzzer/test/RepeatedBytesTest.cpp (added)
+++ llvm/trunk/lib/Fuzzer/test/RepeatedBytesTest.cpp Mon Aug 15 12:48:28 2016
@@ -0,0 +1,29 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find repeated bytes.
+#include <assert.h>
+#include <cstdint>
+#include <cstdlib>
+#include <cstddef>
+#include <iostream>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ assert(Data);
+ // Looking for AAAAAAAAAAAAAAAAAAAAAA or some such.
+ size_t CurA = 0, MaxA = 0;
+ for (size_t i = 0; i < Size; i++) {
+ // Make sure there are no conditionals in the loop so that
+ // coverage can't help the fuzzer.
+ int EQ = Data[i] == 'A';
+ CurA = EQ * (CurA + 1);
+ int GT = CurA > MaxA;
+ MaxA = GT * CurA + (!GT) * MaxA;
+ }
+ if (MaxA >= 20) {
+ std::cout << "BINGO; Found the target (Max: " << MaxA << "), exiting\n";
+ exit(0);
+ }
+ return 0;
+}
+
Modified: llvm/trunk/lib/Fuzzer/test/StrcmpTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/test/StrcmpTest.cpp?rev=278687&r1=278686&r2=278687&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/test/StrcmpTest.cpp (original)
+++ llvm/trunk/lib/Fuzzer/test/StrcmpTest.cpp Mon Aug 15 12:48:28 2016
@@ -20,9 +20,9 @@ bool Eq(const uint8_t *Data, size_t Size
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
- if (Eq(Data, Size, "AAA") &&
- Size >= 3 && Eq(Data + 3, Size - 3, "BBBB") &&
- Size >= 7 && Eq(Data + 7, Size - 7, "CCCCCC") &&
+ if (Eq(Data, Size, "ABC") &&
+ Size >= 3 && Eq(Data + 3, Size - 3, "QWER") &&
+ Size >= 7 && Eq(Data + 7, Size - 7, "ZXCVN") &&
Size >= 14 && Data[13] == 42
) {
fprintf(stderr, "BINGO\n");
Modified: llvm/trunk/lib/Fuzzer/test/fuzzer-traces.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/test/fuzzer-traces.test?rev=278687&r1=278686&r2=278687&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/test/fuzzer-traces.test (original)
+++ llvm/trunk/lib/Fuzzer/test/fuzzer-traces.test Mon Aug 15 12:48:28 2016
@@ -1,9 +1,10 @@
CHECK: BINGO
Done1000000: Done 1000000 runs in
+Done2000000: Done 2000000 runs in
RUN: not LLVMFuzzer-SimpleCmpTest -use_traces=1 -seed=1 -runs=10000001 2>&1 | FileCheck %s
RUN: not LLVMFuzzer-SwitchTest -use_traces=1 -seed=6 -runs=1000002 2>&1 | FileCheck %s
RUN: LLVMFuzzer-SwitchTest -seed=7 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000
-RUN: not LLVMFuzzer-SimpleHashTest -use_traces=1 -seed=8 -runs=1000000 -max_len=16 2>&1 | FileCheck %s
-RUN: LLVMFuzzer-SimpleHashTest -seed=9 -runs=1000000 -max_len=16 2>&1 | FileCheck %s --check-prefix=Done1000000
+RUN: not LLVMFuzzer-SimpleHashTest -use_traces=1 -seed=8 -runs=2000000 -max_len=16 2>&1 | FileCheck %s
+RUN: LLVMFuzzer-SimpleHashTest -seed=9 -runs=2000000 -max_len=16 2>&1 | FileCheck %s --check-prefix=Done2000000
Added: llvm/trunk/lib/Fuzzer/test/repeated-bytes.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/test/repeated-bytes.test?rev=278687&view=auto
==============================================================================
--- llvm/trunk/lib/Fuzzer/test/repeated-bytes.test (added)
+++ llvm/trunk/lib/Fuzzer/test/repeated-bytes.test Mon Aug 15 12:48:28 2016
@@ -0,0 +1,2 @@
+CHECK: BINGO
+RUN: LLVMFuzzer-RepeatedBytesTest -runs=10000 2>&1 | FileCheck %s
More information about the llvm-commits
mailing list