summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Fuzzer/FuzzerDriver.cpp1
-rw-r--r--llvm/lib/Fuzzer/FuzzerFlags.def4
-rw-r--r--llvm/lib/Fuzzer/FuzzerInternal.h3
-rw-r--r--llvm/lib/Fuzzer/FuzzerLoop.cpp25
-rw-r--r--llvm/lib/Fuzzer/test/CMakeLists.txt1
-rw-r--r--llvm/lib/Fuzzer/test/FourIndependentBranchesTest.cpp18
-rw-r--r--llvm/lib/Fuzzer/test/fuzzer.test5
7 files changed, 55 insertions, 2 deletions
diff --git a/llvm/lib/Fuzzer/FuzzerDriver.cpp b/llvm/lib/Fuzzer/FuzzerDriver.cpp
index 8a8659e5f2b..1746afd822d 100644
--- a/llvm/lib/Fuzzer/FuzzerDriver.cpp
+++ b/llvm/lib/Fuzzer/FuzzerDriver.cpp
@@ -159,6 +159,7 @@ int FuzzerDriver(int argc, char **argv, UserCallback Callback) {
Options.MutateDepth = Flags.mutate_depth;
Options.ExitOnFirst = Flags.exit_on_first;
Options.UseFullCoverageSet = Flags.use_full_coverage_set;
+ Options.UseCoveragePairs = Flags.use_coverage_pairs;
Options.PreferSmallDuringInitialShuffle =
Flags.prefer_small_during_initial_shuffle;
if (Flags.runs >= 0)
diff --git a/llvm/lib/Fuzzer/FuzzerFlags.def b/llvm/lib/Fuzzer/FuzzerFlags.def
index 754d02e0153..068f2451b6b 100644
--- a/llvm/lib/Fuzzer/FuzzerFlags.def
+++ b/llvm/lib/Fuzzer/FuzzerFlags.def
@@ -33,9 +33,11 @@ FUZZER_FLAG(
int, save_minimized_corpus, 0,
"If 1, the minimized corpus is saved into the first input directory")
FUZZER_FLAG(int, use_full_coverage_set, 0,
- "Maximize the number of different full"
+ "Experimental: Maximize the number of different full"
" coverage sets as opposed to maximizing the total coverage."
" This is potentially MUCH slower, but may discover more paths.")
+FUZZER_FLAG(int, use_coverage_pairs, 0,
+ "Experimental: Maximize the number of different coverage pairs.")
FUZZER_FLAG(int, jobs, 0, "Number of jobs to run. If jobs >= 1 we spawn"
" this number of jobs in separate worker processes"
" with stdout/stderr redirected to fuzz-JOB.log.")
diff --git a/llvm/lib/Fuzzer/FuzzerInternal.h b/llvm/lib/Fuzzer/FuzzerInternal.h
index bc18c551f59..980b00ec17b 100644
--- a/llvm/lib/Fuzzer/FuzzerInternal.h
+++ b/llvm/lib/Fuzzer/FuzzerInternal.h
@@ -49,6 +49,7 @@ class Fuzzer {
int MutateDepth = 5;
bool ExitOnFirst = false;
bool UseFullCoverageSet = false;
+ bool UseCoveragePairs = false;
int PreferSmallDuringInitialShuffle = -1;
size_t MaxNumberOfRuns = ULONG_MAX;
std::string OutputCorpus;
@@ -81,6 +82,7 @@ class Fuzzer {
size_t RunOne(const Unit &U);
size_t RunOneMaximizeTotalCoverage(const Unit &U);
size_t RunOneMaximizeFullCoverageSet(const Unit &U);
+ size_t RunOneMaximizeCoveragePairs(const Unit &U);
void WriteToOutputCorpus(const Unit &U);
static void WriteToCrash(const Unit &U, const char *Prefix);
@@ -92,6 +94,7 @@ class Fuzzer {
std::vector<Unit> Corpus;
std::unordered_set<uintptr_t> FullCoverageSets;
+ std::unordered_set<uint64_t> CoveragePairs;
UserCallback Callback;
FuzzingOptions Options;
system_clock::time_point ProcessStartTime = system_clock::now();
diff --git a/llvm/lib/Fuzzer/FuzzerLoop.cpp b/llvm/lib/Fuzzer/FuzzerLoop.cpp
index 1529d06b1cc..70b63eb618a 100644
--- a/llvm/lib/Fuzzer/FuzzerLoop.cpp
+++ b/llvm/lib/Fuzzer/FuzzerLoop.cpp
@@ -86,6 +86,8 @@ size_t Fuzzer::RunOne(const Unit &U) {
TotalNumberOfRuns++;
if (Options.UseFullCoverageSet)
return RunOneMaximizeFullCoverageSet(U);
+ if (Options.UseCoveragePairs)
+ return RunOneMaximizeCoveragePairs(U);
return RunOneMaximizeTotalCoverage(U);
}
@@ -97,6 +99,29 @@ static uintptr_t HashOfArrayOfPCs(uintptr_t *PCs, uintptr_t NumPCs) {
return Res;
}
+// Experimental. Does not yet scale.
+// Fuly reset the current coverage state, run a single unit,
+// collect all coverage pairs and return non-zero if a new pair is observed.
+size_t Fuzzer::RunOneMaximizeCoveragePairs(const Unit &U) {
+ __sanitizer_reset_coverage();
+ Callback(U.data(), U.size());
+ uintptr_t *PCs;
+ uintptr_t NumPCs = __sanitizer_get_coverage_guards(&PCs);
+ bool HasNewPairs = false;
+ for (uintptr_t i = 0; i < NumPCs; i++) {
+ if (!PCs[i]) continue;
+ for (uintptr_t j = 0; j < NumPCs; j++) {
+ if (!PCs[j]) continue;
+ uint64_t Pair = (i << 32) | j;
+ HasNewPairs |= CoveragePairs.insert(Pair).second;
+ }
+ }
+ if (HasNewPairs)
+ return CoveragePairs.size();
+ return 0;
+}
+
+// Experimental.
// Fuly reset the current coverage state, run a single unit,
// compute a hash function from the full coverage set,
// return non-zero if the hash value is new.
diff --git a/llvm/lib/Fuzzer/test/CMakeLists.txt b/llvm/lib/Fuzzer/test/CMakeLists.txt
index eb3c1eee7c1..bed9cd89ec9 100644
--- a/llvm/lib/Fuzzer/test/CMakeLists.txt
+++ b/llvm/lib/Fuzzer/test/CMakeLists.txt
@@ -5,6 +5,7 @@
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O0 -fsanitize-coverage=4")
set(Tests
+ FourIndependentBranchesTest
FullCoverageSetTest
InfiniteTest
NullDerefTest
diff --git a/llvm/lib/Fuzzer/test/FourIndependentBranchesTest.cpp b/llvm/lib/Fuzzer/test/FourIndependentBranchesTest.cpp
new file mode 100644
index 00000000000..171668bf764
--- /dev/null
+++ b/llvm/lib/Fuzzer/test/FourIndependentBranchesTest.cpp
@@ -0,0 +1,18 @@
+// Simple test for a fuzzer. The fuzzer must find the string "FUZZ".
+#include <cstdint>
+#include <cstdlib>
+#include <cstddef>
+#include <iostream>
+
+extern "C" void TestOneInput(const uint8_t *Data, size_t Size) {
+ int bits = 0;
+ if (Size > 0 && Data[0] == 'F') bits |= 1;
+ if (Size > 1 && Data[1] == 'U') bits |= 2;
+ if (Size > 2 && Data[2] == 'Z') bits |= 4;
+ if (Size > 3 && Data[3] == 'Z') bits |= 8;
+ if (bits == 15) {
+ std::cerr << "BINGO!\n";
+ exit(1);
+ }
+}
+
diff --git a/llvm/lib/Fuzzer/test/fuzzer.test b/llvm/lib/Fuzzer/test/fuzzer.test
index 51b42d67824..1e42e7249da 100644
--- a/llvm/lib/Fuzzer/test/fuzzer.test
+++ b/llvm/lib/Fuzzer/test/fuzzer.test
@@ -12,5 +12,8 @@ TimeoutTest: CRASHED; file written to timeout
RUN: not ./LLVMFuzzer-NullDerefTest 2>&1 | FileCheck %s --check-prefix=NullDerefTest
NullDerefTest: CRASHED; file written to crash-
-RUN: not ./LLVMFuzzer-FullCoverageSetTest -timeout=15 -mutate_depth=2 -use_full_coverage_set=1 2>&1 | FileCheck %s --check-prefix=FullCoverageSetTest
+RUN: not ./LLVMFuzzer-FullCoverageSetTest -timeout=15 -seed=1 -mutate_depth=2 -use_full_coverage_set=1 2>&1 | FileCheck %s --check-prefix=FullCoverageSetTest
FullCoverageSetTest: BINGO
+
+RUN: not ./LLVMFuzzer-FourIndependentBranchesTest -timeout=15 -seed=1 -use_coverage_pairs=1 2>&1 | FileCheck %s --check-prefix=FourIndependentBranchesTest
+FourIndependentBranchesTest: BINGO
OpenPOWER on IntegriCloud