Index: lib/asan/asan_errors.h =================================================================== --- lib/asan/asan_errors.h +++ lib/asan/asan_errors.h @@ -40,9 +40,24 @@ void Print(); }; +struct ErrorDoubleFree : ErrorBase { + u32 tid; + HeapAddressDescription addr_description; + // ErrorDoubleFree doesn't own the stack trace. + BufferedStackTrace *second_free_stack; + ErrorDoubleFree(uptr addr, u32 tid_, BufferedStackTrace *stack) + : tid(tid_), second_free_stack(stack) { + CHECK_GT(second_free_stack->size, 0); + GetHeapAddressInformation(addr, 1, &addr_description); + scariness.Scare(42, "double-free"); + } + void Print(); +}; + enum ErrorKind { kErrorKindInvalid = 0, kErrorKindStackOverflow, + kErrorKindDoubleFree, }; struct ErrorDescription { @@ -54,11 +69,15 @@ // add a lot of code and the benefit wouldn't be that big. union { ErrorStackOverflow stack_overflow; + ErrorDoubleFree double_free; }; ErrorDescription() { internal_memset(this, 0, sizeof(*this)); } ErrorDescription(const ErrorStackOverflow &e) // NOLINT : kind(kErrorKindStackOverflow), stack_overflow(e) {} + ErrorDescription(const ErrorDoubleFree &e) // NOLINT + : kind(kErrorKindDoubleFree), + double_free(e) {} bool IsValid() { return kind != kErrorKindInvalid; } void Print() { @@ -66,6 +85,9 @@ case kErrorKindStackOverflow: stack_overflow.Print(); return; + case kErrorKindDoubleFree: + double_free.Print(); + return; case kErrorKindInvalid: CHECK(0); } Index: lib/asan/asan_errors.cc =================================================================== --- lib/asan/asan_errors.cc +++ lib/asan/asan_errors.cc @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "asan_errors.h" +#include "asan_descriptions.h" #include "asan_stack.h" namespace __asan { @@ -33,4 +34,21 @@ ReportErrorSummary("stack-overflow", &stack); } +void ErrorDoubleFree::Print() { + Decorator d; + Printf("%s", d.Warning()); + char tname[128]; + Report( + "ERROR: AddressSanitizer: attempting double-free on %p in " + "thread T%d%s:\n", + addr_description.addr, tid, + ThreadNameWithParenthesis(tid, tname, sizeof(tname))); + Printf("%s", d.EndWarning()); + GET_STACK_TRACE_FATAL(second_free_stack->trace[0], + second_free_stack->top_frame_bp); + stack.Print(); + addr_description.Print(); + ReportErrorSummary("double-free", &stack); +} + } // namespace __asan Index: lib/asan/asan_report.cc =================================================================== --- lib/asan/asan_report.cc +++ lib/asan/asan_report.cc @@ -388,21 +388,8 @@ void ReportDoubleFree(uptr addr, BufferedStackTrace *free_stack) { ScopedInErrorReport in_report; - Decorator d; - Printf("%s", d.Warning()); - char tname[128]; - u32 curr_tid = GetCurrentTidOrInvalid(); - Report("ERROR: AddressSanitizer: attempting double-free on %p in " - "thread T%d%s:\n", - addr, curr_tid, - ThreadNameWithParenthesis(curr_tid, tname, sizeof(tname))); - Printf("%s", d.EndWarning()); - CHECK_GT(free_stack->size, 0); - ScarinessScore::PrintSimple(42, "double-free"); - GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp); - stack.Print(); - DescribeAddressIfHeap(addr); - ReportErrorSummary("double-free", &stack); + ErrorDoubleFree error{addr, GetCurrentTidOrInvalid(), free_stack}; // NOLINT + in_report.ReportError(error); } void ReportNewDeleteSizeMismatch(uptr addr, uptr alloc_size, uptr delete_size,