• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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