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,20 @@ } #endif // SANITIZER_GO +bool IsAccessibleMemoryRange(uptr beg, uptr size) { + 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 res = + !internal_iserror(bytes_written, &write_errno) && bytes_written == size; + internal_close(sock_pair[0]); + internal_close(sock_pair[1]); + return res; +} + } // 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/ubsan/ubsan_diag.cc =================================================================== --- lib/ubsan/ubsan_diag.cc +++ lib/ubsan/ubsan_diag.cc @@ -193,28 +193,44 @@ return Best; } +static inline MemoryLocation subtractNoOverflow(uptr LHS, uptr RHS) { + return (LHS < RHS) ? 0 : LHS - RHS; +} + +static inline MemoryLocation addNoOverflow(uptr LHS, uptr RHS) { + const uptr Limit = (uptr)-1; + return (LHS > Limit - RHS) ? Limit : LHS + RHS; +} + /// Render a snippet of the address space near a location. static void renderMemorySnippet(const Decorator &Decor, MemoryLocation Loc, Range *Ranges, unsigned NumRanges, const Diag::Arg *Args) { - const unsigned BytesToShow = 32; const unsigned MinBytesNearLoc = 4; // Show at least the 8 bytes surrounding Loc. - MemoryLocation Min = Loc - MinBytesNearLoc, Max = Loc + MinBytesNearLoc; + MemoryLocation Min = subtractNoOverflow(Loc, MinBytesNearLoc); + MemoryLocation Max = addNoOverflow(Loc, MinBytesNearLoc); + MemoryLocation OrigMin = Min; for (unsigned I = 0; I < NumRanges; ++I) { Min = __sanitizer::Min(Ranges[I].getStart().getMemoryLocation(), Min); Max = __sanitizer::Max(Ranges[I].getEnd().getMemoryLocation(), Max); } // If we have too many interesting bytes, prefer to show bytes after Loc. + const unsigned BytesToShow = 32; if (Max - Min > BytesToShow) - Min = __sanitizer::Min(Max - BytesToShow, Loc - MinBytesNearLoc); - Max = Min + BytesToShow; + Min = __sanitizer::Min(Max - BytesToShow, OrigMin); + Max = addNoOverflow(Min, BytesToShow); + + // Don't print the contents of inaccessible memory. + 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; } }