1 //===-- asan_oob_test.cpp -------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file is a part of AddressSanitizer, an address sanity checker. 10 // 11 //===----------------------------------------------------------------------===// 12 #include "asan_test_utils.h" 13 14 NOINLINE void asan_write_sized_aligned(uint8_t *p, size_t size) { 15 EXPECT_EQ(0U, ((uintptr_t)p % size)); 16 if (size == 1) asan_write((uint8_t*)p); 17 else if (size == 2) asan_write((uint16_t*)p); 18 else if (size == 4) asan_write((uint32_t*)p); 19 else if (size == 8) asan_write((uint64_t*)p); 20 } 21 22 template<typename T> 23 NOINLINE void oob_test(int size, int off) { 24 char *p = (char*)malloc_aaa(size); 25 // fprintf(stderr, "writing %d byte(s) into [%p,%p) with offset %d\n", 26 // sizeof(T), p, p + size, off); 27 asan_write((T*)(p + off)); 28 free_aaa(p); 29 } 30 31 static std::string GetLeftOOBMessage(int off) { 32 char str[100]; 33 sprintf(str, "is located.*%d byte.*to the left", off); 34 return str; 35 } 36 37 static std::string GetRightOOBMessage(int off) { 38 char str[100]; 39 #if !defined(_WIN32) 40 // FIXME: Fix PR42868 and remove SEGV match. 41 sprintf(str, "is located.*%d byte.*to the right|SEGV", off); 42 #else 43 // `|` doesn't work in googletest's regexes on Windows, 44 // see googletest/docs/advanced.md#regular-expression-syntax 45 // But it's not needed on Windows anyways. 46 sprintf(str, "is located.*%d byte.*to the right", off); 47 #endif 48 return str; 49 } 50 51 template<typename T> 52 void OOBTest() { 53 for (int size = sizeof(T); size < 20; size += 5) { 54 for (int i = -5; i < 0; i++) 55 EXPECT_DEATH(oob_test<T>(size, i), GetLeftOOBMessage(-i)); 56 57 for (int i = 0; i < (int)(size - sizeof(T) + 1); i++) 58 oob_test<T>(size, i); 59 60 for (int i = size - sizeof(T) + 1; i <= (int)(size + 2 * sizeof(T)); i++) { 61 // we don't catch unaligned partially OOB accesses. 62 if (i % sizeof(T)) continue; 63 int off = i >= size ? (i - size) : 0; 64 EXPECT_DEATH(oob_test<T>(size, i), GetRightOOBMessage(off)); 65 } 66 } 67 68 EXPECT_DEATH(oob_test<T>(kLargeMalloc, -1), GetLeftOOBMessage(1)); 69 EXPECT_DEATH(oob_test<T>(kLargeMalloc, kLargeMalloc), GetRightOOBMessage(0)); 70 } 71 72 // TODO(glider): the following tests are EXTREMELY slow on Darwin: 73 // AddressSanitizer.OOB_char (125503 ms) 74 // AddressSanitizer.OOB_int (126890 ms) 75 // AddressSanitizer.OOBRightTest (315605 ms) 76 // AddressSanitizer.SimpleStackTest (366559 ms) 77 78 TEST(AddressSanitizer, OOB_char) { 79 OOBTest<U1>(); 80 } 81 82 TEST(AddressSanitizer, OOB_int) { 83 OOBTest<U4>(); 84 } 85 86 TEST(AddressSanitizer, OOBRightTest) { 87 size_t max_access_size = SANITIZER_WORDSIZE == 64 ? 8 : 4; 88 for (size_t access_size = 1; access_size <= max_access_size; 89 access_size *= 2) { 90 for (size_t alloc_size = 1; alloc_size <= 8; alloc_size++) { 91 for (size_t offset = 0; offset <= 8; offset += access_size) { 92 void *p = malloc(alloc_size); 93 // allocated: [p, p + alloc_size) 94 // accessed: [p + offset, p + offset + access_size) 95 uint8_t *addr = (uint8_t*)p + offset; 96 if (offset + access_size <= alloc_size) { 97 asan_write_sized_aligned(addr, access_size); 98 } else { 99 int outside_bytes = offset > alloc_size ? (offset - alloc_size) : 0; 100 EXPECT_DEATH(asan_write_sized_aligned(addr, access_size), 101 GetRightOOBMessage(outside_bytes)); 102 } 103 free(p); 104 } 105 } 106 } 107 } 108 109 TEST(AddressSanitizer, LargeOOBRightTest) { 110 size_t large_power_of_two = 1 << 19; 111 for (size_t i = 16; i <= 256; i *= 2) { 112 size_t size = large_power_of_two - i; 113 char *p = Ident(new char[size]); 114 EXPECT_DEATH(p[size] = 0, GetRightOOBMessage(0)); 115 delete [] p; 116 } 117 } 118 119 TEST(AddressSanitizer, DISABLED_DemoOOBLeftLow) { 120 oob_test<U1>(10, -1); 121 } 122 123 TEST(AddressSanitizer, DISABLED_DemoOOBLeftHigh) { 124 oob_test<U1>(kLargeMalloc, -1); 125 } 126 127 TEST(AddressSanitizer, DISABLED_DemoOOBRightLow) { 128 oob_test<U1>(10, 10); 129 } 130 131 TEST(AddressSanitizer, DISABLED_DemoOOBRightHigh) { 132 oob_test<U1>(kLargeMalloc, kLargeMalloc); 133 } 134