xref: /llvm-project/compiler-rt/test/dfsan/conditional_callbacks.c (revision 370880cdcc487298fd30628cad1a3671ba1c5f5c)
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 
my_dfsan_conditional_callback(dfsan_label Label,dfsan_origin Origin)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 
main(int Argc,char * Argv[])61 int main(int Argc, char *Argv[]) {
62   assert(Argc == 2);
63 
64   dfsan_set_conditional_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(LabelI, &DataI, sizeof(DataI));
73   LabelJ = 2;
74   dfsan_set_label(LabelJ, &DataJ, sizeof(DataJ));
75   LabelIJ = dfsan_union(LabelI, 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, "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, "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, "Result is %d\n", result);
107   assert(result == 424242);
108   return 0;
109 }
110 
111 #endif // #ifdef CALLBACKS
112