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
16extern dfsan_label LabelI;
17extern dfsan_label LabelJ;
18extern dfsan_label LabelIJ;
19extern dfsan_label LabelArgv;
20extern size_t LenArgv;
21
22void __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
44void __dfsan_load_callback(dfsan_label Label) {
45 if (!Label)
46 return;
47
48 fprintf(stderr, "Label %u loaded from memory\n", Label);
49}
50
51void __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
60void __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
71dfsan_label LabelI;
72dfsan_label LabelJ;
73dfsan_label LabelIJ;
74dfsan_label LabelArgv;
75
76size_t LenArgv;
77
78int main(int Argc, char *Argv[]) {
79 assert(Argc == 2);
80
81 int I = 1, J = 2;
82 LabelI = 1;
83 dfsan_set_label(label: LabelI, addr: &I, size: sizeof(I));
84 LabelJ = 2;
85 dfsan_set_label(label: LabelJ, addr: &J, size: sizeof(J));
86 LabelIJ = dfsan_union(l1: LabelI, l2: 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(s: Argv[1]);
114 LabelArgv = 4;
115 dfsan_set_label(label: LabelArgv, addr: Argv[1], size: 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(dest: SinkPtr, src: Argv[1], n: LenArgv);
123
124 // CHECK: Label 4 copied to memory
125 SinkPtr = &Buf[1];
126 memmove(dest: SinkPtr, src: Buf, n: LenArgv);
127
128 return 0;
129}
130
131#endif // #ifdef CALLBACKS
132

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