1// RUN: %clang_dfsan -fno-sanitize=dataflow -O2 -fPIE -DCALLBACKS -c %s -o %t-callbacks.o
2// RUN: %clang_dfsan -fsanitize-ignorelist=%S/Inputs/flags_abilist.txt -O2 -mllvm -dfsan-conditional-callbacks %s %t-callbacks.o -o %t
3// RUN: %run %t FooBarBaz 2>&1 | FileCheck %s
4//
5// RUN: %clang_dfsan -fno-sanitize=dataflow -O2 -fPIE -DCALLBACKS -DORIGINS -c %s -o %t-callbacks-orig.o
6// RUN: %clang_dfsan -fsanitize-ignorelist=%S/Inputs/flags_abilist.txt -O2 -mllvm -dfsan-conditional-callbacks -mllvm -dfsan-track-origins=1 -DORIGINS %s %t-callbacks-orig.o -o %t-orig
7// RUN: %run %t-orig FooBarBaz 2>&1 | FileCheck %s
8
9// Tests that callbacks are inserted for conditionals when
10// -dfsan-conditional-callbacks is specified.
11
12#include <assert.h>
13#include <sanitizer/dfsan_interface.h>
14#include <stdio.h>
15#include <string.h>
16
17#ifdef CALLBACKS
18// Compile this code without DFSan to avoid recursive instrumentation.
19
20extern dfsan_label LabelI;
21extern dfsan_label LabelJ;
22extern dfsan_label LabelIJ;
23
24void my_dfsan_conditional_callback(dfsan_label Label, dfsan_origin Origin) {
25 assert(Label != 0);
26#ifdef ORIGINS
27 assert(Origin != 0);
28#else
29 assert(Origin == 0);
30#endif
31
32 static int Count = 0;
33 switch (Count++) {
34 case 0:
35 assert(Label == LabelI);
36 break;
37 case 1:
38 assert(Label == LabelJ);
39 break;
40 case 2:
41 assert(Label == LabelIJ);
42 break;
43 default:
44 break;
45 }
46
47 fprintf(stderr, "Label %u used as condition\n", Label);
48}
49
50#else
51// Compile this code with DFSan and -dfsan-conditional-callbacks to insert the
52// callbacks.
53
54dfsan_label LabelI;
55dfsan_label LabelJ;
56dfsan_label LabelIJ;
57
58extern void my_dfsan_conditional_callback(dfsan_label Label,
59 dfsan_origin Origin);
60
61int main(int Argc, char *Argv[]) {
62 assert(Argc == 2);
63
64 dfsan_set_conditional_callback(callback: my_dfsan_conditional_callback);
65
66 int result = 0;
67 // Make these not look like constants, otherwise the branch we're expecting
68 // may be optimized out.
69 int DataI = (Argv[0][0] != 0) ? 1 : 0;
70 int DataJ = (Argv[1][0] != 0) ? 2 : 0;
71 LabelI = 1;
72 dfsan_set_label(label: LabelI, addr: &DataI, size: sizeof(DataI));
73 LabelJ = 2;
74 dfsan_set_label(label: LabelJ, addr: &DataJ, size: sizeof(DataJ));
75 LabelIJ = dfsan_union(l1: LabelI, l2: LabelJ);
76
77 assert(dfsan_get_label(DataI) == LabelI);
78
79 // CHECK: Label 1 used as condition
80 if (DataI) {
81 result = 42;
82 }
83
84 fprintf(stderr, format: "Result is %d\n", result);
85 assert(dfsan_get_label(DataJ) == LabelJ);
86
87 // CHECK: Label 2 used as condition
88 switch (DataJ) {
89 case 1:
90 result += 10000;
91 break;
92 case 2:
93 result += 4200;
94 break;
95 default:
96 break;
97 }
98
99 int tainted_cond = ((DataI * DataJ) != 1);
100 fprintf(stderr, format: "Result is %d\n", result);
101 assert(dfsan_get_label(tainted_cond) == LabelIJ);
102
103 // CHECK: Label 3 used as condition
104 result = tainted_cond ? result + 420000 : 9;
105
106 fprintf(stderr, format: "Result is %d\n", result);
107 assert(result == 424242);
108 return 0;
109}
110
111#endif // #ifdef CALLBACKS
112

source code of compiler-rt/test/dfsan/conditional_callbacks.c