diff options
-rw-r--r-- | compiler-rt/lib/asan/asan_interceptors.cc | 2 | ||||
-rw-r--r-- | compiler-rt/lib/asan/asan_mapping.h | 4 | ||||
-rw-r--r-- | compiler-rt/lib/asan/asan_rtl.cc | 66 | ||||
-rw-r--r-- | compiler-rt/lib/asan/tests/asan_noinst_test.cc | 15 |
4 files changed, 66 insertions, 21 deletions
diff --git a/compiler-rt/lib/asan/asan_interceptors.cc b/compiler-rt/lib/asan/asan_interceptors.cc index 57ee58286fd..29cc15f5868 100644 --- a/compiler-rt/lib/asan/asan_interceptors.cc +++ b/compiler-rt/lib/asan/asan_interceptors.cc @@ -115,7 +115,7 @@ namespace __asan { // Instruments read/write access to a single byte in memory. // On error calls __asan_report_error, which aborts the program. #define ACCESS_ADDRESS(address, isWrite) do { \ - if (AddressIsPoisoned(address)) { \ + if (!AddrIsInMem(address) || AddressIsPoisoned(address)) { \ GET_CURRENT_PC_BP_SP; \ __asan_report_error(pc, bp, sp, address, isWrite, /* access_size */ 1); \ } \ diff --git a/compiler-rt/lib/asan/asan_mapping.h b/compiler-rt/lib/asan/asan_mapping.h index 6bf79a39ca5..8e0c6ec5db2 100644 --- a/compiler-rt/lib/asan/asan_mapping.h +++ b/compiler-rt/lib/asan/asan_mapping.h @@ -97,6 +97,10 @@ static inline bool AddrIsInShadow(uptr a) { return AddrIsInLowShadow(a) || AddrIsInHighShadow(a); } +static inline bool AddrIsInShadowGap(uptr a) { + return a >= kShadowGapBeg && a <= kShadowGapEnd; +} + static inline bool AddrIsAlignedByGranularity(uptr a) { return (a & (SHADOW_GRANULARITY - 1)) == 0; } diff --git a/compiler-rt/lib/asan/asan_rtl.cc b/compiler-rt/lib/asan/asan_rtl.cc index b3a7b16f659..70e4b5715ec 100644 --- a/compiler-rt/lib/asan/asan_rtl.cc +++ b/compiler-rt/lib/asan/asan_rtl.cc @@ -257,7 +257,35 @@ static bool DescribeStackAddress(uptr addr, uptr access_size) { return true; } +static bool DescribeAddrIfShadow(uptr addr) { + if (AddrIsInMem(addr)) + return false; + static const char kAddrInShadowReport[] = + "Address %p is located in the %s.\n"; + if (AddrIsInShadowGap(addr)) { + AsanPrintf(kAddrInShadowReport, addr, "shadow gap area"); + return true; + } + if (AddrIsInHighShadow(addr)) { + AsanPrintf(kAddrInShadowReport, addr, "high shadow area"); + return true; + } + if (AddrIsInLowShadow(addr)) { + AsanPrintf(kAddrInShadowReport, addr, "low shadow area"); + return true; + } + + CHECK(0); // Unreachable. + return false; +} + static NOINLINE void DescribeAddress(uptr addr, uptr access_size) { + // Check if this is shadow or shadow gap. + if (DescribeAddrIfShadow(addr)) + return; + + CHECK(AddrIsInMem(addr)); + // Check if this is a global. if (DescribeAddrIfGlobal(addr)) return; @@ -426,27 +454,27 @@ void __asan_report_error(uptr pc, uptr bp, uptr sp, GET_STACK_TRACE_WITH_PC_AND_BP(kStackTraceMax, pc, bp); stack.PrintStack(); - CHECK(AddrIsInMem(addr)); - DescribeAddress(addr, access_size); - uptr shadow_addr = MemToShadow(addr); - AsanReport("ABORTING\n"); - __asan_print_accumulated_stats(); - AsanPrintf("Shadow byte and word:\n"); - AsanPrintf(" %p: %x\n", (void*)shadow_addr, *(unsigned char*)shadow_addr); - uptr aligned_shadow = shadow_addr & ~(kWordSize - 1); - PrintBytes(" ", (uptr*)(aligned_shadow)); - AsanPrintf("More shadow bytes:\n"); - PrintBytes(" ", (uptr*)(aligned_shadow-4*kWordSize)); - PrintBytes(" ", (uptr*)(aligned_shadow-3*kWordSize)); - PrintBytes(" ", (uptr*)(aligned_shadow-2*kWordSize)); - PrintBytes(" ", (uptr*)(aligned_shadow-1*kWordSize)); - PrintBytes("=>", (uptr*)(aligned_shadow+0*kWordSize)); - PrintBytes(" ", (uptr*)(aligned_shadow+1*kWordSize)); - PrintBytes(" ", (uptr*)(aligned_shadow+2*kWordSize)); - PrintBytes(" ", (uptr*)(aligned_shadow+3*kWordSize)); - PrintBytes(" ", (uptr*)(aligned_shadow+4*kWordSize)); + if (AddrIsInMem(addr)) { + uptr shadow_addr = MemToShadow(addr); + AsanReport("ABORTING\n"); + __asan_print_accumulated_stats(); + AsanPrintf("Shadow byte and word:\n"); + AsanPrintf(" %p: %x\n", (void*)shadow_addr, *(unsigned char*)shadow_addr); + uptr aligned_shadow = shadow_addr & ~(kWordSize - 1); + PrintBytes(" ", (uptr*)(aligned_shadow)); + AsanPrintf("More shadow bytes:\n"); + PrintBytes(" ", (uptr*)(aligned_shadow-4*kWordSize)); + PrintBytes(" ", (uptr*)(aligned_shadow-3*kWordSize)); + PrintBytes(" ", (uptr*)(aligned_shadow-2*kWordSize)); + PrintBytes(" ", (uptr*)(aligned_shadow-1*kWordSize)); + PrintBytes("=>", (uptr*)(aligned_shadow+0*kWordSize)); + PrintBytes(" ", (uptr*)(aligned_shadow+1*kWordSize)); + PrintBytes(" ", (uptr*)(aligned_shadow+2*kWordSize)); + PrintBytes(" ", (uptr*)(aligned_shadow+3*kWordSize)); + PrintBytes(" ", (uptr*)(aligned_shadow+4*kWordSize)); + } if (error_report_callback) { error_report_callback(error_message_buffer); } diff --git a/compiler-rt/lib/asan/tests/asan_noinst_test.cc b/compiler-rt/lib/asan/tests/asan_noinst_test.cc index dca16888313..50192a7d6f4 100644 --- a/compiler-rt/lib/asan/tests/asan_noinst_test.cc +++ b/compiler-rt/lib/asan/tests/asan_noinst_test.cc @@ -21,8 +21,9 @@ #include <assert.h> #include <stdio.h> #include <stdlib.h> -#include <vector> +#include <string.h> // for memset() #include <algorithm> +#include <vector> #include "gtest/gtest.h" // Simple stand-alone pseudorandom number generator. @@ -328,6 +329,18 @@ TEST(AddressSanitizer, ThreadedOneSizeMallocStressTest) { } } +TEST(AddressSanitizer, MemsetWildAddressTest) { + typedef void*(*memset_p)(void*, int, size_t); + // Prevent inlining of memset(). + volatile memset_p libc_memset = (memset_p)memset; + EXPECT_DEATH(libc_memset((void*)(kLowShadowBeg + kPageSize), 0, 100), + "unknown-crash.*low shadow"); + EXPECT_DEATH(libc_memset((void*)(kShadowGapBeg + kPageSize), 0, 100), + "unknown-crash.*shadow gap"); + EXPECT_DEATH(libc_memset((void*)(kHighShadowBeg + kPageSize), 0, 100), + "unknown-crash.*high shadow"); +} + TEST(AddressSanitizerInterface, GetEstimatedAllocatedSize) { EXPECT_EQ(1U, __asan_get_estimated_allocated_size(0)); const size_t sizes[] = { 1, 30, 1<<30 }; |