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 -O0 -DO0 -o %t && %run %t
2// RUN: %clangxx_dfsan %s -mllvm -dfsan-fast-16-labels -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))
12std::pair<int *, int>
13make_pair(int *p, int i) { return {p, i}; }
14
15__attribute__((noinline))
16std::pair<int *, int>
17copy_pair1(const std::pair<int *, int> &pair) {
18 return pair;
19}
20
21__attribute__((noinline))
22std::pair<int *, int>
23copy_pair2(std::pair<int *, int> *pair) {
24 return *pair;
25}
26
27__attribute__((noinline))
28std::pair<int *, int>
29copy_pair3(std::pair<int *, int> &&pair) {
30 return std::move(pair);
31}
32
33__attribute__((noinline))
34std::pair<const char *, uint32_t>
35return_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))
47std::pair<const char *, uint64_t>
48return_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
60void 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
115void 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
166int main(void) {
167 test_simple_constructors();
168 test_branches();
169
170 return 0;
171}
172