Index: lib/asan/asan_errors.h =================================================================== --- lib/asan/asan_errors.h +++ lib/asan/asan_errors.h @@ -172,6 +172,7 @@ stack(stack_), addr_description(addr, /*shouldLockThreadRegistry=*/false) { scariness.Clear(); + scariness.Scare(10, "bad-malloc_usable_size"); } void Print(); }; @@ -189,6 +190,7 @@ stack(stack_), addr_description(addr, /*shouldLockThreadRegistry=*/false) { scariness.Clear(); + scariness.Scare(10, "bad-__sanitizer_get_allocated_size"); } void Print(); }; @@ -258,7 +260,10 @@ 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 @@ 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 @@ 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 @@ // 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) }; Index: lib/asan/asan_errors.cc =================================================================== --- lib/asan/asan_errors.cc +++ lib/asan/asan_errors.cc @@ -26,8 +26,8 @@ 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 @@ 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) { @@ -87,9 +87,9 @@ 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(); @@ -97,7 +97,7 @@ second_free_stack->top_frame_bp); stack.Print(); addr_description.Print(); - ReportErrorSummary("double-free", &stack); + ReportErrorSummary(scariness.GetDescription(), &stack); } void ErrorNewDeleteSizeMismatch::Print() { @@ -105,9 +105,9 @@ 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( @@ -119,7 +119,7 @@ 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"); @@ -140,7 +140,7 @@ 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() { @@ -151,7 +151,8 @@ 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()); @@ -160,7 +161,7 @@ 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"); @@ -176,7 +177,7 @@ Printf("%s", d.EndWarning()); stack->Print(); addr_description.Print(); - ReportErrorSummary("bad-malloc_usable_size", stack); + ReportErrorSummary(scariness.GetDescription(), stack); } void ErrorSanitizerGetAllocatedSizeNotOwned::Print() { @@ -189,7 +190,7 @@ Printf("%s", d.EndWarning()); stack->Print(); addr_description.Print(); - ReportErrorSummary("bad-__sanitizer_get_allocated_size", stack); + ReportErrorSummary(scariness.GetDescription(), stack); } void ErrorStringFunctionMemoryRangesOverlap::Print() { @@ -214,13 +215,13 @@ 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() { @@ -236,13 +237,14 @@ 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); @@ -262,23 +264,22 @@ "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) { Index: lib/asan/asan_report.cc =================================================================== --- lib/asan/asan_report.cc +++ lib/asan/asan_report.cc @@ -427,7 +427,7 @@ } 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_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 @@ 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" { Index: test/asan/TestCases/debug_double_free.cc =================================================================== --- test/asan/TestCases/debug_double_free.cc +++ test/asan/TestCases/debug_double_free.cc @@ -0,0 +1,32 @@ +// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s + +#include +#include +#include + +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