For wild addresses in the shadow or shadow gap areas print an error message instead of crashing on a check.
Add AddressSanitizer.MemsetWildAddressTest that makes sure a proper error message is printed. llvm-svn: 160620
This commit is contained in:
parent
9056076cab
commit
7f3e84c9fd
|
|
@ -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); \
|
||||
} \
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 };
|
||||
|
|
|
|||
Loading…
Reference in New Issue