Index: lib/sanitizer_common/sanitizer_common.h =================================================================== --- lib/sanitizer_common/sanitizer_common.h +++ lib/sanitizer_common/sanitizer_common.h @@ -167,6 +167,8 @@ void *MapFileToMemory(const char *file_name, uptr *buff_size); void *MapWritableFileToMemory(void *addr, uptr size, uptr fd, uptr offset); +bool IsAccessibleMemoryRange(uptr beg, uptr size); + // Error report formatting. const char *StripPathPrefix(const char *filepath, const char *strip_file_prefix); Index: lib/sanitizer_common/sanitizer_posix_libcdep.cc =================================================================== --- lib/sanitizer_common/sanitizer_posix_libcdep.cc +++ lib/sanitizer_common/sanitizer_posix_libcdep.cc @@ -166,6 +166,28 @@ } #endif // SANITIZER_GO +bool IsAccessibleMemoryRange(uptr beg, uptr size) { + uptr page_size = GetPageSizeCached(); + // Checking too large memory ranges is slow. + CHECK_LT(size, page_size * 10); + int sock_pair[2]; + if (pipe(sock_pair)) + return false; + uptr bytes_written = + internal_write(sock_pair[1], reinterpret_cast(beg), size); + int write_errno; + bool result; + if (internal_iserror(bytes_written, &write_errno)) { + CHECK_EQ(EFAULT, write_errno); + result = false; + } else { + result = (bytes_written == size); + } + internal_close(sock_pair[0]); + internal_close(sock_pair[1]); + return result; +} + } // namespace __sanitizer #endif // SANITIZER_POSIX Index: lib/sanitizer_common/sanitizer_win.cc =================================================================== --- lib/sanitizer_common/sanitizer_win.cc +++ lib/sanitizer_common/sanitizer_win.cc @@ -522,6 +522,10 @@ return false; } +bool IsAccessibleMemoryRange(uptr beg, uptr size) { + UNIMPLEMENTED(); +} + } // namespace __sanitizer #endif // _WIN32 Index: lib/sanitizer_common/tests/sanitizer_posix_test.cc =================================================================== --- lib/sanitizer_common/tests/sanitizer_posix_test.cc +++ lib/sanitizer_common/tests/sanitizer_posix_test.cc @@ -18,6 +18,7 @@ #include "gtest/gtest.h" #include +#include namespace __sanitizer { @@ -57,6 +58,23 @@ EXPECT_FALSE(destructor_executed); } +TEST(SanitizerCommon, IsAccessibleMemoryRange) { + const int page_size = GetPageSize(); + uptr mem = (uptr)mmap(0, 3 * page_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + // Protect the middle page. + mprotect((void *)(mem + page_size), page_size, PROT_NONE); + EXPECT_TRUE(IsAccessibleMemoryRange(mem, page_size - 1)); + EXPECT_TRUE(IsAccessibleMemoryRange(mem, page_size)); + EXPECT_FALSE(IsAccessibleMemoryRange(mem, page_size + 1)); + EXPECT_TRUE(IsAccessibleMemoryRange(mem + page_size - 1, 1)); + EXPECT_FALSE(IsAccessibleMemoryRange(mem + page_size - 1, 2)); + EXPECT_FALSE(IsAccessibleMemoryRange(mem + 2 * page_size - 1, 1)); + EXPECT_TRUE(IsAccessibleMemoryRange(mem + 2 * page_size, page_size)); + EXPECT_FALSE(IsAccessibleMemoryRange(mem, 3 * page_size)); + EXPECT_FALSE(IsAccessibleMemoryRange(0x0, 2)); +} + } // namespace __sanitizer #endif // SANITIZER_POSIX Index: lib/ubsan/ubsan_diag.cc =================================================================== --- lib/ubsan/ubsan_diag.cc +++ lib/ubsan/ubsan_diag.cc @@ -222,9 +222,13 @@ Min = __sanitizer::Min(Max - BytesToShow, OrigMin); Max = addNoOverflow(Min, BytesToShow); + if (!IsAccessibleMemoryRange(Min, Max - Min)) { + Printf("\n"); + return; + } + // Emit data. for (uptr P = Min; P != Max; ++P) { - // FIXME: Check that the address is readable before printing it. unsigned char C = *reinterpret_cast(P); Printf("%s%02x", (P % 8 == 0) ? " " : " ", C); } Index: test/ubsan/TestCases/TypeCheck/misaligned.cpp =================================================================== --- test/ubsan/TestCases/TypeCheck/misaligned.cpp +++ test/ubsan/TestCases/TypeCheck/misaligned.cpp @@ -8,6 +8,9 @@ // RUN: %run %t n1 2>&1 | FileCheck %s --check-prefix=CHECK-NEW // RUN: UBSAN_OPTIONS=print_stacktrace=1 %run %t l1 2>&1 | FileCheck %s --check-prefix=CHECK-LOAD --check-prefix=CHECK-%os-STACK-LOAD +// RUN: %clangxx -fsanitize=alignment -fno-sanitize-recover %s -O3 -o %t +// RUN: not %run %t w1 2>&1 | FileCheck %s --check-prefix=CHECK-WILD + #include struct S { @@ -23,6 +26,8 @@ int *p = (int*)&c[4 + argv[1][1] - '0']; S *s = (S*)p; + void *wild = reinterpret_cast(0x123L); + (void)*p; // ok! switch (argv[1][0]) { @@ -74,5 +79,11 @@ // CHECK-NEW-NEXT: {{^ 00 00 00 01 02 03 04 05}} // CHECK-NEW-NEXT: {{^ \^}} return (new (s) S)->k && 0; + + case 'w': + // CHECK-WILD: misaligned.cpp:[[@LINE+3]]:35: runtime error: member access within misaligned address 0x000000000123 for type 'S', which requires 4 byte alignment + // CHECK-WILD-NEXT: 0x000000000123: note: pointer points here + // CHECK-WILD-NEXT: + return static_cast(wild)->k; } }