summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorKostya Serebryany <kcc@google.com>2015-01-29 23:01:07 +0000
committerKostya Serebryany <kcc@google.com>2015-01-29 23:01:07 +0000
commit2c1b33b8976ca473c90fb1848ae0dc5d72597a96 (patch)
tree7b8474d40fd8363e3ed4534a9be696adf32f60ef /llvm/lib
parent11d943d32c35720db2aaf8496bf20496a917fd71 (diff)
downloadbcm5719-llvm-2c1b33b8976ca473c90fb1848ae0dc5d72597a96.tar.gz
bcm5719-llvm-2c1b33b8976ca473c90fb1848ae0dc5d72597a96.zip
[fuzzer] add -use_full_coverage_set=1 which solves FullCoverageSetTest. This does not scale very well yet, but might be a good start.
llvm-svn: 227507
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Fuzzer/CMakeLists.txt2
-rw-r--r--llvm/lib/Fuzzer/FuzzerFlags.def4
-rw-r--r--llvm/lib/Fuzzer/FuzzerInternal.h5
-rw-r--r--llvm/lib/Fuzzer/FuzzerLoop.cpp29
-rw-r--r--llvm/lib/Fuzzer/FuzzerMain.cpp1
-rw-r--r--llvm/lib/Fuzzer/test/CMakeLists.txt8
-rw-r--r--llvm/lib/Fuzzer/test/FullCoverageSetTest.cpp (renamed from llvm/lib/Fuzzer/test/ExactTest.cpp)2
-rw-r--r--llvm/lib/Fuzzer/test/fuzzer.test3
8 files changed, 52 insertions, 2 deletions
diff --git a/llvm/lib/Fuzzer/CMakeLists.txt b/llvm/lib/Fuzzer/CMakeLists.txt
index 2538375063c..499cf98a6b9 100644
--- a/llvm/lib/Fuzzer/CMakeLists.txt
+++ b/llvm/lib/Fuzzer/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Disable the coverage instrumentation for the fuzzer itself.
+set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2 -fsanitize-coverage=0")
if( LLVM_USE_SANITIZE_COVERAGE )
add_library(LLVMFuzzer STATIC
EXCLUDE_FROM_ALL # Do not build if you are not building fuzzers.
diff --git a/llvm/lib/Fuzzer/FuzzerFlags.def b/llvm/lib/Fuzzer/FuzzerFlags.def
index e165ebdbf37..264c105950c 100644
--- a/llvm/lib/Fuzzer/FuzzerFlags.def
+++ b/llvm/lib/Fuzzer/FuzzerFlags.def
@@ -25,3 +25,7 @@ FUZZER_FLAG(int, help, 0, "Print help.")
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"
+ " coverage sets as opposed to maximizing the total coverage."
+ " This is potentially MUCH slower, but may discover more paths.")
diff --git a/llvm/lib/Fuzzer/FuzzerInternal.h b/llvm/lib/Fuzzer/FuzzerInternal.h
index c361ffba83a..45379711db4 100644
--- a/llvm/lib/Fuzzer/FuzzerInternal.h
+++ b/llvm/lib/Fuzzer/FuzzerInternal.h
@@ -14,6 +14,7 @@
#include <cstdlib>
#include <string>
#include <vector>
+#include <unordered_set>
namespace fuzzer {
typedef std::vector<uint8_t> Unit;
@@ -43,6 +44,7 @@ class Fuzzer {
bool DoCrossOver = true;
bool MutateDepth = 10;
bool ExitOnFirst = false;
+ bool UseFullCoverageSet = false;
std::string OutputCorpus;
};
Fuzzer(FuzzingOptions Options) : Options(Options) {
@@ -63,6 +65,8 @@ class Fuzzer {
private:
size_t MutateAndTestOne(Unit *U);
size_t RunOne(const Unit &U);
+ size_t RunOneMaximizeTotalCoverage(const Unit &U);
+ size_t RunOneMaximizeFullCoverageSet(const Unit &U);
void WriteToOutputCorpus(const Unit &U);
static void WriteToCrash(const Unit &U, const char *Prefix);
@@ -73,6 +77,7 @@ class Fuzzer {
size_t TotalNumberOfRuns = 0;
std::vector<Unit> Corpus;
+ std::unordered_set<uintptr_t> FullCoverageSets;
FuzzingOptions Options;
system_clock::time_point ProcessStartTime = system_clock::now();
static system_clock::time_point UnitStartTime;
diff --git a/llvm/lib/Fuzzer/FuzzerLoop.cpp b/llvm/lib/Fuzzer/FuzzerLoop.cpp
index dcfc965f6bf..f3dee7c7f46 100644
--- a/llvm/lib/Fuzzer/FuzzerLoop.cpp
+++ b/llvm/lib/Fuzzer/FuzzerLoop.cpp
@@ -76,6 +76,35 @@ void Fuzzer::ShuffleAndMinimize() {
size_t Fuzzer::RunOne(const Unit &U) {
UnitStartTime = system_clock::now();
TotalNumberOfRuns++;
+ if (Options.UseFullCoverageSet)
+ return RunOneMaximizeFullCoverageSet(U);
+ return RunOneMaximizeTotalCoverage(U);
+}
+
+static uintptr_t HashOfArrayOfPCs(uintptr_t *PCs, uintptr_t NumPCs) {
+ uintptr_t Res = 0;
+ for (uintptr_t i = 0; i < NumPCs; i++) {
+ Res = (Res + PCs[i]) * 7;
+ }
+ return Res;
+}
+
+// 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.
+// This produces tons of new units and as is it's only suitable for small tests,
+// e.g. test/FullCoverageSetTest.cpp. FIXME: make it scale.
+size_t Fuzzer::RunOneMaximizeFullCoverageSet(const Unit &U) {
+ __sanitizer_reset_coverage();
+ TestOneInput(U.data(), U.size());
+ uintptr_t *PCs;
+ uintptr_t NumPCs =__sanitizer_get_coverage_guards(&PCs);
+ if (FullCoverageSets.insert(HashOfArrayOfPCs(PCs, NumPCs)).second)
+ return FullCoverageSets.size();
+ return 0;
+}
+
+size_t Fuzzer::RunOneMaximizeTotalCoverage(const Unit &U) {
size_t OldCoverage = __sanitizer_get_total_unique_coverage();
TestOneInput(U.data(), U.size());
size_t NewCoverage = __sanitizer_get_total_unique_coverage();
diff --git a/llvm/lib/Fuzzer/FuzzerMain.cpp b/llvm/lib/Fuzzer/FuzzerMain.cpp
index 6031fc835b9..03e0566049d 100644
--- a/llvm/lib/Fuzzer/FuzzerMain.cpp
+++ b/llvm/lib/Fuzzer/FuzzerMain.cpp
@@ -117,6 +117,7 @@ int main(int argc, char **argv) {
Options.DoCrossOver = Flags.cross_over;
Options.MutateDepth = Flags.mutate_depth;
Options.ExitOnFirst = Flags.exit_on_first;
+ Options.UseFullCoverageSet = Flags.use_full_coverage_set;
if (!inputs.empty())
Options.OutputCorpus = inputs[0];
Fuzzer F(Options);
diff --git a/llvm/lib/Fuzzer/test/CMakeLists.txt b/llvm/lib/Fuzzer/test/CMakeLists.txt
index 0c2118f31b0..17afd92c3b4 100644
--- a/llvm/lib/Fuzzer/test/CMakeLists.txt
+++ b/llvm/lib/Fuzzer/test/CMakeLists.txt
@@ -1,5 +1,11 @@
+# Build all these tests with -O0, otherwise optimizations may merge some
+# basic blocks and we'll fail to discover the targets.
+# Also enable the coverage instrumentation back (it is disabled
+# for the Fuzzer lib)
+set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O0 -fsanitize-coverage=4")
+
set(Tests
- ExactTest
+ FullCoverageSetTest
InfiniteTest
NullDerefTest
SimpleTest
diff --git a/llvm/lib/Fuzzer/test/ExactTest.cpp b/llvm/lib/Fuzzer/test/FullCoverageSetTest.cpp
index bbfed3c1eb0..d4f8c115abc 100644
--- a/llvm/lib/Fuzzer/test/ExactTest.cpp
+++ b/llvm/lib/Fuzzer/test/FullCoverageSetTest.cpp
@@ -14,7 +14,7 @@ extern "C" void TestOneInput(const uint8_t *Data, size_t Size) {
if (Size > 5 && Data[5] == 'R') bits |= 32;
if (bits == 63) {
std::cerr << "BINGO!\n";
- abort();
+ exit(1);
}
}
diff --git a/llvm/lib/Fuzzer/test/fuzzer.test b/llvm/lib/Fuzzer/test/fuzzer.test
index 5f013109f62..51b42d67824 100644
--- a/llvm/lib/Fuzzer/test/fuzzer.test
+++ b/llvm/lib/Fuzzer/test/fuzzer.test
@@ -11,3 +11,6 @@ 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
+FullCoverageSetTest: BINGO
OpenPOWER on IntegriCloud