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
18extern dfsan_label LabelI;
19extern dfsan_label LabelJ;
20extern dfsan_label LabelIJ;
21extern dfsan_label LabelArgv;
22extern size_t LenArgv;
23
24void __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
46void __dfsan_load_callback(dfsan_label Label) {
47 if (!Label)
48 return;
49
50 fprintf(stderr, "Label %u loaded from memory\n", Label);
51}
52
53void __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
62void __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
73dfsan_label LabelI;
74dfsan_label LabelJ;
75dfsan_label LabelIJ;
76dfsan_label LabelArgv;
77
78size_t LenArgv;
79
80int main(int Argc, char *Argv[]) {
81 assert(Argc == 2);
82
83 int I = 1, J = 2;
84 LabelI = dfsan_create_label("I", 0);
85 dfsan_set_label(LabelI, &I, sizeof(I));
86 LabelJ = dfsan_create_label("J", 0);
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 = dfsan_create_label("Argv", 0);
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