1 //===-- asan_oob_test.cpp -------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file is a part of AddressSanitizer, an address sanity checker.
11 //===----------------------------------------------------------------------===//
12 #include "asan_test_utils.h"
15 // Tests using unaligned accesses cannot work on strict-alignment targets.
16 #define SKIP_ON_STRICT_ALIGNMENT(x) DISABLED_##x
18 #define SKIP_ON_STRICT_ALIGNMENT(x) x
21 NOINLINE
void asan_write_sized_aligned(uint8_t *p
, size_t size
) {
22 EXPECT_EQ(0U, ((uintptr_t)p
% size
));
23 if (size
== 1) asan_write((uint8_t*)p
);
24 else if (size
== 2) asan_write((uint16_t*)p
);
25 else if (size
== 4) asan_write((uint32_t*)p
);
26 else if (size
== 8) asan_write((uint64_t*)p
);
30 NOINLINE
void oob_test(int size
, int off
) {
31 char *p
= (char*)malloc_aaa(size
);
32 // fprintf(stderr, "writing %d byte(s) into [%p,%p) with offset %d\n",
33 // sizeof(T), p, p + size, off);
34 asan_write((T
*)(p
+ off
));
38 static std::string
GetLeftOOBMessage(int off
) {
40 sprintf(str
, "is located.*%d byte.*before", off
);
44 static std::string
GetRightOOBMessage(int off
) {
47 // FIXME: Fix PR42868 and remove SEGV match.
48 sprintf(str
, "is located.*%d byte.*after|SEGV", off
);
50 // `|` doesn't work in googletest's regexes on Windows,
51 // see googletest/docs/advanced.md#regular-expression-syntax
52 // But it's not needed on Windows anyways.
53 sprintf(str
, "is located.*%d byte.*after", off
);
60 for (int size
= sizeof(T
); size
< 20; size
+= 5) {
61 for (int i
= -5; i
< 0; i
++)
62 EXPECT_DEATH(oob_test
<T
>(size
, i
), GetLeftOOBMessage(-i
));
64 for (int i
= 0; i
< (int)(size
- sizeof(T
) + 1); i
++)
67 for (int i
= size
- sizeof(T
) + 1; i
<= (int)(size
+ 2 * sizeof(T
)); i
++) {
68 // we don't catch unaligned partially OOB accesses.
69 if (i
% sizeof(T
)) continue;
70 int off
= i
>= size
? (i
- size
) : 0;
71 EXPECT_DEATH(oob_test
<T
>(size
, i
), GetRightOOBMessage(off
));
75 EXPECT_DEATH(oob_test
<T
>(kLargeMalloc
, -1), GetLeftOOBMessage(1));
76 EXPECT_DEATH(oob_test
<T
>(kLargeMalloc
, kLargeMalloc
), GetRightOOBMessage(0));
79 // TODO(glider): the following tests are EXTREMELY slow on Darwin:
80 // AddressSanitizer.OOB_char (125503 ms)
81 // AddressSanitizer.OOB_int (126890 ms)
82 // AddressSanitizer.OOBRightTest (315605 ms)
83 // AddressSanitizer.SimpleStackTest (366559 ms)
85 TEST(AddressSanitizer
, OOB_char
) {
89 TEST(AddressSanitizer
, SKIP_ON_STRICT_ALIGNMENT(OOB_int
)) {
93 TEST(AddressSanitizer
, OOBRightTest
) {
94 size_t max_access_size
= SANITIZER_WORDSIZE
== 64 ? 8 : 4;
95 for (size_t access_size
= 1; access_size
<= max_access_size
;
97 for (size_t alloc_size
= 1; alloc_size
<= 8; alloc_size
++) {
98 for (size_t offset
= 0; offset
<= 8; offset
+= access_size
) {
99 void *p
= malloc(alloc_size
);
100 // allocated: [p, p + alloc_size)
101 // accessed: [p + offset, p + offset + access_size)
102 uint8_t *addr
= (uint8_t*)p
+ offset
;
103 if (offset
+ access_size
<= alloc_size
) {
104 asan_write_sized_aligned(addr
, access_size
);
106 int outside_bytes
= offset
> alloc_size
? (offset
- alloc_size
) : 0;
107 EXPECT_DEATH(asan_write_sized_aligned(addr
, access_size
),
108 GetRightOOBMessage(outside_bytes
));
116 TEST(AddressSanitizer
, LargeOOBRightTest
) {
117 size_t large_power_of_two
= 1 << 19;
118 for (size_t i
= 16; i
<= 256; i
*= 2) {
119 size_t size
= large_power_of_two
- i
;
120 char *p
= Ident(new char[size
]);
121 EXPECT_DEATH(p
[size
] = 0, GetRightOOBMessage(0));
126 TEST(AddressSanitizer
, DISABLED_DemoOOBLeftLow
) {
127 oob_test
<U1
>(10, -1);
130 TEST(AddressSanitizer
, DISABLED_DemoOOBLeftHigh
) {
131 oob_test
<U1
>(kLargeMalloc
, -1);
134 TEST(AddressSanitizer
, DISABLED_DemoOOBRightLow
) {
135 oob_test
<U1
>(10, 10);
138 TEST(AddressSanitizer
, DISABLED_DemoOOBRightHigh
) {
139 oob_test
<U1
>(kLargeMalloc
, kLargeMalloc
);