13cab2bb3Spatrick //===-- asan_oob_test.cpp -------------------------------------------------===//
23cab2bb3Spatrick //
33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information.
53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63cab2bb3Spatrick //
73cab2bb3Spatrick //===----------------------------------------------------------------------===//
83cab2bb3Spatrick //
93cab2bb3Spatrick // This file is a part of AddressSanitizer, an address sanity checker.
103cab2bb3Spatrick //
113cab2bb3Spatrick //===----------------------------------------------------------------------===//
123cab2bb3Spatrick #include "asan_test_utils.h"
133cab2bb3Spatrick
asan_write_sized_aligned(uint8_t * p,size_t size)143cab2bb3Spatrick NOINLINE void asan_write_sized_aligned(uint8_t *p, size_t size) {
153cab2bb3Spatrick EXPECT_EQ(0U, ((uintptr_t)p % size));
163cab2bb3Spatrick if (size == 1) asan_write((uint8_t*)p);
173cab2bb3Spatrick else if (size == 2) asan_write((uint16_t*)p);
183cab2bb3Spatrick else if (size == 4) asan_write((uint32_t*)p);
193cab2bb3Spatrick else if (size == 8) asan_write((uint64_t*)p);
203cab2bb3Spatrick }
213cab2bb3Spatrick
223cab2bb3Spatrick template<typename T>
oob_test(int size,int off)233cab2bb3Spatrick NOINLINE void oob_test(int size, int off) {
243cab2bb3Spatrick char *p = (char*)malloc_aaa(size);
253cab2bb3Spatrick // fprintf(stderr, "writing %d byte(s) into [%p,%p) with offset %d\n",
263cab2bb3Spatrick // sizeof(T), p, p + size, off);
273cab2bb3Spatrick asan_write((T*)(p + off));
283cab2bb3Spatrick free_aaa(p);
293cab2bb3Spatrick }
303cab2bb3Spatrick
GetLeftOOBMessage(int off)313cab2bb3Spatrick static std::string GetLeftOOBMessage(int off) {
323cab2bb3Spatrick char str[100];
33*810390e3Srobert sprintf(str, "is located.*%d byte.*before", off);
343cab2bb3Spatrick return str;
353cab2bb3Spatrick }
363cab2bb3Spatrick
GetRightOOBMessage(int off)373cab2bb3Spatrick static std::string GetRightOOBMessage(int off) {
383cab2bb3Spatrick char str[100];
393cab2bb3Spatrick #if !defined(_WIN32)
403cab2bb3Spatrick // FIXME: Fix PR42868 and remove SEGV match.
41*810390e3Srobert sprintf(str, "is located.*%d byte.*after|SEGV", off);
423cab2bb3Spatrick #else
433cab2bb3Spatrick // `|` doesn't work in googletest's regexes on Windows,
443cab2bb3Spatrick // see googletest/docs/advanced.md#regular-expression-syntax
453cab2bb3Spatrick // But it's not needed on Windows anyways.
46*810390e3Srobert sprintf(str, "is located.*%d byte.*after", off);
473cab2bb3Spatrick #endif
483cab2bb3Spatrick return str;
493cab2bb3Spatrick }
503cab2bb3Spatrick
513cab2bb3Spatrick template<typename T>
OOBTest()523cab2bb3Spatrick void OOBTest() {
533cab2bb3Spatrick for (int size = sizeof(T); size < 20; size += 5) {
543cab2bb3Spatrick for (int i = -5; i < 0; i++)
553cab2bb3Spatrick EXPECT_DEATH(oob_test<T>(size, i), GetLeftOOBMessage(-i));
563cab2bb3Spatrick
573cab2bb3Spatrick for (int i = 0; i < (int)(size - sizeof(T) + 1); i++)
583cab2bb3Spatrick oob_test<T>(size, i);
593cab2bb3Spatrick
603cab2bb3Spatrick for (int i = size - sizeof(T) + 1; i <= (int)(size + 2 * sizeof(T)); i++) {
613cab2bb3Spatrick // we don't catch unaligned partially OOB accesses.
623cab2bb3Spatrick if (i % sizeof(T)) continue;
633cab2bb3Spatrick int off = i >= size ? (i - size) : 0;
643cab2bb3Spatrick EXPECT_DEATH(oob_test<T>(size, i), GetRightOOBMessage(off));
653cab2bb3Spatrick }
663cab2bb3Spatrick }
673cab2bb3Spatrick
683cab2bb3Spatrick EXPECT_DEATH(oob_test<T>(kLargeMalloc, -1), GetLeftOOBMessage(1));
693cab2bb3Spatrick EXPECT_DEATH(oob_test<T>(kLargeMalloc, kLargeMalloc), GetRightOOBMessage(0));
703cab2bb3Spatrick }
713cab2bb3Spatrick
723cab2bb3Spatrick // TODO(glider): the following tests are EXTREMELY slow on Darwin:
733cab2bb3Spatrick // AddressSanitizer.OOB_char (125503 ms)
743cab2bb3Spatrick // AddressSanitizer.OOB_int (126890 ms)
753cab2bb3Spatrick // AddressSanitizer.OOBRightTest (315605 ms)
763cab2bb3Spatrick // AddressSanitizer.SimpleStackTest (366559 ms)
773cab2bb3Spatrick
TEST(AddressSanitizer,OOB_char)783cab2bb3Spatrick TEST(AddressSanitizer, OOB_char) {
793cab2bb3Spatrick OOBTest<U1>();
803cab2bb3Spatrick }
813cab2bb3Spatrick
TEST(AddressSanitizer,OOB_int)823cab2bb3Spatrick TEST(AddressSanitizer, OOB_int) {
833cab2bb3Spatrick OOBTest<U4>();
843cab2bb3Spatrick }
853cab2bb3Spatrick
TEST(AddressSanitizer,OOBRightTest)863cab2bb3Spatrick TEST(AddressSanitizer, OOBRightTest) {
873cab2bb3Spatrick size_t max_access_size = SANITIZER_WORDSIZE == 64 ? 8 : 4;
883cab2bb3Spatrick for (size_t access_size = 1; access_size <= max_access_size;
893cab2bb3Spatrick access_size *= 2) {
903cab2bb3Spatrick for (size_t alloc_size = 1; alloc_size <= 8; alloc_size++) {
913cab2bb3Spatrick for (size_t offset = 0; offset <= 8; offset += access_size) {
923cab2bb3Spatrick void *p = malloc(alloc_size);
933cab2bb3Spatrick // allocated: [p, p + alloc_size)
943cab2bb3Spatrick // accessed: [p + offset, p + offset + access_size)
953cab2bb3Spatrick uint8_t *addr = (uint8_t*)p + offset;
963cab2bb3Spatrick if (offset + access_size <= alloc_size) {
973cab2bb3Spatrick asan_write_sized_aligned(addr, access_size);
983cab2bb3Spatrick } else {
993cab2bb3Spatrick int outside_bytes = offset > alloc_size ? (offset - alloc_size) : 0;
1003cab2bb3Spatrick EXPECT_DEATH(asan_write_sized_aligned(addr, access_size),
1013cab2bb3Spatrick GetRightOOBMessage(outside_bytes));
1023cab2bb3Spatrick }
1033cab2bb3Spatrick free(p);
1043cab2bb3Spatrick }
1053cab2bb3Spatrick }
1063cab2bb3Spatrick }
1073cab2bb3Spatrick }
1083cab2bb3Spatrick
TEST(AddressSanitizer,LargeOOBRightTest)1093cab2bb3Spatrick TEST(AddressSanitizer, LargeOOBRightTest) {
1103cab2bb3Spatrick size_t large_power_of_two = 1 << 19;
1113cab2bb3Spatrick for (size_t i = 16; i <= 256; i *= 2) {
1123cab2bb3Spatrick size_t size = large_power_of_two - i;
1133cab2bb3Spatrick char *p = Ident(new char[size]);
1143cab2bb3Spatrick EXPECT_DEATH(p[size] = 0, GetRightOOBMessage(0));
1153cab2bb3Spatrick delete [] p;
1163cab2bb3Spatrick }
1173cab2bb3Spatrick }
1183cab2bb3Spatrick
TEST(AddressSanitizer,DISABLED_DemoOOBLeftLow)1193cab2bb3Spatrick TEST(AddressSanitizer, DISABLED_DemoOOBLeftLow) {
1203cab2bb3Spatrick oob_test<U1>(10, -1);
1213cab2bb3Spatrick }
1223cab2bb3Spatrick
TEST(AddressSanitizer,DISABLED_DemoOOBLeftHigh)1233cab2bb3Spatrick TEST(AddressSanitizer, DISABLED_DemoOOBLeftHigh) {
1243cab2bb3Spatrick oob_test<U1>(kLargeMalloc, -1);
1253cab2bb3Spatrick }
1263cab2bb3Spatrick
TEST(AddressSanitizer,DISABLED_DemoOOBRightLow)1273cab2bb3Spatrick TEST(AddressSanitizer, DISABLED_DemoOOBRightLow) {
1283cab2bb3Spatrick oob_test<U1>(10, 10);
1293cab2bb3Spatrick }
1303cab2bb3Spatrick
TEST(AddressSanitizer,DISABLED_DemoOOBRightHigh)1313cab2bb3Spatrick TEST(AddressSanitizer, DISABLED_DemoOOBRightHigh) {
1323cab2bb3Spatrick oob_test<U1>(kLargeMalloc, kLargeMalloc);
1333cab2bb3Spatrick }
134