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