172 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			172 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			C++
		
	
	
	
// 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
 | 
						|
// RUN: %clangxx_dfsan %s -mllvm -dfsan-track-select-control-flow=false -mllvm -dfsan-combine-pointer-labels-on-load=false -O1 -o %t && %run %t
 | 
						|
//
 | 
						|
// REQUIRES: x86_64-target-arch
 | 
						|
 | 
						|
#include <algorithm>
 | 
						|
#include <assert.h>
 | 
						|
#include <sanitizer/dfsan_interface.h>
 | 
						|
#include <utility>
 | 
						|
 | 
						|
__attribute__((noinline))
 | 
						|
std::pair<int *, int>
 | 
						|
make_pair(int *p, int i) { return {p, i}; }
 | 
						|
 | 
						|
__attribute__((noinline))
 | 
						|
std::pair<int *, int>
 | 
						|
copy_pair1(const std::pair<int *, int> &pair) {
 | 
						|
  return pair;
 | 
						|
}
 | 
						|
 | 
						|
__attribute__((noinline))
 | 
						|
std::pair<int *, int>
 | 
						|
copy_pair2(std::pair<int *, int> *pair) {
 | 
						|
  return *pair;
 | 
						|
}
 | 
						|
 | 
						|
__attribute__((noinline))
 | 
						|
std::pair<int *, int>
 | 
						|
copy_pair3(std::pair<int *, int> &&pair) {
 | 
						|
  return std::move(pair);
 | 
						|
}
 | 
						|
 | 
						|
__attribute__((noinline))
 | 
						|
std::pair<const char *, uint32_t>
 | 
						|
return_ptr_and_i32(const char *p, uint32_t res) {
 | 
						|
  for (uint32_t i = 2; i < 5; i++) {
 | 
						|
    uint32_t byte = static_cast<uint8_t>(p[i]);
 | 
						|
    res += (byte - 1) << (7 * i);
 | 
						|
    if (byte < 128) {
 | 
						|
      return {p + i + 1, res};
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return {nullptr, 0};
 | 
						|
}
 | 
						|
 | 
						|
__attribute__((noinline))
 | 
						|
std::pair<const char *, uint64_t>
 | 
						|
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<uint8_t>(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<int *, int> pair1 = make_pair(ptr, i);
 | 
						|
  int i1 = pair1.second;
 | 
						|
  int *ptr1 = pair1.first;
 | 
						|
 | 
						|
#ifdef O0
 | 
						|
  assert(dfsan_read_label(&i1, sizeof(i1)) == 10);
 | 
						|
  assert(dfsan_read_label(&ptr1, sizeof(ptr1)) == 10);
 | 
						|
#else
 | 
						|
  assert(dfsan_read_label(&i1, sizeof(i1)) == 8);
 | 
						|
  assert(dfsan_read_label(&ptr1, sizeof(ptr1)) == 2);
 | 
						|
#endif
 | 
						|
 | 
						|
  std::pair<int *, int> pair2 = copy_pair1(pair1);
 | 
						|
  int i2 = pair2.second;
 | 
						|
  int *ptr2 = pair2.first;
 | 
						|
 | 
						|
#ifdef O0
 | 
						|
  assert(dfsan_read_label(&i2, sizeof(i2)) == 10);
 | 
						|
  assert(dfsan_read_label(&ptr2, sizeof(ptr2)) == 10);
 | 
						|
#else
 | 
						|
  assert(dfsan_read_label(&i2, sizeof(i2)) == 8);
 | 
						|
  assert(dfsan_read_label(&ptr2, sizeof(ptr2)) == 2);
 | 
						|
#endif
 | 
						|
 | 
						|
  std::pair<int *, int> pair3 = copy_pair2(&pair1);
 | 
						|
  int i3 = pair3.second;
 | 
						|
  int *ptr3 = pair3.first;
 | 
						|
 | 
						|
#ifdef O0
 | 
						|
  assert(dfsan_read_label(&i3, sizeof(i3)) == 10);
 | 
						|
  assert(dfsan_read_label(&ptr3, sizeof(ptr3)) == 10);
 | 
						|
#else
 | 
						|
  assert(dfsan_read_label(&i3, sizeof(i3)) == 8);
 | 
						|
  assert(dfsan_read_label(&ptr3, sizeof(ptr3)) == 2);
 | 
						|
#endif
 | 
						|
 | 
						|
  std::pair<int *, int> pair4 = copy_pair3(std::move(pair1));
 | 
						|
  int i4 = pair4.second;
 | 
						|
  int *ptr4 = pair4.first;
 | 
						|
 | 
						|
#ifdef O0
 | 
						|
  assert(dfsan_read_label(&i4, sizeof(i4)) == 10);
 | 
						|
  assert(dfsan_read_label(&ptr4, sizeof(ptr4)) == 10);
 | 
						|
#else
 | 
						|
  assert(dfsan_read_label(&i4, sizeof(i4)) == 8);
 | 
						|
  assert(dfsan_read_label(&ptr4, sizeof(ptr4)) == 2);
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
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<char>(128));
 | 
						|
 | 
						|
    {
 | 
						|
      std::pair<const char *, uint32_t> 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<const char *, uint64_t> 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<const char *, uint32_t> r = return_ptr_and_i32(q, res);
 | 
						|
#ifdef O0
 | 
						|
      assert(dfsan_read_label(&r.first, sizeof(r.first)) == 10);
 | 
						|
      assert(dfsan_read_label(&r.second, sizeof(r.second)) == 10);
 | 
						|
#else
 | 
						|
      assert(dfsan_read_label(&r.first, sizeof(r.first)) == 2);
 | 
						|
      assert(dfsan_read_label(&r.second, sizeof(r.second)) == 8);
 | 
						|
#endif
 | 
						|
    }
 | 
						|
 | 
						|
    {
 | 
						|
      std::pair<const char *, uint64_t> r = return_ptr_and_i64(q, res);
 | 
						|
#ifdef O0
 | 
						|
      assert(dfsan_read_label(&r.first, sizeof(r.first)) == 10);
 | 
						|
      assert(dfsan_read_label(&r.second, sizeof(r.second)) == 10);
 | 
						|
#else
 | 
						|
      assert(dfsan_read_label(&r.first, sizeof(r.first)) == 2);
 | 
						|
      assert(dfsan_read_label(&r.second, sizeof(r.second)) == 8);
 | 
						|
#endif
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
int main(void) {
 | 
						|
  test_simple_constructors();
 | 
						|
  test_branches();
 | 
						|
 | 
						|
  return 0;
 | 
						|
}
 |