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