summaryrefslogtreecommitdiff
path: root/test/fuzzer
diff options
context:
space:
mode:
authorKostya Serebryany <kcc@google.com>2018-05-10 19:59:01 +0000
committerKostya Serebryany <kcc@google.com>2018-05-10 19:59:01 +0000
commitfe2c72c59aa7f4afa45e3f65a5d16a374b6cce26 (patch)
tree243d0a550a8dd133adbbbbd3e645d02af2e57342 /test/fuzzer
parent35bf686a59e439af1b5087e2d093f2c69a86fca0 (diff)
[libFuzzer] Experimental data flow tracer for fuzz targets.
Summary: Experimental data flow tracer for fuzz targets. Allows to tell which bytes of the input affect which functions of the fuzz target. We previously attempted to use DFSan directly in the libFuzzer process, and that didn't work nicely. Now we will try to collect the data flow information for the seed corpus in a separate process (using this tracer), and then use it in the regular libFuzzer runs. Reviewers: morehouse, pcc, Dor1s Reviewed By: morehouse, Dor1s Subscribers: delcypher, #sanitizers, llvm-commits Differential Revision: https://reviews.llvm.org/D46666 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@332029 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/fuzzer')
-rw-r--r--test/fuzzer/ThreeFunctionsTest.cpp34
-rw-r--r--test/fuzzer/dataflow.test76
2 files changed, 110 insertions, 0 deletions
diff --git a/test/fuzzer/ThreeFunctionsTest.cpp b/test/fuzzer/ThreeFunctionsTest.cpp
new file mode 100644
index 000000000..0ff682abc
--- /dev/null
+++ b/test/fuzzer/ThreeFunctionsTest.cpp
@@ -0,0 +1,34 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Find "FUZZME", the target has 3 different functions.
+#include <assert.h>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <cstdio>
+
+__attribute__((noinline))
+static bool Func1(const uint8_t *Data, size_t Size) {
+ // assumes Size >= 5, doesn't check it.
+ return Data[4] == 'M';
+}
+
+__attribute__((noinline))
+bool Func2(const uint8_t *Data, size_t Size) {
+ return Size >= 6 && Data[5] == 'E';
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size >= 5
+ && Data[0] == 'F'
+ && Data[1] == 'U'
+ && Data[2] == 'Z'
+ && Data[3] == 'Z'
+ && Func1(Data, Size)
+ && Func2(Data, Size)) {
+ fprintf(stderr, "BINGO\n");
+ abort();
+ }
+ return 0;
+}
diff --git a/test/fuzzer/dataflow.test b/test/fuzzer/dataflow.test
new file mode 100644
index 000000000..ba2d6e561
--- /dev/null
+++ b/test/fuzzer/dataflow.test
@@ -0,0 +1,76 @@
+# Tests the data flow tracer.
+REQUIRES: linux
+
+# Build the tracer and the test.
+RUN: %no_fuzzer_cpp_compiler -c -fno-sanitize=all -fsanitize=dataflow -fsanitize-coverage=trace-pc-guard,pc-table,func,trace-cmp %S/ThreeFunctionsTest.cpp -o %t-ThreeFunctionsTest.o
+RUN: %no_fuzzer_cpp_compiler -fno-sanitize=all -fsanitize=dataflow %t-ThreeFunctionsTest.o %S/../../lib/fuzzer/dataflow/DataFlow.cpp -o %t-ThreeFunctionsTestDF
+
+# Dump the function list.
+RUN: %t-ThreeFunctionsTestDF 2>&1 | FileCheck %s --check-prefix=FUNC_LIST
+FUNC_LIST-DAG: LLVMFuzzerTestOneInput
+FUNC_LIST-DAG: Func1
+FUNC_LIST-DAG: Func2
+
+# Prepare the inputs.
+RUN: rm -rf %t/IN
+RUN: mkdir -p %t/IN
+RUN: echo -n ABC > %t/IN/ABC
+RUN: echo -n FUABC > %t/IN/FUABC
+RUN: echo -n FUZZR > %t/IN/FUZZR
+RUN: echo -n FUZZM > %t/IN/FUZZM
+RUN: echo -n FUZZMU > %t/IN/FUZZMU
+
+# ABC: No data is used, the only used label is 4 (corresponds to the size)
+RUN:%t-ThreeFunctionsTestDF %t/IN/ABC | FileCheck %s --check-prefix=IN_ABC
+IN_ABC: LEN: 3
+IN_ABC: LABELS: 4
+IN_ABC: F{{[012]}} 4
+IN_ABC-NOT: F
+
+# FUABC: First 3 bytes are checked, Func1/Func2 are not called.
+RUN:%t-ThreeFunctionsTestDF %t/IN/FUABC | FileCheck %s --check-prefix=IN_FUABC
+IN_FUABC: LEN: 5
+IN_FUABC: LABELS:
+IN_FUABC: L{{.*}} 1
+IN_FUABC: L{{.*}} 2
+IN_FUABC: L{{.*}} 3
+IN_FUABC-NOT: L{{.*}} 4
+IN_FUABC: F{{[012]}}
+IN_FUABC-NOT: F
+
+# FUZZR: 5 bytes are used (4 in one function, 5-th in the other), Func2 is not called.
+RUN:%t-ThreeFunctionsTestDF %t/IN/FUZZR | FileCheck %s --check-prefix=IN_FUZZR
+IN_FUZZR: LEN: 5
+IN_FUZZR: LABELS:
+IN_FUZZR: L{{.*}} 1
+IN_FUZZR: L{{.*}} 2
+IN_FUZZR: L{{.*}} 3
+IN_FUZZR: L[[L0:[0-9]*]] 4
+IN_FUZZR-DAG: F{{[012]}} 5
+IN_FUZZR-DAG: F{{[012]}} [[L0]]
+IN_FUZZR-NOT: F
+
+# FUZZM: 5 bytes are used, both Func1 and Func2 are called, Func2 depends only on size (label 6).
+RUN:%t-ThreeFunctionsTestDF %t/IN/FUZZM | FileCheck %s --check-prefix=IN_FUZZM
+IN_FUZZM: LEN: 5
+IN_FUZZM: LABELS:
+IN_FUZZM: L{{.*}} 1
+IN_FUZZM: L{{.*}} 2
+IN_FUZZM: L{{.*}} 3
+IN_FUZZM: L{{.*}} 4
+IN_FUZZM-DAG: F{{[012]}} 6
+IN_FUZZM-DAG: F{{[012]}} 5
+IN_FUZZM-DAG: F
+
+# FUZZMU: 6 bytes are used, both Func1 and Func2 are called, Func2 depends on byte 6 and size (label 7)
+RUN:%t-ThreeFunctionsTestDF %t/IN/FUZZMU | FileCheck %s --check-prefix=IN_FUZZMU
+IN_FUZZMU: LEN: 6
+IN_FUZZMU: LABELS:
+IN_FUZZMU: L{{.*}} 1
+IN_FUZZMU: L{{.*}} 2
+IN_FUZZMU: L{{.*}} 3
+IN_FUZZMU: L{{.*}} 4
+IN_FUZZMU: L[[L2:[0-9]*]] 6 7
+IN_FUZZMU-DAG: F{{[012]}} 5
+IN_FUZZMU-DAG: F{{[012]}} [[L2]]
+IN_FUZZMU-DAG: F