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.
break_optimization(void * arg)27 inline void break_optimization(void *arg) {
28 #if !defined(_WIN32) || defined(__clang__)
29 __asm__ __volatile__("" : : "r" (arg) : "memory");
30 #endif
31 }
32
malloc_fff(size_t size)33 NOINLINE void *malloc_fff(size_t size) {
34 void *res = malloc/**/(size); break_optimization(0); return res;}
malloc_eee(size_t size)35 NOINLINE void *malloc_eee(size_t size) {
36 void *res = malloc_fff(size); break_optimization(0); return res;}
malloc_ddd(size_t size)37 NOINLINE void *malloc_ddd(size_t size) {
38 void *res = malloc_eee(size); break_optimization(0); return res;}
malloc_ccc(size_t size)39 NOINLINE void *malloc_ccc(size_t size) {
40 void *res = malloc_ddd(size); break_optimization(0); return res;}
malloc_bbb(size_t size)41 NOINLINE void *malloc_bbb(size_t size) {
42 void *res = malloc_ccc(size); break_optimization(0); return res;}
malloc_aaa(size_t size)43 NOINLINE void *malloc_aaa(size_t size) {
44 void *res = malloc_bbb(size); break_optimization(0); return res;}
45
free_ccc(void * p)46 NOINLINE void free_ccc(void *p) { free(p); break_optimization(0);}
free_bbb(void * p)47 NOINLINE void free_bbb(void *p) { free_ccc(p); break_optimization(0);}
free_aaa(void * p)48 NOINLINE void free_aaa(void *p) { free_bbb(p); break_optimization(0);}
49
50 template<typename T>
asan_write(T * a)51 NOINLINE void asan_write(T *a) {
52 *a = 0;
53 }
54
55 template<typename T>
oob_test(int size,int off)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>
OOBTest()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
TEST(AddressSanitizer,OOB_char)95 TEST(AddressSanitizer, OOB_char) {
96 OOBTest<U1>();
97 }
98
TEST(AddressSanitizer,OOB_int)99 TEST(AddressSanitizer, OOB_int) {
100 OOBTest<U4>();
101 }
102