138db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany//===-- asan_oob_test.cc --------------------------------------------------===//
238db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany//
338db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany//                     The LLVM Compiler Infrastructure
438db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany//
538db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany// This file is distributed under the University of Illinois Open Source
638db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany// License. See LICENSE.TXT for details.
738db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany//
838db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany//===----------------------------------------------------------------------===//
938db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany//
1038db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany// This file is a part of AddressSanitizer, an address sanity checker.
1138db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany//
1238db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany//===----------------------------------------------------------------------===//
1338db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany#include "asan_test_utils.h"
1438db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany
1538db30686c5962f8b5c877e29c6669d72198d42bKostya SerebryanyNOINLINE void asan_write_sized_aligned(uint8_t *p, size_t size) {
1638db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany  EXPECT_EQ(0U, ((uintptr_t)p % size));
1738db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany  if      (size == 1) asan_write((uint8_t*)p);
1838db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany  else if (size == 2) asan_write((uint16_t*)p);
1938db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany  else if (size == 4) asan_write((uint32_t*)p);
2038db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany  else if (size == 8) asan_write((uint64_t*)p);
2138db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany}
2238db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany
2338db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryanytemplate<typename T>
2438db30686c5962f8b5c877e29c6669d72198d42bKostya SerebryanyNOINLINE void oob_test(int size, int off) {
2538db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany  char *p = (char*)malloc_aaa(size);
2638db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany  // fprintf(stderr, "writing %d byte(s) into [%p,%p) with offset %d\n",
2738db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany  //        sizeof(T), p, p + size, off);
2838db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany  asan_write((T*)(p + off));
2938db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany  free_aaa(p);
3038db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany}
3138db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany
3238db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryanytemplate<typename T>
3338db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryanyvoid OOBTest() {
3438db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany  char expected_str[100];
3538db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany  for (int size = sizeof(T); size < 20; size += 5) {
3638db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany    for (int i = -5; i < 0; i++) {
3738db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany      const char *str =
3838db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany          "is located.*%d byte.*to the left";
3938db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany      sprintf(expected_str, str, abs(i));
4038db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany      EXPECT_DEATH(oob_test<T>(size, i), expected_str);
4138db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany    }
4238db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany
4338db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany    for (int i = 0; i < (int)(size - sizeof(T) + 1); i++)
4438db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany      oob_test<T>(size, i);
4538db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany
4638db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany    for (int i = size - sizeof(T) + 1; i <= (int)(size + 2 * sizeof(T)); i++) {
4738db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany      const char *str =
4838db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany          "is located.*%d byte.*to the right";
4938db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany      int off = i >= size ? (i - size) : 0;
5038db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany      // we don't catch unaligned partially OOB accesses.
5138db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany      if (i % sizeof(T)) continue;
5238db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany      sprintf(expected_str, str, off);
5338db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany      EXPECT_DEATH(oob_test<T>(size, i), expected_str);
5438db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany    }
5538db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany  }
5638db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany
5738db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany  EXPECT_DEATH(oob_test<T>(kLargeMalloc, -1),
5838db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany          "is located.*1 byte.*to the left");
5938db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany  EXPECT_DEATH(oob_test<T>(kLargeMalloc, kLargeMalloc),
6038db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany          "is located.*0 byte.*to the right");
6138db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany}
6238db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany
6338db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany// TODO(glider): the following tests are EXTREMELY slow on Darwin:
6438db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany//   AddressSanitizer.OOB_char (125503 ms)
6538db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany//   AddressSanitizer.OOB_int (126890 ms)
6638db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany//   AddressSanitizer.OOBRightTest (315605 ms)
6738db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany//   AddressSanitizer.SimpleStackTest (366559 ms)
6838db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany
6938db30686c5962f8b5c877e29c6669d72198d42bKostya SerebryanyTEST(AddressSanitizer, OOB_char) {
7038db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany  OOBTest<U1>();
7138db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany}
7238db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany
7338db30686c5962f8b5c877e29c6669d72198d42bKostya SerebryanyTEST(AddressSanitizer, OOB_int) {
7438db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany  OOBTest<U4>();
7538db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany}
7638db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany
7738db30686c5962f8b5c877e29c6669d72198d42bKostya SerebryanyTEST(AddressSanitizer, OOBRightTest) {
782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  size_t max_access_size = SANITIZER_WORDSIZE == 64 ? 8 : 4;
792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  for (size_t access_size = 1; access_size <= max_access_size;
802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines       access_size *= 2) {
8138db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany    for (size_t alloc_size = 1; alloc_size <= 8; alloc_size++) {
8238db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany      for (size_t offset = 0; offset <= 8; offset += access_size) {
8338db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany        void *p = malloc(alloc_size);
8438db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany        // allocated: [p, p + alloc_size)
8538db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany        // accessed:  [p + offset, p + offset + access_size)
8638db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany        uint8_t *addr = (uint8_t*)p + offset;
8738db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany        if (offset + access_size <= alloc_size) {
8838db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany          asan_write_sized_aligned(addr, access_size);
8938db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany        } else {
9038db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany          int outside_bytes = offset > alloc_size ? (offset - alloc_size) : 0;
9138db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany          const char *str =
9238db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany              "is located.%d *byte.*to the right";
9338db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany          char expected_str[100];
9438db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany          sprintf(expected_str, str, outside_bytes);
9538db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany          EXPECT_DEATH(asan_write_sized_aligned(addr, access_size),
9638db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany                       expected_str);
9738db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany        }
9838db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany        free(p);
9938db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany      }
10038db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany    }
10138db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany  }
10238db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany}
10338db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany
10438db30686c5962f8b5c877e29c6669d72198d42bKostya SerebryanyTEST(AddressSanitizer, LargeOOBRightTest) {
10538db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany  size_t large_power_of_two = 1 << 19;
10638db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany  for (size_t i = 16; i <= 256; i *= 2) {
10738db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany    size_t size = large_power_of_two - i;
10838db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany    char *p = Ident(new char[size]);
10938db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany    EXPECT_DEATH(p[size] = 0, "is located 0 bytes to the right");
11038db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany    delete [] p;
11138db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany  }
11238db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany}
11338db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany
11438db30686c5962f8b5c877e29c6669d72198d42bKostya SerebryanyTEST(AddressSanitizer, DISABLED_DemoOOBLeftLow) {
11538db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany  oob_test<U1>(10, -1);
11638db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany}
11738db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany
11838db30686c5962f8b5c877e29c6669d72198d42bKostya SerebryanyTEST(AddressSanitizer, DISABLED_DemoOOBLeftHigh) {
11938db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany  oob_test<U1>(kLargeMalloc, -1);
12038db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany}
12138db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany
12238db30686c5962f8b5c877e29c6669d72198d42bKostya SerebryanyTEST(AddressSanitizer, DISABLED_DemoOOBRightLow) {
12338db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany  oob_test<U1>(10, 10);
12438db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany}
12538db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany
12638db30686c5962f8b5c877e29c6669d72198d42bKostya SerebryanyTEST(AddressSanitizer, DISABLED_DemoOOBRightHigh) {
12738db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany  oob_test<U1>(kLargeMalloc, kLargeMalloc);
12838db30686c5962f8b5c877e29c6669d72198d42bKostya Serebryany}
129