Rename DescribeHeapAddress to DescribeAddressIfHeap and split it into a function to get all the information about the address, and one to print it.

Summary:
Replacement for part of D23518
This deals with heap addresses, and renames DescribeHeapAddress.
Requires D23520, which moves code around to make it accessible in asan_describers.cc (and still accessible in asan_report.cc if needed).

Reviewers: kcc, samsonov

Subscribers: kubabrecka, llvm-commits

Differential Revision: https://reviews.llvm.org/D23569

llvm-svn: 278917
This commit is contained in:
Filipe Cabecinhas 2016-08-17 09:16:08 +00:00
parent d43ae376d4
commit e068de5137
6 changed files with 162 additions and 77 deletions

View File

@ -673,6 +673,9 @@ uptr AsanChunkView::End() { return Beg() + UsedSize(); }
uptr AsanChunkView::UsedSize() { return chunk_->UsedSize(); }
uptr AsanChunkView::AllocTid() { return chunk_->alloc_tid; }
uptr AsanChunkView::FreeTid() { return chunk_->free_tid; }
AllocType AsanChunkView::AllocType() {
return (enum AllocType)chunk_->alloc_type;
}
static StackTrace GetStackTraceFromId(u32 id) {
CHECK(id);

View File

@ -62,6 +62,7 @@ class AsanChunkView {
u32 GetFreeStackId();
StackTrace GetAllocStack();
StackTrace GetFreeStack();
AllocType AllocType();
bool AddrIsInside(uptr addr, uptr access_size, sptr *offset) {
if (addr >= Beg() && (addr + access_size) <= End()) {
*offset = addr - Beg();

View File

@ -101,4 +101,124 @@ bool GetShadowAddressInformation(uptr addr, ShadowAddressDescription *descr) {
return true;
}
// Heap descriptions
static void GetAccessToHeapChunkInformation(ChunkAccess *descr,
AsanChunkView chunk, uptr addr,
uptr access_size) {
descr->bad_addr = addr;
if (chunk.AddrIsAtLeft(addr, access_size, &descr->offset)) {
descr->access_type = kAccessTypeLeft;
} else if (chunk.AddrIsAtRight(addr, access_size, &descr->offset)) {
descr->access_type = kAccessTypeRight;
if (descr->offset < 0) {
descr->bad_addr -= descr->offset;
descr->offset = 0;
}
} else if (chunk.AddrIsInside(addr, access_size, &descr->offset)) {
descr->access_type = kAccessTypeInside;
} else {
descr->access_type = kAccessTypeUnknown;
}
descr->chunk_begin = chunk.Beg();
descr->chunk_size = chunk.UsedSize();
descr->alloc_type = chunk.AllocType();
}
static void PrintHeapChunkAccess(uptr addr, const ChunkAccess &descr) {
Decorator d;
InternalScopedString str(4096);
str.append("%s", d.Location());
switch (descr.access_type) {
case kAccessTypeLeft:
str.append("%p is located %zd bytes to the left of",
(void *)descr.bad_addr, descr.offset);
break;
case kAccessTypeRight:
str.append("%p is located %zd bytes to the right of",
(void *)descr.bad_addr, descr.offset);
break;
case kAccessTypeInside:
str.append("%p is located %zd bytes inside of", (void *)descr.bad_addr,
descr.offset);
break;
case kAccessTypeUnknown:
str.append(
"%p is located somewhere around (this is AddressSanitizer bug!)",
(void *)descr.bad_addr);
}
str.append(" %zu-byte region [%p,%p)\n", descr.chunk_size,
(void *)descr.chunk_begin,
(void *)(descr.chunk_begin + descr.chunk_size));
str.append("%s", d.EndLocation());
Printf("%s", str.data());
}
bool GetHeapAddressInformation(uptr addr, uptr access_size,
HeapAddressDescription *descr) {
AsanChunkView chunk = FindHeapChunkByAddress(addr);
if (!chunk.IsValid()) {
return false;
}
descr->addr = addr;
GetAccessToHeapChunkInformation(&descr->chunk_access, chunk, addr,
access_size);
CHECK_NE(chunk.AllocTid(), kInvalidTid);
descr->alloc_tid = chunk.AllocTid();
descr->alloc_stack_id = chunk.GetAllocStackId();
descr->free_tid = chunk.FreeTid();
if (descr->free_tid != kInvalidTid)
descr->free_stack_id = chunk.GetFreeStackId();
return true;
}
static StackTrace GetStackTraceFromId(u32 id) {
CHECK(id);
StackTrace res = StackDepotGet(id);
CHECK(res.trace);
return res;
}
bool DescribeAddressIfHeap(uptr addr, uptr access_size) {
HeapAddressDescription descr;
if (!GetHeapAddressInformation(addr, access_size, &descr)) {
Printf(
"AddressSanitizer can not describe address in more detail "
"(wild memory access suspected).\n");
return false;
}
PrintHeapChunkAccess(addr, descr.chunk_access);
asanThreadRegistry().CheckLocked();
AsanThreadContext *alloc_thread =
GetThreadContextByTidLocked(descr.alloc_tid);
StackTrace alloc_stack = GetStackTraceFromId(descr.alloc_stack_id);
char tname[128];
Decorator d;
AsanThreadContext *free_thread = nullptr;
if (descr.free_tid != kInvalidTid) {
free_thread = GetThreadContextByTidLocked(descr.free_tid);
Printf("%sfreed by thread T%d%s here:%s\n", d.Allocation(),
free_thread->tid,
ThreadNameWithParenthesis(free_thread, tname, sizeof(tname)),
d.EndAllocation());
StackTrace free_stack = GetStackTraceFromId(descr.free_stack_id);
free_stack.Print();
Printf("%spreviously allocated by thread T%d%s here:%s\n", d.Allocation(),
alloc_thread->tid,
ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)),
d.EndAllocation());
} else {
Printf("%sallocated by thread T%d%s here:%s\n", d.Allocation(),
alloc_thread->tid,
ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)),
d.EndAllocation());
}
alloc_stack.Print();
DescribeThread(GetCurrentThread());
if (free_thread) DescribeThread(free_thread);
DescribeThread(alloc_thread);
return true;
}
} // namespace __asan

View File

@ -13,7 +13,7 @@
// TODO(filcab): Most struct definitions should move to the interface headers.
//===----------------------------------------------------------------------===//
#include "asan_internal.h"
#include "asan_allocator.h"
#include "asan_thread.h"
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_report_decorator.h"
@ -94,4 +94,33 @@ struct ShadowAddressDescription {
bool GetShadowAddressInformation(uptr addr, ShadowAddressDescription *descr);
bool DescribeAddressIfShadow(uptr addr);
enum AccessType {
kAccessTypeLeft,
kAccessTypeRight,
kAccessTypeInside,
kAccessTypeUnknown, // This means we have an AddressSanitizer bug!
};
struct ChunkAccess {
uptr bad_addr;
sptr offset;
uptr chunk_begin;
uptr chunk_size;
u32 access_type : 2;
u32 alloc_type : 2;
};
struct HeapAddressDescription {
uptr addr;
uptr alloc_tid;
uptr free_tid;
u32 alloc_stack_id;
u32 free_stack_id;
ChunkAccess chunk_access;
};
bool GetHeapAddressInformation(uptr addr, uptr access_size,
HeapAddressDescription *descr);
bool DescribeAddressIfHeap(uptr addr, uptr access_size = 1);
} // namespace __asan

View File

@ -417,73 +417,6 @@ bool DescribeAddressIfStack(uptr addr, uptr access_size) {
return true;
}
static void DescribeAccessToHeapChunk(AsanChunkView chunk, uptr addr,
uptr access_size) {
sptr offset;
Decorator d;
InternalScopedString str(4096);
str.append("%s", d.Location());
if (chunk.AddrIsAtLeft(addr, access_size, &offset)) {
str.append("%p is located %zd bytes to the left of", (void *)addr, offset);
} else if (chunk.AddrIsAtRight(addr, access_size, &offset)) {
if (offset < 0) {
addr -= offset;
offset = 0;
}
str.append("%p is located %zd bytes to the right of", (void *)addr, offset);
} else if (chunk.AddrIsInside(addr, access_size, &offset)) {
str.append("%p is located %zd bytes inside of", (void*)addr, offset);
} else {
str.append("%p is located somewhere around (this is AddressSanitizer bug!)",
(void *)addr);
}
str.append(" %zu-byte region [%p,%p)\n", chunk.UsedSize(),
(void *)(chunk.Beg()), (void *)(chunk.End()));
str.append("%s", d.EndLocation());
Printf("%s", str.data());
}
void DescribeHeapAddress(uptr addr, uptr access_size) {
AsanChunkView chunk = FindHeapChunkByAddress(addr);
if (!chunk.IsValid()) {
Printf("AddressSanitizer can not describe address in more detail "
"(wild memory access suspected).\n");
return;
}
DescribeAccessToHeapChunk(chunk, addr, access_size);
CHECK_NE(chunk.AllocTid(), kInvalidTid);
asanThreadRegistry().CheckLocked();
AsanThreadContext *alloc_thread =
GetThreadContextByTidLocked(chunk.AllocTid());
StackTrace alloc_stack = chunk.GetAllocStack();
char tname[128];
Decorator d;
AsanThreadContext *free_thread = nullptr;
if (chunk.FreeTid() != kInvalidTid) {
free_thread = GetThreadContextByTidLocked(chunk.FreeTid());
Printf("%sfreed by thread T%d%s here:%s\n", d.Allocation(),
free_thread->tid,
ThreadNameWithParenthesis(free_thread, tname, sizeof(tname)),
d.EndAllocation());
StackTrace free_stack = chunk.GetFreeStack();
free_stack.Print();
Printf("%spreviously allocated by thread T%d%s here:%s\n",
d.Allocation(), alloc_thread->tid,
ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)),
d.EndAllocation());
} else {
Printf("%sallocated by thread T%d%s here:%s\n", d.Allocation(),
alloc_thread->tid,
ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)),
d.EndAllocation());
}
alloc_stack.Print();
DescribeThread(GetCurrentThread());
if (free_thread)
DescribeThread(free_thread);
DescribeThread(alloc_thread);
}
static void DescribeAddress(uptr addr, uptr access_size, const char *bug_type) {
// Check if this is shadow or shadow gap.
if (DescribeAddressIfShadow(addr))
@ -494,7 +427,7 @@ static void DescribeAddress(uptr addr, uptr access_size, const char *bug_type) {
if (DescribeAddressIfStack(addr, access_size))
return;
// Assume it is a heap address.
DescribeHeapAddress(addr, access_size);
DescribeAddressIfHeap(addr, access_size);
}
// -------------------- Different kinds of reports ----------------- {{{1
@ -685,7 +618,7 @@ void ReportDoubleFree(uptr addr, BufferedStackTrace *free_stack) {
ScarinessScore::PrintSimple(42, "double-free");
GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp);
stack.Print();
DescribeHeapAddress(addr, 1);
DescribeAddressIfHeap(addr);
ReportErrorSummary("double-free", &stack);
}
@ -708,7 +641,7 @@ void ReportNewDeleteSizeMismatch(uptr addr, uptr alloc_size, uptr delete_size,
ScarinessScore::PrintSimple(10, "new-delete-type-mismatch");
GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp);
stack.Print();
DescribeHeapAddress(addr, 1);
DescribeAddressIfHeap(addr);
ReportErrorSummary("new-delete-type-mismatch", &stack);
Report("HINT: if you don't care about these errors you may set "
"ASAN_OPTIONS=new_delete_type_mismatch=0\n");
@ -728,7 +661,7 @@ void ReportFreeNotMalloced(uptr addr, BufferedStackTrace *free_stack) {
ScarinessScore::PrintSimple(40, "bad-free");
GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp);
stack.Print();
DescribeHeapAddress(addr, 1);
DescribeAddressIfHeap(addr);
ReportErrorSummary("bad-free", &stack);
}
@ -750,7 +683,7 @@ void ReportAllocTypeMismatch(uptr addr, BufferedStackTrace *free_stack,
ScarinessScore::PrintSimple(10, "alloc-dealloc-mismatch");
GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp);
stack.Print();
DescribeHeapAddress(addr, 1);
DescribeAddressIfHeap(addr);
ReportErrorSummary("alloc-dealloc-mismatch", &stack);
Report("HINT: if you don't care about these errors you may set "
"ASAN_OPTIONS=alloc_dealloc_mismatch=0\n");
@ -765,7 +698,7 @@ void ReportMallocUsableSizeNotOwned(uptr addr, BufferedStackTrace *stack) {
"not owned: %p\n", addr);
Printf("%s", d.EndWarning());
stack->Print();
DescribeHeapAddress(addr, 1);
DescribeAddressIfHeap(addr);
ReportErrorSummary("bad-malloc_usable_size", stack);
}
@ -779,7 +712,7 @@ void ReportSanitizerGetAllocatedSizeNotOwned(uptr addr,
"not owned: %p\n", addr);
Printf("%s", d.EndWarning());
stack->Print();
DescribeHeapAddress(addr, 1);
DescribeAddressIfHeap(addr);
ReportErrorSummary("bad-__sanitizer_get_allocated_size", stack);
}
@ -903,7 +836,7 @@ void ReportMacMzReallocUnknown(uptr addr, uptr zone_ptr, const char *zone_name,
addr);
PrintZoneForPointer(addr, zone_ptr, zone_name);
stack->Print();
DescribeHeapAddress(addr, 1);
DescribeAddressIfHeap(addr);
}
// -------------- SuppressErrorReport -------------- {{{1

View File

@ -40,7 +40,6 @@ int GetGlobalsForAddress(uptr addr, __asan_global *globals, u32 *reg_sites,
bool GetInfoForAddressIfGlobal(uptr addr, AddressDescription *descr);
// The following functions prints address description depending
// on the memory type (shadow/heap/stack/global).
void DescribeHeapAddress(uptr addr, uptr access_size);
bool ParseFrameDescription(const char *frame_descr,
InternalMmapVector<StackVarDescr> *vars);
bool DescribeAddressIfStack(uptr addr, uptr access_size);