// RUN: %clangxx_dfsan %s -mllvm -dfsan-fast-16-labels -mllvm -dfsan-track-select-control-flow=false -mllvm -dfsan-combine-pointer-labels-on-load=false -o %t && %run %t #include #include #include #include __attribute__((noinline)) std::pair make_pair(int *p, int i) { return {p, i}; } __attribute__((noinline)) std::pair copy_pair1(const std::pair &pair) { return pair; } __attribute__((noinline)) std::pair copy_pair2(std::pair *pair) { return *pair; } __attribute__((noinline)) std::pair copy_pair3(std::pair &&pair) { return std::move(pair); } __attribute__((noinline)) std::pair return_ptr_and_i32(const char *p, uint32_t res) { for (uint32_t i = 2; i < 5; i++) { uint32_t byte = static_cast(p[i]); res += (byte - 1) << (7 * i); if (byte < 128) { return {p + i + 1, res}; } } return {nullptr, 0}; } __attribute__((noinline)) std::pair return_ptr_and_i64(const char *p, uint32_t res32) { uint64_t res = res32; for (uint32_t i = 2; i < 10; i++) { uint64_t byte = static_cast(p[i]); res += (byte - 1) << (7 * i); if (byte < 128) { return {p + i + 1, res}; } } return {nullptr, 0}; } void test_simple_constructors() { int i = 1; int *ptr = NULL; dfsan_set_label(8, &i, sizeof(i)); dfsan_set_label(2, &ptr, sizeof(ptr)); std::pair pair1 = make_pair(ptr, i); int i1 = pair1.second; int *ptr1 = pair1.first; assert(dfsan_read_label(&i1, sizeof(i1)) == 10); assert(dfsan_read_label(&ptr1, sizeof(ptr1)) == 10); std::pair pair2 = copy_pair1(pair1); int i2 = pair2.second; int *ptr2 = pair2.first; assert(dfsan_read_label(&i2, sizeof(i2)) == 10); assert(dfsan_read_label(&ptr2, sizeof(ptr2)) == 10); std::pair pair3 = copy_pair2(&pair1); int i3 = pair3.second; int *ptr3 = pair3.first; assert(dfsan_read_label(&i3, sizeof(i3)) == 10); assert(dfsan_read_label(&ptr3, sizeof(ptr3)) == 10); std::pair pair4 = copy_pair3(std::move(pair1)); int i4 = pair4.second; int *ptr4 = pair4.first; assert(dfsan_read_label(&i4, sizeof(i4)) == 10); assert(dfsan_read_label(&ptr4, sizeof(ptr4)) == 10); } void test_branches() { uint32_t res = 4; dfsan_set_label(8, &res, sizeof(res)); char p[100]; const char *q = p; dfsan_set_label(2, &q, sizeof(q)); { std::fill_n(p, 100, static_cast(128)); { std::pair r = return_ptr_and_i32(q, res); assert(dfsan_read_label(&r.first, sizeof(r.first)) == 0); assert(dfsan_read_label(&r.second, sizeof(r.second)) == 0); } { std::pair r = return_ptr_and_i64(q, res); assert(dfsan_read_label(&r.first, sizeof(r.first)) == 0); assert(dfsan_read_label(&r.second, sizeof(r.second)) == 0); } } { std::fill_n(p, 100, 0); { std::pair r = return_ptr_and_i32(q, res); assert(dfsan_read_label(&r.first, sizeof(r.first)) == 10); assert(dfsan_read_label(&r.second, sizeof(r.second)) == 10); } { std::pair r = return_ptr_and_i64(q, res); assert(dfsan_read_label(&r.first, sizeof(r.first)) == 10); assert(dfsan_read_label(&r.second, sizeof(r.second)) == 10); } } } int main(void) { test_simple_constructors(); test_branches(); return 0; }