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 | |
20 | extern dfsan_label LabelI; |
21 | extern dfsan_label LabelJ; |
22 | extern dfsan_label LabelIJ; |
23 | |
24 | void 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 | |
54 | dfsan_label LabelI; |
55 | dfsan_label LabelJ; |
56 | dfsan_label LabelIJ; |
57 | |
58 | extern void my_dfsan_conditional_callback(dfsan_label Label, |
59 | dfsan_origin Origin); |
60 | |
61 | int 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 | |