1 // RUN: %clangxx_dfsan %s -mllvm -dfsan-track-select-control-flow=false -mllvm -dfsan-combine-pointer-labels-on-load=false -O0 -DO0 -o %t && %run %t
2 // RUN: %clangxx_dfsan %s -mllvm -dfsan-track-select-control-flow=false -mllvm -dfsan-combine-pointer-labels-on-load=false -O1 -o %t && %run %t
3 //
4 // REQUIRES: x86_64-target-arch
5 
6 #include <algorithm>
7 #include <assert.h>
8 #include <sanitizer/dfsan_interface.h>
9 #include <utility>
10 
11 __attribute__((noinline))
12 std::pair<int *, int>
make_pair(int * p,int i)13 make_pair(int *p, int i) { return {p, i}; }
14 
15 __attribute__((noinline))
16 std::pair<int *, int>
copy_pair1(const std::pair<int *,int> & pair)17 copy_pair1(const std::pair<int *, int> &pair) {
18   return pair;
19 }
20 
21 __attribute__((noinline))
22 std::pair<int *, int>
copy_pair2(std::pair<int *,int> * pair)23 copy_pair2(std::pair<int *, int> *pair) {
24   return *pair;
25 }
26 
27 __attribute__((noinline))
28 std::pair<int *, int>
copy_pair3(std::pair<int *,int> && pair)29 copy_pair3(std::pair<int *, int> &&pair) {
30   return std::move(pair);
31 }
32 
33 __attribute__((noinline))
34 std::pair<const char *, uint32_t>
return_ptr_and_i32(const char * p,uint32_t res)35 return_ptr_and_i32(const char *p, uint32_t res) {
36   for (uint32_t i = 2; i < 5; i++) {
37     uint32_t byte = static_cast<uint8_t>(p[i]);
38     res += (byte - 1) << (7 * i);
39     if (byte < 128) {
40       return {p + i + 1, res};
41     }
42   }
43   return {nullptr, 0};
44 }
45 
46 __attribute__((noinline))
47 std::pair<const char *, uint64_t>
return_ptr_and_i64(const char * p,uint32_t res32)48 return_ptr_and_i64(const char *p, uint32_t res32) {
49   uint64_t res = res32;
50   for (uint32_t i = 2; i < 10; i++) {
51     uint64_t byte = static_cast<uint8_t>(p[i]);
52     res += (byte - 1) << (7 * i);
53     if (byte < 128) {
54       return {p + i + 1, res};
55     }
56   }
57   return {nullptr, 0};
58 }
59 
test_simple_constructors()60 void test_simple_constructors() {
61   int i = 1;
62   int *ptr = NULL;
63   dfsan_set_label(8, &i, sizeof(i));
64   dfsan_set_label(2, &ptr, sizeof(ptr));
65 
66   std::pair<int *, int> pair1 = make_pair(ptr, i);
67   int i1 = pair1.second;
68   int *ptr1 = pair1.first;
69 
70 #ifdef O0
71   assert(dfsan_read_label(&i1, sizeof(i1)) == 10);
72   assert(dfsan_read_label(&ptr1, sizeof(ptr1)) == 10);
73 #else
74   assert(dfsan_read_label(&i1, sizeof(i1)) == 8);
75   assert(dfsan_read_label(&ptr1, sizeof(ptr1)) == 2);
76 #endif
77 
78   std::pair<int *, int> pair2 = copy_pair1(pair1);
79   int i2 = pair2.second;
80   int *ptr2 = pair2.first;
81 
82 #ifdef O0
83   assert(dfsan_read_label(&i2, sizeof(i2)) == 10);
84   assert(dfsan_read_label(&ptr2, sizeof(ptr2)) == 10);
85 #else
86   assert(dfsan_read_label(&i2, sizeof(i2)) == 8);
87   assert(dfsan_read_label(&ptr2, sizeof(ptr2)) == 2);
88 #endif
89 
90   std::pair<int *, int> pair3 = copy_pair2(&pair1);
91   int i3 = pair3.second;
92   int *ptr3 = pair3.first;
93 
94 #ifdef O0
95   assert(dfsan_read_label(&i3, sizeof(i3)) == 10);
96   assert(dfsan_read_label(&ptr3, sizeof(ptr3)) == 10);
97 #else
98   assert(dfsan_read_label(&i3, sizeof(i3)) == 8);
99   assert(dfsan_read_label(&ptr3, sizeof(ptr3)) == 2);
100 #endif
101 
102   std::pair<int *, int> pair4 = copy_pair3(std::move(pair1));
103   int i4 = pair4.second;
104   int *ptr4 = pair4.first;
105 
106 #ifdef O0
107   assert(dfsan_read_label(&i4, sizeof(i4)) == 10);
108   assert(dfsan_read_label(&ptr4, sizeof(ptr4)) == 10);
109 #else
110   assert(dfsan_read_label(&i4, sizeof(i4)) == 8);
111   assert(dfsan_read_label(&ptr4, sizeof(ptr4)) == 2);
112 #endif
113 }
114 
test_branches()115 void test_branches() {
116   uint32_t res = 4;
117   dfsan_set_label(8, &res, sizeof(res));
118 
119   char p[100];
120   const char *q = p;
121   dfsan_set_label(2, &q, sizeof(q));
122 
123   {
124     std::fill_n(p, 100, static_cast<char>(128));
125 
126     {
127       std::pair<const char *, uint32_t> r = return_ptr_and_i32(q, res);
128       assert(dfsan_read_label(&r.first, sizeof(r.first)) == 0);
129       assert(dfsan_read_label(&r.second, sizeof(r.second)) == 0);
130     }
131 
132     {
133       std::pair<const char *, uint64_t> r = return_ptr_and_i64(q, res);
134       assert(dfsan_read_label(&r.first, sizeof(r.first)) == 0);
135       assert(dfsan_read_label(&r.second, sizeof(r.second)) == 0);
136     }
137   }
138 
139   {
140     std::fill_n(p, 100, 0);
141 
142     {
143       std::pair<const char *, uint32_t> r = return_ptr_and_i32(q, res);
144 #ifdef O0
145       assert(dfsan_read_label(&r.first, sizeof(r.first)) == 10);
146       assert(dfsan_read_label(&r.second, sizeof(r.second)) == 10);
147 #else
148       assert(dfsan_read_label(&r.first, sizeof(r.first)) == 2);
149       assert(dfsan_read_label(&r.second, sizeof(r.second)) == 8);
150 #endif
151     }
152 
153     {
154       std::pair<const char *, uint64_t> r = return_ptr_and_i64(q, res);
155 #ifdef O0
156       assert(dfsan_read_label(&r.first, sizeof(r.first)) == 10);
157       assert(dfsan_read_label(&r.second, sizeof(r.second)) == 10);
158 #else
159       assert(dfsan_read_label(&r.first, sizeof(r.first)) == 2);
160       assert(dfsan_read_label(&r.second, sizeof(r.second)) == 8);
161 #endif
162     }
163   }
164 }
165 
main(void)166 int main(void) {
167   test_simple_constructors();
168   test_branches();
169 
170   return 0;
171 }
172