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 
asan_write_sized_aligned(uint8_t * p,size_t size)15 NOINLINE 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 
23 template<typename T>
oob_test(int size,int off)24 NOINLINE 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 
32 template<typename T>
OOBTest()33 void 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 
TEST(AddressSanitizer,OOB_char)69 TEST(AddressSanitizer, OOB_char) {
70   OOBTest<U1>();
71 }
72 
TEST(AddressSanitizer,OOB_int)73 TEST(AddressSanitizer, OOB_int) {
74   OOBTest<U4>();
75 }
76 
TEST(AddressSanitizer,OOBRightTest)77 TEST(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 
TEST(AddressSanitizer,LargeOOBRightTest)104 TEST(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 
TEST(AddressSanitizer,DISABLED_DemoOOBLeftLow)114 TEST(AddressSanitizer, DISABLED_DemoOOBLeftLow) {
115   oob_test<U1>(10, -1);
116 }
117 
TEST(AddressSanitizer,DISABLED_DemoOOBLeftHigh)118 TEST(AddressSanitizer, DISABLED_DemoOOBLeftHigh) {
119   oob_test<U1>(kLargeMalloc, -1);
120 }
121 
TEST(AddressSanitizer,DISABLED_DemoOOBRightLow)122 TEST(AddressSanitizer, DISABLED_DemoOOBRightLow) {
123   oob_test<U1>(10, 10);
124 }
125 
TEST(AddressSanitizer,DISABLED_DemoOOBRightHigh)126 TEST(AddressSanitizer, DISABLED_DemoOOBRightHigh) {
127   oob_test<U1>(kLargeMalloc, kLargeMalloc);
128 }
129