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))
10std::pair<int *, int>
11make_pair(int *p, int i) { return {p, i}; }
12
13__attribute__((noinline))
14std::pair<int *, int>
15copy_pair1(const std::pair<int *, int> &pair) {
16 return pair;
17}
18
19__attribute__((noinline))
20std::pair<int *, int>
21copy_pair2(std::pair<int *, int> *pair) {
22 return *pair;
23}
24
25__attribute__((noinline))
26std::pair<int *, int>
27copy_pair3(std::pair<int *, int> &&pair) {
28 return std::move(pair);
29}
30
31__attribute__((noinline))
32std::pair<const char *, uint32_t>
33return_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))
45std::pair<const char *, uint64_t>
46return_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
58void 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
113void 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
164int main(void) {
165 test_simple_constructors();
166 test_branches();
167
168 return 0;
169}
170

source code of compiler-rt/test/dfsan/pair.cpp