1 // RUN: %clang_dfsan -fno-sanitize=dataflow -O2 -fPIE -DCALLBACKS -c %s -o %t-callbacks.o
2 // RUN: %clang_dfsan -O2 -mllvm -dfsan-event-callbacks %s %t-callbacks.o -o %t
3 // RUN: %run %t FooBarBaz 2>&1 | FileCheck %s
4 //
5 // REQUIRES: x86_64-target-arch
6 
7 // Tests that callbacks are inserted for store events when
8 // -dfsan-event-callbacks is specified.
9 
10 #include <assert.h>
11 #include <sanitizer/dfsan_interface.h>
12 #include <stdio.h>
13 #include <string.h>
14 
15 #ifdef CALLBACKS
16 // Compile this code without DFSan to avoid recursive instrumentation.
17 
18 extern dfsan_label LabelI;
19 extern dfsan_label LabelJ;
20 extern dfsan_label LabelIJ;
21 extern dfsan_label LabelArgv;
22 extern size_t LenArgv;
23 
__dfsan_store_callback(dfsan_label Label)24 void __dfsan_store_callback(dfsan_label Label) {
25   if (!Label)
26     return;
27 
28   static int Count = 0;
29   switch (Count++) {
30   case 0:
31     assert(Label == LabelI);
32     break;
33   case 1:
34     assert(Label == LabelJ);
35     break;
36   case 2:
37     assert(Label == LabelIJ);
38     break;
39   default:
40     assert(0);
41   }
42 
43   fprintf(stderr, "Label %u stored to memory\n", Label);
44 }
45 
__dfsan_load_callback(dfsan_label Label)46 void __dfsan_load_callback(dfsan_label Label) {
47   if (!Label)
48     return;
49 
50   fprintf(stderr, "Label %u loaded from memory\n", Label);
51 }
52 
__dfsan_mem_transfer_callback(dfsan_label * Start,size_t Len)53 void __dfsan_mem_transfer_callback(dfsan_label *Start, size_t Len) {
54   assert(Len == LenArgv);
55   for (int I = 0; I < Len; ++I) {
56     assert(Start[I] == LabelArgv);
57   }
58 
59   fprintf(stderr, "Label %u copied to memory\n", Start[0]);
60 }
61 
__dfsan_cmp_callback(dfsan_label CombinedLabel)62 void __dfsan_cmp_callback(dfsan_label CombinedLabel) {
63   if (!CombinedLabel)
64     return;
65 
66   fprintf(stderr, "Label %u used for branching\n", CombinedLabel);
67 }
68 
69 #else
70 // Compile this code with DFSan and -dfsan-event-callbacks to insert the
71 // callbacks.
72 
73 dfsan_label LabelI;
74 dfsan_label LabelJ;
75 dfsan_label LabelIJ;
76 dfsan_label LabelArgv;
77 
78 size_t LenArgv;
79 
main(int Argc,char * Argv[])80 int main(int Argc, char *Argv[]) {
81   assert(Argc == 2);
82 
83   int I = 1, J = 2;
84   LabelI = 1;
85   dfsan_set_label(LabelI, &I, sizeof(I));
86   LabelJ = 2;
87   dfsan_set_label(LabelJ, &J, sizeof(J));
88   LabelIJ = dfsan_union(LabelI, LabelJ);
89 
90   // CHECK: Label 1 stored to memory
91   volatile int Sink = I;
92 
93   // CHECK: Label 1 loaded from memory
94   // CHECK: Label 1 used for branching
95   assert(Sink == 1);
96 
97   // CHECK: Label 2 stored to memory
98   Sink = J;
99 
100   // CHECK: Label 2 loaded from memory
101   // CHECK: Label 2 used for branching
102   assert(Sink == 2);
103 
104   // CHECK: Label 2 loaded from memory
105   // CHECK: Label 3 stored to memory
106   Sink += I;
107 
108   // CHECK: Label 3 loaded from memory
109   // CHECK: Label 3 used for branching
110   assert(Sink == 3);
111 
112   // CHECK: Label 3 used for branching
113   assert(I != J);
114 
115   LenArgv = strlen(Argv[1]);
116   LabelArgv = 4;
117   dfsan_set_label(LabelArgv, Argv[1], LenArgv);
118 
119   char Buf[64];
120   assert(LenArgv < sizeof(Buf) - 1);
121 
122   // CHECK: Label 4 copied to memory
123   void *volatile SinkPtr = Buf;
124   memcpy(SinkPtr, Argv[1], LenArgv);
125 
126   // CHECK: Label 4 copied to memory
127   SinkPtr = &Buf[1];
128   memmove(SinkPtr, Buf, LenArgv);
129 
130   return 0;
131 }
132 
133 #endif // #ifdef CALLBACKS
134