[asan] Provide bug descriptions for all reports (not just ErrorGeneric)

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

llvm-svn: 288065
This commit is contained in:
Kuba Mracek 2016-11-28 21:18:15 +00:00
parent b3d93889f5
commit 48090f5b82
4 changed files with 78 additions and 31 deletions

View File

@ -26,8 +26,8 @@ void ErrorStackOverflow::Print() {
Decorator d;
Printf("%s", d.Warning());
Report(
"ERROR: AddressSanitizer: stack-overflow on address %p"
" (pc %p bp %p sp %p T%d)\n",
"ERROR: AddressSanitizer: %s on address %p"
" (pc %p bp %p sp %p T%d)\n", scariness.GetDescription(),
(void *)addr, (void *)pc, (void *)bp, (void *)sp, tid);
Printf("%s", d.EndWarning());
scariness.Print();
@ -35,7 +35,7 @@ void ErrorStackOverflow::Print() {
GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, pc, bp, context,
common_flags()->fast_unwind_on_fatal);
stack.Print();
ReportErrorSummary("stack-overflow", &stack);
ReportErrorSummary(scariness.GetDescription(), &stack);
}
static void MaybeDumpInstructionBytes(uptr pc) {
@ -93,9 +93,9 @@ void ErrorDoubleFree::Print() {
Printf("%s", d.Warning());
char tname[128];
Report(
"ERROR: AddressSanitizer: attempting double-free on %p in "
"ERROR: AddressSanitizer: attempting %s on %p in "
"thread T%d%s:\n",
addr_description.addr, tid,
scariness.GetDescription(), addr_description.addr, tid,
ThreadNameWithParenthesis(tid, tname, sizeof(tname)));
Printf("%s", d.EndWarning());
scariness.Print();
@ -103,7 +103,7 @@ void ErrorDoubleFree::Print() {
second_free_stack->top_frame_bp);
stack.Print();
addr_description.Print();
ReportErrorSummary("double-free", &stack);
ReportErrorSummary(scariness.GetDescription(), &stack);
}
void ErrorNewDeleteSizeMismatch::Print() {
@ -111,9 +111,9 @@ void ErrorNewDeleteSizeMismatch::Print() {
Printf("%s", d.Warning());
char tname[128];
Report(
"ERROR: AddressSanitizer: new-delete-type-mismatch on %p in thread "
"ERROR: AddressSanitizer: %s on %p in thread "
"T%d%s:\n",
addr_description.addr, tid,
scariness.GetDescription(), addr_description.addr, tid,
ThreadNameWithParenthesis(tid, tname, sizeof(tname)));
Printf("%s object passed to delete has wrong type:\n", d.EndWarning());
Printf(
@ -125,7 +125,7 @@ void ErrorNewDeleteSizeMismatch::Print() {
GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp);
stack.Print();
addr_description.Print();
ReportErrorSummary("new-delete-type-mismatch", &stack);
ReportErrorSummary(scariness.GetDescription(), &stack);
Report(
"HINT: if you don't care about these errors you may set "
"ASAN_OPTIONS=new_delete_type_mismatch=0\n");
@ -146,7 +146,7 @@ void ErrorFreeNotMalloced::Print() {
GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp);
stack.Print();
addr_description.Print();
ReportErrorSummary("bad-free", &stack);
ReportErrorSummary(scariness.GetDescription(), &stack);
}
void ErrorAllocTypeMismatch::Print() {
@ -157,7 +157,8 @@ void ErrorAllocTypeMismatch::Print() {
CHECK_NE(alloc_type, dealloc_type);
Decorator d;
Printf("%s", d.Warning());
Report("ERROR: AddressSanitizer: alloc-dealloc-mismatch (%s vs %s) on %p\n",
Report("ERROR: AddressSanitizer: %s (%s vs %s) on %p\n",
scariness.GetDescription(),
alloc_names[alloc_type], dealloc_names[dealloc_type],
addr_description.addr);
Printf("%s", d.EndWarning());
@ -166,7 +167,7 @@ void ErrorAllocTypeMismatch::Print() {
GET_STACK_TRACE_FATAL(dealloc_stack->trace[0], dealloc_stack->top_frame_bp);
stack.Print();
addr_description.Print();
ReportErrorSummary("alloc-dealloc-mismatch", &stack);
ReportErrorSummary(scariness.GetDescription(), &stack);
Report(
"HINT: if you don't care about these errors you may set "
"ASAN_OPTIONS=alloc_dealloc_mismatch=0\n");
@ -182,7 +183,7 @@ void ErrorMallocUsableSizeNotOwned::Print() {
Printf("%s", d.EndWarning());
stack->Print();
addr_description.Print();
ReportErrorSummary("bad-malloc_usable_size", stack);
ReportErrorSummary(scariness.GetDescription(), stack);
}
void ErrorSanitizerGetAllocatedSizeNotOwned::Print() {
@ -195,7 +196,7 @@ void ErrorSanitizerGetAllocatedSizeNotOwned::Print() {
Printf("%s", d.EndWarning());
stack->Print();
addr_description.Print();
ReportErrorSummary("bad-__sanitizer_get_allocated_size", stack);
ReportErrorSummary(scariness.GetDescription(), stack);
}
void ErrorStringFunctionMemoryRangesOverlap::Print() {
@ -220,13 +221,13 @@ void ErrorStringFunctionMemoryRangesOverlap::Print() {
void ErrorStringFunctionSizeOverflow::Print() {
Decorator d;
Printf("%s", d.Warning());
const char *bug_type = "negative-size-param";
Report("ERROR: AddressSanitizer: %s: (size=%zd)\n", bug_type, size);
Report("ERROR: AddressSanitizer: %s: (size=%zd)\n",
scariness.GetDescription(), size);
Printf("%s", d.EndWarning());
scariness.Print();
stack->Print();
addr_description.Print();
ReportErrorSummary(bug_type, stack);
ReportErrorSummary(scariness.GetDescription(), stack);
}
void ErrorBadParamsToAnnotateContiguousContainer::Print() {
@ -242,13 +243,14 @@ void ErrorBadParamsToAnnotateContiguousContainer::Print() {
if (!IsAligned(beg, granularity))
Report("ERROR: beg is not aligned by %d\n", granularity);
stack->Print();
ReportErrorSummary("bad-__sanitizer_annotate_contiguous_container", stack);
ReportErrorSummary(scariness.GetDescription(), stack);
}
void ErrorODRViolation::Print() {
Decorator d;
Printf("%s", d.Warning());
Report("ERROR: AddressSanitizer: odr-violation (%p):\n", global1.beg);
Report("ERROR: AddressSanitizer: %s (%p):\n", scariness.GetDescription(),
global1.beg);
Printf("%s", d.EndWarning());
InternalScopedString g1_loc(256), g2_loc(256);
PrintGlobalLocation(&g1_loc, global1);
@ -268,23 +270,22 @@ void ErrorODRViolation::Print() {
"HINT: if you don't care about these errors you may set "
"ASAN_OPTIONS=detect_odr_violation=0\n");
InternalScopedString error_msg(256);
error_msg.append("odr-violation: global '%s' at %s",
error_msg.append("%s: global '%s' at %s", scariness.GetDescription(),
MaybeDemangleGlobalName(global1.name), g1_loc.data());
ReportErrorSummary(error_msg.data());
}
void ErrorInvalidPointerPair::Print() {
const char *bug_type = "invalid-pointer-pair";
Decorator d;
Printf("%s", d.Warning());
Report("ERROR: AddressSanitizer: invalid-pointer-pair: %p %p\n",
Report("ERROR: AddressSanitizer: %s: %p %p\n", scariness.GetDescription(),
addr1_description.Address(), addr2_description.Address());
Printf("%s", d.EndWarning());
GET_STACK_TRACE_FATAL(pc, bp);
stack.Print();
addr1_description.Print();
addr2_description.Print();
ReportErrorSummary(bug_type, &stack);
ReportErrorSummary(scariness.GetDescription(), &stack);
}
static bool AdjacentShadowValuesAreFullyPoisoned(u8 *s) {

View File

@ -172,6 +172,7 @@ struct ErrorMallocUsableSizeNotOwned : ErrorBase {
stack(stack_),
addr_description(addr, /*shouldLockThreadRegistry=*/false) {
scariness.Clear();
scariness.Scare(10, "bad-malloc_usable_size");
}
void Print();
};
@ -189,6 +190,7 @@ struct ErrorSanitizerGetAllocatedSizeNotOwned : ErrorBase {
stack(stack_),
addr_description(addr, /*shouldLockThreadRegistry=*/false) {
scariness.Clear();
scariness.Scare(10, "bad-__sanitizer_get_allocated_size");
}
void Print();
};
@ -258,7 +260,10 @@ struct ErrorBadParamsToAnnotateContiguousContainer : ErrorBase {
beg(beg_),
end(end_),
old_mid(old_mid_),
new_mid(new_mid_) {}
new_mid(new_mid_) {
scariness.Clear();
scariness.Scare(10, "bad-__sanitizer_annotate_contiguous_container");
}
void Print();
};
@ -274,7 +279,10 @@ struct ErrorODRViolation : ErrorBase {
global1(*g1),
global2(*g2),
stack_id1(stack_id1_),
stack_id2(stack_id2_) {}
stack_id2(stack_id2_) {
scariness.Clear();
scariness.Scare(10, "odr-violation");
}
void Print();
};
@ -292,7 +300,10 @@ struct ErrorInvalidPointerPair : ErrorBase {
bp(bp_),
sp(sp_),
addr1_description(p1, 1, /*shouldLockThreadRegistry=*/false),
addr2_description(p2, 1, /*shouldLockThreadRegistry=*/false) {}
addr2_description(p2, 1, /*shouldLockThreadRegistry=*/false) {
scariness.Clear();
scariness.Scare(10, "invalid-pointer-pair");
}
void Print();
};
@ -350,6 +361,7 @@ struct ErrorDescription {
// We can add a wrapper around it to make it "more c++-like", but that would
// add a lot of code and the benefit wouldn't be that big.
union {
ErrorBase Base;
ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_MEMBER)
};

View File

@ -427,7 +427,7 @@ void __asan_describe_address(uptr addr) {
}
int __asan_report_present() {
return ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric;
return ScopedInErrorReport::CurrentError().kind != kErrorKindInvalid;
}
uptr __asan_get_report_pc() {
@ -449,9 +449,11 @@ uptr __asan_get_report_sp() {
}
uptr __asan_get_report_address() {
if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
return ScopedInErrorReport::CurrentError()
.Generic.addr_description.Address();
ErrorDescription &err = ScopedInErrorReport::CurrentError();
if (err.kind == kErrorKindGeneric)
return err.Generic.addr_description.Address();
else if (err.kind == kErrorKindDoubleFree)
return err.DoubleFree.addr_description.addr;
return 0;
}
@ -470,7 +472,7 @@ uptr __asan_get_report_access_size() {
const char *__asan_get_report_description() {
if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
return ScopedInErrorReport::CurrentError().Generic.bug_descr;
return nullptr;
return ScopedInErrorReport::CurrentError().Base.scariness.GetDescription();
}
extern "C" {

View File

@ -0,0 +1,32 @@
// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
#include <sanitizer/asan_interface.h>
#include <stdio.h>
#include <stdlib.h>
char *heap_ptr;
int main() {
heap_ptr = (char *)malloc(10);
fprintf(stderr, "heap_ptr: %p\n", heap_ptr);
// CHECK: heap_ptr: 0x[[ADDR:[0-9a-f]+]]
free(heap_ptr);
free(heap_ptr); // BOOM
return 0;
}
void __asan_on_error() {
int present = __asan_report_present();
void *addr = __asan_get_report_address();
const char *description = __asan_get_report_description();
fprintf(stderr, "%s\n", (present == 1) ? "report present" : "");
// CHECK: report present
fprintf(stderr, "addr: %p\n", addr);
// CHECK: addr: {{0x0*}}[[ADDR]]
fprintf(stderr, "description: %s\n", description);
// CHECK: description: double-free
}
// CHECK: AddressSanitizer: attempting double-free on {{0x0*}}[[ADDR]] in thread T0