1# Tests the data flow tracer.
2REQUIRES: linux, x86_64
3
4# Build the tracer and the test.
5RUN: %no_fuzzer_cpp_compiler -c -fno-sanitize=all -fsanitize=dataflow -mllvm -dfsan-fast-16-labels  %S/../../lib/fuzzer/dataflow/DataFlow.cpp -o  %t-DataFlow.o
6RUN: %no_fuzzer_cpp_compiler -c -fno-sanitize=all -fPIC                %S/../../lib/fuzzer/dataflow/DataFlowCallbacks.cpp -o  %t-DataFlowCallbacks.o
7RUN: %no_fuzzer_cpp_compiler    -fno-sanitize=all -fsanitize=dataflow -mllvm -dfsan-fast-16-labels -fsanitize-coverage=trace-pc-guard,pc-table,bb,trace-cmp   %S/ThreeFunctionsTest.cpp     %t-DataFlow*.o -o %t-ThreeFunctionsTestDF
8RUN: %no_fuzzer_cpp_compiler    -fno-sanitize=all -fsanitize=dataflow -mllvm -dfsan-fast-16-labels -fsanitize-coverage=trace-pc-guard,pc-table,bb,trace-cmp   %S/Labels20Test.cpp     %t-DataFlow*.o -o %t-Labels20TestDF
9RUN: %cpp_compiler %S/ThreeFunctionsTest.cpp -o %t-ThreeFunctionsTest
10
11# Dump the function list.
12RUN:  %t-ThreeFunctionsTestDF 2>&1 | FileCheck %s --check-prefix=FUNC_LIST
13FUNC_LIST-DAG: LLVMFuzzerTestOneInput
14FUNC_LIST-DAG: Func1
15FUNC_LIST-DAG: Func2
16
17# Prepare the inputs.
18RUN: rm -rf %t/IN %t/IN20
19RUN: mkdir -p %t/IN %t/IN20
20RUN: echo -n ABC    > %t/IN/ABC
21RUN: echo -n FUABC  > %t/IN/FUABC
22RUN: echo -n FUZZR  > %t/IN/FUZZR
23RUN: echo -n FUZZM  > %t/IN/FUZZM
24RUN: echo -n FUZZMU > %t/IN/FUZZMU
25RUN: echo -n 1234567890123456 > %t/IN/1234567890123456
26
27RUN: echo -n FUZZxxxxxxxxxxxxxxxx > %t/IN20/FUZZxxxxxxxxxxxxxxxx
28RUN: echo -n FUZZxxxxxxxxxxxxMxxx > %t/IN20/FUZZxxxxxxxxxxxxMxxx
29RUN: echo -n FUZxxxxxxxxxxxxxxxxx > %t/IN20/FUZxxxxxxxxxxxxxxxxx
30RUN: echo -n FUxxxxxxxxxxxxxxxxxx > %t/IN20/FUxxxxxxxxxxxxxxxxxx
31
32
33RUN: export DFSAN_OPTIONS=warn_unimplemented=0
34
35# This test assumes that the functions in ThreeFunctionsTestDF are instrumented
36# in a specific order:
37# LLVMFuzzerTestOneInput: F0
38# Func1: F1
39# Func2: F2
40
41# ABC: No data is used
42RUN:%t-ThreeFunctionsTestDF %t/IN/ABC    | FileCheck %s --check-prefix=IN_ABC
43IN_ABC-NOT: F0
44IN_ABC: C0
45IN_ABC-NOT: C
46
47# FUABC: First 3 bytes are checked, Func1/Func2 are not called.
48RUN:%t-ThreeFunctionsTestDF %t/IN/FUABC  | FileCheck %s --check-prefix=IN_FUABC
49IN_FUABC: F0 11100{{$}}
50IN_FUABC-NOT: F
51IN_FUABC-NEXT: C0
52IN_FUABC-NOT: C
53
54# FUZZR: 5 bytes are used (4 in one function, 5-th in the other), Func2 is not called.
55RUN:%t-ThreeFunctionsTestDF %t/IN/FUZZR  | FileCheck %s --check-prefix=IN_FUZZR
56IN_FUZZR: F0 11110
57IN_FUZZR: F1 00001
58IN_FUZZR-NOT: F
59IN_FUZZR: C0
60IN_FUZZR: C1
61IN_FUZZR-NOT: C
62
63# FUZZM: 5 bytes are used, both Func1 and Func2 are called, Func2 depends only on size.
64RUN:%t-ThreeFunctionsTestDF %t/IN/FUZZM  | FileCheck %s --check-prefix=IN_FUZZM
65IN_FUZZM: F0 11110
66IN_FUZZM: F1 00001
67IN_FUZZM-NOT: F2
68IN_FUZZM: C0
69IN_FUZZM: C1
70IN_FUZZM: C2
71
72# FUZZMU: 6 bytes are used, both Func1 and Func2 are called, Func2 depends on byte 6 and size.
73RUN:%t-ThreeFunctionsTestDF %t/IN/FUZZMU  | FileCheck %s --check-prefix=IN_FUZZMU
74
75
76# Test Labels20TestDF
77RUN:%t-Labels20TestDF %t/IN20/FUxxxxxxxxxxxxxxxxxx | FileCheck %s --check-prefix=L20_FU
78L20_FU: F0 11100000000000000000{{$}}
79L20_FU-NOT: F
80
81RUN:%t-Labels20TestDF %t/IN20/FUZxxxxxxxxxxxxxxxxx | FileCheck %s --check-prefix=L20_FUZ
82L20_FUZ: F0 11110000000000000000{{$}}
83L20_FUZ-NOT: F
84
85RUN:%t-Labels20TestDF %t/IN20/FUZZxxxxxxxxxxxxxxxx | FileCheck %s --check-prefix=L20_FUZZ
86L20_FUZZ: F0 11110000000000000000{{$}}
87L20_FUZZ-NEXT: F1 00000000000000001000{{$}}
88L20_FUZZ-NOT: F
89
90RUN:%t-Labels20TestDF %t/IN20/FUZZxxxxxxxxxxxxMxxx | FileCheck %s --check-prefix=L20_FUZZM
91L20_FUZZM: F0 11110000000000000000{{$}}
92L20_FUZZM-NEXT: F1 00000000000000001000{{$}}
93L20_FUZZM-NEXT: F2 00000000000000000001{{$}}
94L20_FUZZM-NOT: F
95
96# Test libFuzzer's built in DFT collection.
97RUN: rm -rf %t-DFT
98RUN: %t-ThreeFunctionsTest  -collect_data_flow=%t-ThreeFunctionsTestDF -data_flow_trace=%t-DFT %t/IN/FUZZMU
99RUN: cat %t-DFT/* | sort | FileCheck %s --check-prefix=IN_FUZZMU
100
101IN_FUZZMU: F0 111100
102IN_FUZZMU: F1 000010
103IN_FUZZMU: F2 000001
104
105# Test that we can run collect_data_flow on the entire corpus dir
106RUN: rm -rf %t/OUT
107RUN: %t-ThreeFunctionsTest  -collect_data_flow=%t-ThreeFunctionsTestDF -data_flow_trace=%t/OUT %t/IN
108RUN: %t-ThreeFunctionsTest -data_flow_trace=%t/OUT -runs=0 -focus_function=Func2 %t/IN 2>&1 | FileCheck %s --check-prefix=USE_DATA_FLOW_TRACE
109
110USE_DATA_FLOW_TRACE: INFO: DataFlowTrace: reading from {{.*}}/OUT
111USE_DATA_FLOW_TRACE: d28cb407e8e1a702c72d25473f0553d3ec172262 => |000001|
112USE_DATA_FLOW_TRACE: INFO: DataFlowTrace: 6 trace files, 3 functions, 1 traces with focus function
113USE_DATA_FLOW_TRACE: INFO: Focus function is set to 'Func2'
114USE_DATA_FLOW_TRACE: INITED
115USE_DATA_FLOW_TRACE: INFO: 2/6 inputs touch the focus function
116USE_DATA_FLOW_TRACE: INFO: 1/2 inputs have the Data Flow Trace
117
118# Test that we can run collect_data_flow on a long input (>2**16 bytes)
119RUN: printf "%0.sA" {1..150001} > %t/IN/very_long_input
120RUN: rm -rf %t/OUT
121RUN: %t-ThreeFunctionsTest  -collect_data_flow=%t-ThreeFunctionsTestDF -data_flow_trace=%t/OUT %t/IN/very_long_input
122RUN: rm %t/IN/very_long_input
123
124# Test that it fails explicitly when an empty corpus is provided.
125RUN: rm -rf %t/IN && mkdir %t/IN
126RUN: not %t-ThreeFunctionsTest  -collect_data_flow=%t-ThreeFunctionsTestDF -data_flow_trace=%t/OUT %t/IN 2>&1 | FileCheck %s --check-prefix=EMPTY_CORPUS
127
128EMPTY_CORPUS: ERROR: can't collect data flow without corpus provided
129