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> |
11 | make_pair(int *p, int i) { return {p, i}; } |
12 | |
13 | __attribute__((noinline)) |
14 | std::pair<int *, int> |
15 | copy_pair1(const std::pair<int *, int> &pair) { |
16 | return pair; |
17 | } |
18 | |
19 | __attribute__((noinline)) |
20 | std::pair<int *, int> |
21 | copy_pair2(std::pair<int *, int> *pair) { |
22 | return *pair; |
23 | } |
24 | |
25 | __attribute__((noinline)) |
26 | std::pair<int *, int> |
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> |
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> |
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 | |
58 | void test_simple_constructors() { |
59 | int i = 1; |
60 | int *ptr = NULL; |
61 | dfsan_set_label(label: 8, addr: &i, size: sizeof(i)); |
62 | dfsan_set_label(label: 2, addr: &ptr, size: 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 | |
113 | void test_branches() { |
114 | uint32_t res = 4; |
115 | dfsan_set_label(label: 8, addr: &res, size: sizeof(res)); |
116 | |
117 | char p[100]; |
118 | const char *q = p; |
119 | dfsan_set_label(label: 2, addr: &q, size: 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 | |
164 | int main(void) { |
165 | test_simple_constructors(); |
166 | test_branches(); |
167 | |
168 | return 0; |
169 | } |
170 | |