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 <stdio.h> 14 15 #include <gtest/gtest.h> 16 17 #define NOINLINE __attribute__((noinline)) 18 19 typedef uint8_t U1; 20 typedef uint16_t U2; 21 typedef uint32_t U4; 22 typedef uint64_t U8; 23 24 const size_t kLargeMalloc = 1 << 24; 25 26 // Make the compiler thinks that something is going on there. 27 inline void break_optimization(void *arg) { 28 #if !defined(_WIN32) || defined(__clang__) 29 __asm__ __volatile__("" : : "r" (arg) : "memory"); 30 #endif 31 } 32 33 NOINLINE void *malloc_fff(size_t size) { 34 void *res = malloc/**/(size); break_optimization(0); return res;} 35 NOINLINE void *malloc_eee(size_t size) { 36 void *res = malloc_fff(size); break_optimization(0); return res;} 37 NOINLINE void *malloc_ddd(size_t size) { 38 void *res = malloc_eee(size); break_optimization(0); return res;} 39 NOINLINE void *malloc_ccc(size_t size) { 40 void *res = malloc_ddd(size); break_optimization(0); return res;} 41 NOINLINE void *malloc_bbb(size_t size) { 42 void *res = malloc_ccc(size); break_optimization(0); return res;} 43 NOINLINE void *malloc_aaa(size_t size) { 44 void *res = malloc_bbb(size); break_optimization(0); return res;} 45 46 NOINLINE void free_ccc(void *p) { free(p); break_optimization(0);} 47 NOINLINE void free_bbb(void *p) { free_ccc(p); break_optimization(0);} 48 NOINLINE void free_aaa(void *p) { free_bbb(p); break_optimization(0);} 49 50 template<typename T> 51 NOINLINE void asan_write(T *a) { 52 *a = 0; 53 } 54 55 template<typename T> 56 NOINLINE void oob_test(int size, int off) { 57 char *p = (char*)malloc_aaa(size); 58 // fprintf(stderr, "writing %d byte(s) into [%p,%p) with offset %d\n", 59 // sizeof(T), p, p + size, off); 60 asan_write((T*)(p + off)); 61 free_aaa(p); 62 } 63 64 template<typename T> 65 void OOBTest() { 66 char expected_str[100]; 67 for (int size = sizeof(T); size < 20; size += 5) { 68 for (int i = -5; i < 0; i++) { 69 const char *str = 70 "is located.*%d byte.*to the left"; 71 sprintf(expected_str, str, abs(i)); 72 EXPECT_DEATH(oob_test<T>(size, i), expected_str); 73 } 74 75 for (int i = 0; i < (int)(size - sizeof(T) + 1); i++) 76 oob_test<T>(size, i); 77 78 for (int i = size - sizeof(T) + 1; i <= (int)(size + 2 * sizeof(T)); i++) { 79 const char *str = 80 "is located.*%d byte.*to the right"; 81 int off = i >= size ? (i - size) : 0; 82 // we don't catch unaligned partially OOB accesses. 83 if (i % sizeof(T)) continue; 84 sprintf(expected_str, str, off); 85 EXPECT_DEATH(oob_test<T>(size, i), expected_str); 86 } 87 } 88 89 EXPECT_DEATH(oob_test<T>(kLargeMalloc, -1), 90 "is located.*1 byte.*to the left"); 91 EXPECT_DEATH(oob_test<T>(kLargeMalloc, kLargeMalloc), 92 "is located.*0 byte.*to the right"); 93 } 94 95 TEST(AddressSanitizer, OOB_char) { 96 OOBTest<U1>(); 97 } 98 99 TEST(AddressSanitizer, OOB_int) { 100 OOBTest<U4>(); 101 } 102