//===-- hwasan_report.cc ----------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of HWAddressSanitizer. // // Error reporting. //===----------------------------------------------------------------------===// #include "hwasan.h" #include "hwasan_allocator.h" #include "sanitizer_common/sanitizer_allocator_internal.h" #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_flags.h" #include "sanitizer_common/sanitizer_mutex.h" #include "sanitizer_common/sanitizer_report_decorator.h" #include "sanitizer_common/sanitizer_stackdepot.h" #include "sanitizer_common/sanitizer_symbolizer.h" using namespace __sanitizer; namespace __hwasan { static StackTrace GetStackTraceFromId(u32 id) { CHECK(id); StackTrace res = StackDepotGet(id); CHECK(res.trace); return res; } class Decorator: public __sanitizer::SanitizerCommonDecorator { public: Decorator() : SanitizerCommonDecorator() { } const char *Allocation() { return Magenta(); } const char *Origin() { return Magenta(); } const char *Name() { return Green(); } }; struct HeapAddressDescription { uptr addr; u32 alloc_stack_id; u32 free_stack_id; void Print() const { Decorator d; if (free_stack_id) { Printf("%sfreed here:%s\n", d.Allocation(), d.Default()); GetStackTraceFromId(free_stack_id).Print(); Printf("%spreviously allocated here:%s\n", d.Allocation(), d.Default()); } else { Printf("%sallocated here:%s\n", d.Allocation(), d.Default()); } GetStackTraceFromId(alloc_stack_id).Print(); } }; bool GetHeapAddressInformation(uptr addr, uptr access_size, HeapAddressDescription *description) { HwasanChunkView chunk = FindHeapChunkByAddress(addr); if (!chunk.IsValid()) return false; description->addr = addr; description->alloc_stack_id = chunk.GetAllocStackId(); description->free_stack_id = chunk.GetFreeStackId(); return true; } void PrintAddressDescription(uptr addr, uptr access_size) { HeapAddressDescription heap_description; if (GetHeapAddressInformation(addr, access_size, &heap_description)) { heap_description.Print(); return; } // We exhausted our possibilities. Bail out. Printf("HWAddressSanitizer can not describe address in more detail.\n"); } void ReportInvalidAccess(StackTrace *stack, u32 origin) { ScopedErrorReportLock l; Decorator d; Printf("%s", d.Warning()); Report("WARNING: HWAddressSanitizer: invalid access\n"); Printf("%s", d.Default()); stack->Print(); ReportErrorSummary("invalid-access", stack); } void ReportStats() {} void ReportInvalidAccessInsideAddressRange(const char *what, const void *start, uptr size, uptr offset) { ScopedErrorReportLock l; Decorator d; Printf("%s", d.Warning()); Printf("%sTag mismatch in %s%s%s at offset %zu inside [%p, %zu)%s\n", d.Warning(), d.Name(), what, d.Warning(), offset, start, size, d.Default()); PrintAddressDescription((uptr)start + offset, 1); // if (__sanitizer::Verbosity()) // DescribeMemoryRange(start, size); } void ReportTagMismatch(StackTrace *stack, uptr addr, uptr access_size, bool is_store) { ScopedErrorReportLock l; Decorator d; Printf("%s", d.Warning()); uptr address = GetAddressFromPointer(addr); Printf("%s of size %zu at %p\n", is_store ? "WRITE" : "READ", access_size, address); tag_t ptr_tag = GetTagFromPointer(addr); tag_t mem_tag = *(tag_t *)MEM_TO_SHADOW(address); Printf("pointer tag 0x%x\nmemory tag 0x%x\n", ptr_tag, mem_tag); Printf("%s", d.Default()); stack->Print(); PrintAddressDescription(address, access_size); ReportErrorSummary("tag-mismatch", stack); } } // namespace __hwasan