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