Index: compiler-rt/trunk/lib/asan/asan_allocator.cc =================================================================== --- compiler-rt/trunk/lib/asan/asan_allocator.cc +++ compiler-rt/trunk/lib/asan/asan_allocator.cc @@ -530,7 +530,7 @@ if (delete_size && flags()->new_delete_type_mismatch && delete_size != m->UsedSize()) { - ReportNewDeleteSizeMismatch(p, m->UsedSize(), delete_size, stack); + ReportNewDeleteSizeMismatch(p, delete_size, stack); } QuarantineChunk(m, ptr, stack, alloc_type); Index: compiler-rt/trunk/lib/asan/asan_errors.h =================================================================== --- compiler-rt/trunk/lib/asan/asan_errors.h +++ compiler-rt/trunk/lib/asan/asan_errors.h @@ -62,10 +62,30 @@ void Print(); }; +struct ErrorNewDeleteSizeMismatch : ErrorBase { + u32 tid; + HeapAddressDescription addr_description; + uptr delete_size; + // ErrorNewDeleteSizeMismatch doesn't own the stack trace. + BufferedStackTrace *free_stack; + // VS2013 doesn't implement unrestricted unions, so we need a trivial default + // constructor + ErrorNewDeleteSizeMismatch() = default; + ErrorNewDeleteSizeMismatch(uptr addr, u32 tid_, uptr delete_size_, + BufferedStackTrace *stack) + : tid(tid_), delete_size(delete_size_), free_stack(stack) { + GetHeapAddressInformation(addr, 1, &addr_description); + scariness.Clear(); + scariness.Scare(10, "new-delete-type-mismatch"); + } + void Print(); +}; + enum ErrorKind { kErrorKindInvalid = 0, kErrorKindStackOverflow, kErrorKindDoubleFree, + kErrorKindNewDeleteSizeMismatch, }; struct ErrorDescription { @@ -78,6 +98,7 @@ union { ErrorStackOverflow stack_overflow; ErrorDoubleFree double_free; + ErrorNewDeleteSizeMismatch new_delete_size_mismatch; }; ErrorDescription() { internal_memset(this, 0, sizeof(*this)); } ErrorDescription(const ErrorStackOverflow &e) // NOLINT @@ -86,6 +107,9 @@ ErrorDescription(const ErrorDoubleFree &e) // NOLINT : kind(kErrorKindDoubleFree), double_free(e) {} + ErrorDescription(const ErrorNewDeleteSizeMismatch &e) // NOLINT + : kind(kErrorKindNewDeleteSizeMismatch), + new_delete_size_mismatch(e) {} bool IsValid() { return kind != kErrorKindInvalid; } void Print() { @@ -96,6 +120,9 @@ case kErrorKindDoubleFree: double_free.Print(); return; + case kErrorKindNewDeleteSizeMismatch: + new_delete_size_mismatch.Print(); + return; case kErrorKindInvalid: CHECK(0); } Index: compiler-rt/trunk/lib/asan/asan_errors.cc =================================================================== --- compiler-rt/trunk/lib/asan/asan_errors.cc +++ compiler-rt/trunk/lib/asan/asan_errors.cc @@ -52,4 +52,29 @@ ReportErrorSummary("double-free", &stack); } +void ErrorNewDeleteSizeMismatch::Print() { + Decorator d; + Printf("%s", d.Warning()); + char tname[128]; + Report( + "ERROR: AddressSanitizer: new-delete-type-mismatch on %p in thread " + "T%d%s:\n", + addr_description.addr, tid, + ThreadNameWithParenthesis(tid, tname, sizeof(tname))); + Printf("%s object passed to delete has wrong type:\n", d.EndWarning()); + Printf( + " size of the allocated type: %zd bytes;\n" + " size of the deallocated type: %zd bytes.\n", + addr_description.chunk_access.chunk_size, delete_size); + CHECK_GT(free_stack->size, 0); + scariness.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); + Report( + "HINT: if you don't care about these errors you may set " + "ASAN_OPTIONS=new_delete_type_mismatch=0\n"); +} + } // namespace __asan Index: compiler-rt/trunk/lib/asan/asan_report.h =================================================================== --- compiler-rt/trunk/lib/asan/asan_report.h +++ compiler-rt/trunk/lib/asan/asan_report.h @@ -52,7 +52,7 @@ uptr access_size, u32 exp, bool fatal); void ReportStackOverflow(const SignalContext &sig); void ReportDeadlySignal(const char *description, const SignalContext &sig); -void ReportNewDeleteSizeMismatch(uptr addr, uptr alloc_size, uptr delete_size, +void ReportNewDeleteSizeMismatch(uptr addr, uptr delete_size, BufferedStackTrace *free_stack); void ReportDoubleFree(uptr addr, BufferedStackTrace *free_stack); void ReportFreeNotMalloced(uptr addr, BufferedStackTrace *free_stack); Index: compiler-rt/trunk/lib/asan/asan_report.cc =================================================================== --- compiler-rt/trunk/lib/asan/asan_report.cc +++ compiler-rt/trunk/lib/asan/asan_report.cc @@ -392,29 +392,12 @@ in_report.ReportError(error); } -void ReportNewDeleteSizeMismatch(uptr addr, uptr alloc_size, uptr delete_size, +void ReportNewDeleteSizeMismatch(uptr addr, uptr delete_size, BufferedStackTrace *free_stack) { ScopedInErrorReport in_report; - Decorator d; - Printf("%s", d.Warning()); - char tname[128]; - u32 curr_tid = GetCurrentTidOrInvalid(); - Report("ERROR: AddressSanitizer: new-delete-type-mismatch on %p in " - "thread T%d%s:\n", - addr, curr_tid, - ThreadNameWithParenthesis(curr_tid, tname, sizeof(tname))); - Printf("%s object passed to delete has wrong type:\n", d.EndWarning()); - Printf(" size of the allocated type: %zd bytes;\n" - " size of the deallocated type: %zd bytes.\n", - alloc_size, delete_size); - CHECK_GT(free_stack->size, 0); - ScarinessScore::PrintSimple(10, "new-delete-type-mismatch"); - GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp); - stack.Print(); - 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"); + ErrorNewDeleteSizeMismatch error(addr, GetCurrentTidOrInvalid(), delete_size, + free_stack); + in_report.ReportError(error); } void ReportFreeNotMalloced(uptr addr, BufferedStackTrace *free_stack) {