| 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 | |