summaryrefslogtreecommitdiffstats
path: root/compiler-rt/test/fuzzer/dataflow.test
blob: 5f728a8fbe1747038c04bdc66a08d7579d1fb106 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# Tests the data flow tracer.
REQUIRES: linux, x86_64

# Build the tracer and the test.
RUN: %no_fuzzer_cpp_compiler -c -fno-sanitize=all -fsanitize=dataflow  %S/../../lib/fuzzer/dataflow/DataFlow.cpp -o  %t-DataFlow.o
RUN: %no_fuzzer_cpp_compiler    -fno-sanitize=all -fsanitize=dataflow -fsanitize-coverage=trace-pc-guard,pc-table,bb,trace-cmp   %S/ThreeFunctionsTest.cpp     %t-DataFlow.o -o %t-ThreeFunctionsTestDF
RUN: %no_fuzzer_cpp_compiler    -fno-sanitize=all -fsanitize=dataflow -fsanitize-coverage=trace-pc-guard,pc-table,bb,trace-cmp   %S/ExplodeDFSanLabelsTest.cpp %t-DataFlow.o -o %t-ExplodeDFSanLabelsTestDF
RUN: %cpp_compiler %S/ThreeFunctionsTest.cpp -o %t-ThreeFunctionsTest

# 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
RUN: echo -n 1234567890123456 > %t/IN/1234567890123456

# This test assumes that the functions in ThreeFunctionsTestDF are instrumented
# in a specific order:
# LLVMFuzzerTestOneInput: F0
# Func1: F1
# Func2: F2

# ABC: No data is used, the only used label is 4 (corresponds to the size)
RUN:%t-ThreeFunctionsTestDF 0 3 %t/IN/ABC    | FileCheck %s --check-prefix=IN_ABC
IN_ABC: F0 0001
IN_ABC-NOT: F
IN_ABC-NEXT: C0
IN_ABC-NOT: C

# FUABC: First 3 bytes are checked, Func1/Func2 are not called.
RUN:%t-ThreeFunctionsTestDF 0 5 %t/IN/FUABC  | FileCheck %s --check-prefix=IN_FUABC
IN_FUABC: F0 111001
IN_FUABC-NOT: F
IN_FUABC-NEXT: C0
IN_FUABC-NOT: C

# FUZZR: 5 bytes are used (4 in one function, 5-th in the other), Func2 is not called.
RUN:%t-ThreeFunctionsTestDF 0 5 %t/IN/FUZZR  | FileCheck %s --check-prefix=IN_FUZZR
IN_FUZZR: F0 111101
IN_FUZZR: F1 000010
IN_FUZZR-NOT: F
IN_FUZZR: C0
IN_FUZZR: C1
IN_FUZZR-NOT: C

# FUZZM: 5 bytes are used, both Func1 and Func2 are called, Func2 depends only on size (label 6).
RUN:%t-ThreeFunctionsTestDF 0 5 %t/IN/FUZZM  | FileCheck %s --check-prefix=IN_FUZZM
IN_FUZZM: F0 111101
IN_FUZZM: F1 000010
IN_FUZZM: F2 000001
IN_FUZZM: C0
IN_FUZZM: C1
IN_FUZZM: C2

# FUZZMU: 6 bytes are used, both Func1 and Func2 are called, Func2 depends on byte 6 and size (label 7)
RUN:%t-ThreeFunctionsTestDF 0 6 %t/IN/FUZZMU  | FileCheck %s --check-prefix=IN_FUZZMU

# Test merge_data_flow
RUN:rm -f %t-merge-*
RUN:%t-ThreeFunctionsTestDF 0 2 %t/IN/FUZZMU > %t-merge-1
RUN:%t-ThreeFunctionsTestDF 2 4 %t/IN/FUZZMU > %t-merge-2
RUN:%t-ThreeFunctionsTestDF 4 6 %t/IN/FUZZMU > %t-merge-3
RUN:%libfuzzer_src/scripts/merge_data_flow.py  %t-merge-* | sort | FileCheck %s --check-prefix=IN_FUZZMU

# Test collect_data_flow
RUN: %libfuzzer_src/scripts/collect_data_flow.py %t-ThreeFunctionsTestDF %t/IN/FUZZMU | sort | FileCheck %s --check-prefix=IN_FUZZMU

# Test libFuzzer's built in DFT collection.
RUN: rm -rf %t-DFT
RUN: %t-ThreeFunctionsTest  -collect_data_flow=%t-ThreeFunctionsTestDF -data_flow_trace=%t-DFT %t/IN/FUZZMU
RUN: cat %t-DFT/* | sort | FileCheck %s --check-prefix=IN_FUZZMU

IN_FUZZMU: F0 1111001
IN_FUZZMU: F1 0000100
IN_FUZZMU: F2 0000011

# A very simple test will cause DFSan to die with "out of labels"
RUN: not %t-ExplodeDFSanLabelsTestDF 0 16 %t/IN/1234567890123456 2>&1 | FileCheck %s --check-prefix=OUT_OF_LABELS
OUT_OF_LABELS: ==FATAL: DataFlowSanitizer: out of labels
# However we can run the same test piece by piece.
RUN: %t-ExplodeDFSanLabelsTestDF 0 2  %t/IN/1234567890123456
RUN: %t-ExplodeDFSanLabelsTestDF 2 4  %t/IN/1234567890123456
RUN: %t-ExplodeDFSanLabelsTestDF 4 6  %t/IN/1234567890123456
# Or we can use collect_data_flow
RUN: %libfuzzer_src/scripts/collect_data_flow.py %t-ExplodeDFSanLabelsTestDF %t/IN/1234567890123456

# Test libFuzzer's builtin collect_data_flow.
RUN: %t-ThreeFunctionsTest  -collect_data_flow=%t-ThreeFunctionsTestDF -data_flow_trace=%t-DFT %t/IN/1234567890123456

# Test that we can run collect_data_flow on the entire corpus dir
RUN: rm -rf %t/OUT
RUN: %libfuzzer_src/scripts/collect_data_flow.py %t-ThreeFunctionsTestDF %t/IN %t/OUT
RUN: %t-ThreeFunctionsTest -data_flow_trace=%t/OUT -runs=0 -focus_function=Func2 2>&1 | FileCheck %s --check-prefix=USE_DATA_FLOW_TRACE

RUN: rm -rf %t/OUT
RUN: %t-ThreeFunctionsTest  -collect_data_flow=%t-ThreeFunctionsTestDF -data_flow_trace=%t/OUT %t/IN
RUN: %t-ThreeFunctionsTest -data_flow_trace=%t/OUT -runs=0 -focus_function=Func2 2>&1 | FileCheck %s --check-prefix=USE_DATA_FLOW_TRACE


USE_DATA_FLOW_TRACE: INFO: DataFlowTrace: reading from {{.*}}/OUT
USE_DATA_FLOW_TRACE-DAG: ca8eefe2fd5d6b32028f355fafa3e739a6bf5edc => |000001|
USE_DATA_FLOW_TRACE-DAG: d28cb407e8e1a702c72d25473f0553d3ec172262 => |0000011|
USE_DATA_FLOW_TRACE: INFO: DataFlowTrace: 6 trace files, 3 functions, 2 traces with focus function
USE_DATA_FLOW_TRACE: INFO: Focus function is set to 'Func2'

# Test that we can run collect_data_flow on a long input (>2**16 bytes)
RUN: printf "%0.sA" {1..150001} > %t/IN/very_long_input
RUN: rm -rf %t/OUT
RUN: %libfuzzer_src/scripts/collect_data_flow.py %t-ThreeFunctionsTestDF %t/IN/very_long_input %t/OUT | FileCheck %s --check-prefix=COLLECT_TRACE_FOR_LONG_INPUT
RUN: rm -rf %t/OUT
RUN: %t-ThreeFunctionsTest  -collect_data_flow=%t-ThreeFunctionsTestDF -data_flow_trace=%t/OUT %t/IN/very_long_input 2>&1 | FileCheck %s --check-prefix=COLLECT_TRACE_FOR_LONG_INPUT
RUN: rm %t/IN/very_long_input
COLLECT_TRACE_FOR_LONG_INPUT: ******* Trying:{{[ ]+}}[0, 150001
COLLECT_TRACE_FOR_LONG_INPUT-DAG: ******* Trying:{{[ ]+}}[75000, 150001
COLLECT_TRACE_FOR_LONG_INPUT-DAG: ******* Trying:{{[ ]+}}[112500, 150001
COLLECT_TRACE_FOR_LONG_INPUT-DAG: ******* Success:{{[ ]+}}[{{[0123456789]+}}, 150001
COLLECT_TRACE_FOR_LONG_INPUT-DAG: ******* Success:{{[ ]+}}[0, {{[0123456789]+}}
OpenPOWER on IntegriCloud