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:
Alexander Potapenko 2012-07-23 08:22:27 +00:00
parent 9056076cab
commit 7f3e84c9fd
4 changed files with 66 additions and 21 deletions

View File

@ -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); \
} \

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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 };