1//===-- asan_oob_test.cc --------------------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file is a part of AddressSanitizer, an address sanity checker.
11//
12//===----------------------------------------------------------------------===//
13#include "asan_test_utils.h"
14
15NOINLINE void asan_write_sized_aligned(uint8_t *p, size_t size) {
16  EXPECT_EQ(0U, ((uintptr_t)p % size));
17  if      (size == 1) asan_write((uint8_t*)p);
18  else if (size == 2) asan_write((uint16_t*)p);
19  else if (size == 4) asan_write((uint32_t*)p);
20  else if (size == 8) asan_write((uint64_t*)p);
21}
22
23template<typename T>
24NOINLINE void oob_test(int size, int off) {
25  char *p = (char*)malloc_aaa(size);
26  // fprintf(stderr, "writing %d byte(s) into [%p,%p) with offset %d\n",
27  //        sizeof(T), p, p + size, off);
28  asan_write((T*)(p + off));
29  free_aaa(p);
30}
31
32template<typename T>
33void OOBTest() {
34  char expected_str[100];
35  for (int size = sizeof(T); size < 20; size += 5) {
36    for (int i = -5; i < 0; i++) {
37      const char *str =
38          "is located.*%d byte.*to the left";
39      sprintf(expected_str, str, abs(i));
40      EXPECT_DEATH(oob_test<T>(size, i), expected_str);
41    }
42
43    for (int i = 0; i < (int)(size - sizeof(T) + 1); i++)
44      oob_test<T>(size, i);
45
46    for (int i = size - sizeof(T) + 1; i <= (int)(size + 2 * sizeof(T)); i++) {
47      const char *str =
48          "is located.*%d byte.*to the right";
49      int off = i >= size ? (i - size) : 0;
50      // we don't catch unaligned partially OOB accesses.
51      if (i % sizeof(T)) continue;
52      sprintf(expected_str, str, off);
53      EXPECT_DEATH(oob_test<T>(size, i), expected_str);
54    }
55  }
56
57  EXPECT_DEATH(oob_test<T>(kLargeMalloc, -1),
58          "is located.*1 byte.*to the left");
59  EXPECT_DEATH(oob_test<T>(kLargeMalloc, kLargeMalloc),
60          "is located.*0 byte.*to the right");
61}
62
63// TODO(glider): the following tests are EXTREMELY slow on Darwin:
64//   AddressSanitizer.OOB_char (125503 ms)
65//   AddressSanitizer.OOB_int (126890 ms)
66//   AddressSanitizer.OOBRightTest (315605 ms)
67//   AddressSanitizer.SimpleStackTest (366559 ms)
68
69TEST(AddressSanitizer, OOB_char) {
70  OOBTest<U1>();
71}
72
73TEST(AddressSanitizer, OOB_int) {
74  OOBTest<U4>();
75}
76
77TEST(AddressSanitizer, OOBRightTest) {
78  size_t max_access_size = SANITIZER_WORDSIZE == 64 ? 8 : 4;
79  for (size_t access_size = 1; access_size <= max_access_size;
80       access_size *= 2) {
81    for (size_t alloc_size = 1; alloc_size <= 8; alloc_size++) {
82      for (size_t offset = 0; offset <= 8; offset += access_size) {
83        void *p = malloc(alloc_size);
84        // allocated: [p, p + alloc_size)
85        // accessed:  [p + offset, p + offset + access_size)
86        uint8_t *addr = (uint8_t*)p + offset;
87        if (offset + access_size <= alloc_size) {
88          asan_write_sized_aligned(addr, access_size);
89        } else {
90          int outside_bytes = offset > alloc_size ? (offset - alloc_size) : 0;
91          const char *str =
92              "is located.%d *byte.*to the right";
93          char expected_str[100];
94          sprintf(expected_str, str, outside_bytes);
95          EXPECT_DEATH(asan_write_sized_aligned(addr, access_size),
96                       expected_str);
97        }
98        free(p);
99      }
100    }
101  }
102}
103
104TEST(AddressSanitizer, LargeOOBRightTest) {
105  size_t large_power_of_two = 1 << 19;
106  for (size_t i = 16; i <= 256; i *= 2) {
107    size_t size = large_power_of_two - i;
108    char *p = Ident(new char[size]);
109    EXPECT_DEATH(p[size] = 0, "is located 0 bytes to the right");
110    delete [] p;
111  }
112}
113
114TEST(AddressSanitizer, DISABLED_DemoOOBLeftLow) {
115  oob_test<U1>(10, -1);
116}
117
118TEST(AddressSanitizer, DISABLED_DemoOOBLeftHigh) {
119  oob_test<U1>(kLargeMalloc, -1);
120}
121
122TEST(AddressSanitizer, DISABLED_DemoOOBRightLow) {
123  oob_test<U1>(10, 10);
124}
125
126TEST(AddressSanitizer, DISABLED_DemoOOBRightHigh) {
127  oob_test<U1>(kLargeMalloc, kLargeMalloc);
128}
129