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