Index: lib/asan/asan_descriptions.h =================================================================== --- lib/asan/asan_descriptions.h +++ lib/asan/asan_descriptions.h @@ -88,6 +88,8 @@ uptr addr; ShadowKind kind; u8 shadow_byte; + + void Print(); }; bool GetShadowAddressInformation(uptr addr, ShadowAddressDescription *descr); @@ -116,6 +118,8 @@ u32 alloc_stack_id; u32 free_stack_id; ChunkAccess chunk_access; + + void Print(); }; bool GetHeapAddressInformation(uptr addr, uptr access_size, @@ -128,7 +132,10 @@ uptr offset; uptr frame_pc; const char *frame_descr; + + void Print(uptr access_size = 1); }; + bool GetStackAddressInformation(uptr addr, StackAddressDescription *descr); bool DescribeAddressIfStack(uptr addr, uptr access_size); @@ -139,9 +146,22 @@ __asan_global globals[kMaxGlobals]; u32 reg_sites[kMaxGlobals]; u8 size; + + void Print(uptr access_size = 1, const char *bug_type = ""); }; bool GetGlobalAddressInformation(uptr addr, GlobalAddressDescription *descr); bool DescribeAddressIfGlobal(uptr addr, uptr access_size, const char *bug_type); +// General function to describe an address. Will try to describe the address as +// a shadow, global (variable), stack, or heap address. +// bug_type is optional and is used for checking if we're reporting an +// initialization-order-fiasco +// The proper access_size should be passed for stack, global, and heap +// addresses. Defaults to 1. +// Each of the *AddressDescription functions has its own Print() member, which +// may take access_size and bug_type parameters if needed. +void PrintAddressDescription(uptr addr, uptr access_size = 1, + const char *bug_type = ""); + } // namespace __asan Index: lib/asan/asan_descriptions.cc =================================================================== --- lib/asan/asan_descriptions.cc +++ lib/asan/asan_descriptions.cc @@ -88,8 +88,7 @@ bool DescribeAddressIfShadow(uptr addr) { ShadowAddressDescription descr; if (!GetShadowAddressInformation(addr, &descr)) return false; - Printf("Address %p is located in the %s area.\n", addr, - ShadowNames[descr.kind]); + descr.Print(); return true; } @@ -188,38 +187,7 @@ "(wild memory access suspected).\n"); return false; } - PrintHeapChunkAccess(addr, descr.chunk_access); - - asanThreadRegistry().CheckLocked(); - AsanThreadContext *alloc_thread = - GetThreadContextByTidLocked(descr.alloc_tid); - StackTrace alloc_stack = GetStackTraceFromId(descr.alloc_stack_id); - - char tname[128]; - Decorator d; - AsanThreadContext *free_thread = nullptr; - if (descr.free_tid != kInvalidTid) { - free_thread = GetThreadContextByTidLocked(descr.free_tid); - Printf("%sfreed by thread T%d%s here:%s\n", d.Allocation(), - free_thread->tid, - ThreadNameWithParenthesis(free_thread, tname, sizeof(tname)), - d.EndAllocation()); - StackTrace free_stack = GetStackTraceFromId(descr.free_stack_id); - free_stack.Print(); - Printf("%spreviously allocated by thread T%d%s here:%s\n", d.Allocation(), - alloc_thread->tid, - ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)), - d.EndAllocation()); - } else { - Printf("%sallocated by thread T%d%s here:%s\n", d.Allocation(), - alloc_thread->tid, - ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)), - d.EndAllocation()); - } - alloc_stack.Print(); - DescribeThread(GetCurrentThread()); - if (free_thread) DescribeThread(free_thread); - DescribeThread(alloc_thread); + descr.Print(); return true; } @@ -297,59 +265,7 @@ bool DescribeAddressIfStack(uptr addr, uptr access_size) { StackAddressDescription descr; if (!GetStackAddressInformation(addr, &descr)) return false; - - Decorator d; - char tname[128]; - Printf("%s", d.Location()); - Printf("Address %p is located in stack of thread T%d%s", addr, descr.tid, - ThreadNameWithParenthesis(descr.tid, tname, sizeof(tname))); - - if (!descr.frame_descr) { - Printf("%s\n", d.EndLocation()); - return true; - } - Printf(" at offset %zu in frame%s\n", descr.offset, d.EndLocation()); - - // Now we print the frame where the alloca has happened. - // We print this frame as a stack trace with one element. - // The symbolizer may print more than one frame if inlining was involved. - // The frame numbers may be different than those in the stack trace printed - // previously. That's unfortunate, but I have no better solution, - // especially given that the alloca may be from entirely different place - // (e.g. use-after-scope, or different thread's stack). - Printf("%s", d.EndLocation()); - StackTrace alloca_stack(&descr.frame_pc, 1); - alloca_stack.Print(); - - InternalMmapVector vars(16); - if (!ParseFrameDescription(descr.frame_descr, &vars)) { - Printf( - "AddressSanitizer can't parse the stack frame " - "descriptor: |%s|\n", - descr.frame_descr); - // 'addr' is a stack address, so return true even if we can't parse frame - return true; - } - uptr n_objects = vars.size(); - // Report the number of stack objects. - Printf(" This frame has %zu object(s):\n", n_objects); - - // Report all objects in this frame. - for (uptr i = 0; i < n_objects; i++) { - uptr prev_var_end = i ? vars[i - 1].beg + vars[i - 1].size : 0; - uptr next_var_beg = i + 1 < n_objects ? vars[i + 1].beg : ~(0UL); - PrintAccessAndVarIntersection(vars[i], descr.offset, access_size, - prev_var_end, next_var_beg); - } - Printf( - "HINT: this may be a false positive if your program uses " - "some custom stack unwind mechanism or swapcontext\n"); - if (SANITIZER_WINDOWS) - Printf(" (longjmp, SEH and C++ exceptions *are* supported)\n"); - else - Printf(" (longjmp and C++ exceptions *are* supported)\n"); - - DescribeThread(GetThreadContextByTidLocked(descr.tid)); + descr.Print(access_size); return true; } @@ -392,15 +308,143 @@ GlobalAddressDescription descr; if (!GetGlobalAddressInformation(addr, &descr)) return false; - for (int i = 0; i < descr.size; i++) { - DescribeAddressRelativeToGlobal(descr.addr, access_size, descr.globals[i]); - if (0 == internal_strcmp(bug_type, "initialization-order-fiasco") && - descr.reg_sites[i]) { - Printf(" registered at:\n"); - StackDepotGet(descr.reg_sites[i]).Print(); - } - } + descr.Print(access_size, bug_type); return true; } +void ShadowAddressDescription::Print() { + Printf("Address %p is located in the %s area.\n", addr, ShadowNames[kind]); +} + +void GlobalAddressDescription::Print(uptr access_size, const char *bug_type) { + for (int i = 0; i < size; i++) { + DescribeAddressRelativeToGlobal(addr, access_size, globals[i]); + if (0 == internal_strcmp(bug_type, "initialization-order-fiasco") && + reg_sites[i]) { + Printf(" registered at:\n"); + StackDepotGet(reg_sites[i]).Print(); + } + } +} + +void StackAddressDescription::Print(uptr access_size) { + Decorator d; + char tname[128]; + Printf("%s", d.Location()); + Printf("Address %p is located in stack of thread T%d%s", addr, tid, + ThreadNameWithParenthesis(tid, tname, sizeof(tname))); + + if (!frame_descr) { + Printf("%s\n", d.EndLocation()); + return; + } + Printf(" at offset %zu in frame%s\n", offset, d.EndLocation()); + + // Now we print the frame where the alloca has happened. + // We print this frame as a stack trace with one element. + // The symbolizer may print more than one frame if inlining was involved. + // The frame numbers may be different than those in the stack trace printed + // previously. That's unfortunate, but I have no better solution, + // especially given that the alloca may be from entirely different place + // (e.g. use-after-scope, or different thread's stack). + Printf("%s", d.EndLocation()); + StackTrace alloca_stack(&frame_pc, 1); + alloca_stack.Print(); + + InternalMmapVector vars(16); + if (!ParseFrameDescription(frame_descr, &vars)) { + Printf( + "AddressSanitizer can't parse the stack frame " + "descriptor: |%s|\n", + frame_descr); + // 'addr' is a stack address, so return true even if we can't parse frame + return; + } + uptr n_objects = vars.size(); + // Report the number of stack objects. + Printf(" This frame has %zu object(s):\n", n_objects); + + // Report all objects in this frame. + for (uptr i = 0; i < n_objects; i++) { + uptr prev_var_end = i ? vars[i - 1].beg + vars[i - 1].size : 0; + uptr next_var_beg = i + 1 < n_objects ? vars[i + 1].beg : ~(0UL); + PrintAccessAndVarIntersection(vars[i], offset, access_size, prev_var_end, + next_var_beg); + } + Printf( + "HINT: this may be a false positive if your program uses " + "some custom stack unwind mechanism or swapcontext\n"); + if (SANITIZER_WINDOWS) + Printf(" (longjmp, SEH and C++ exceptions *are* supported)\n"); + else + Printf(" (longjmp and C++ exceptions *are* supported)\n"); + + DescribeThread(GetThreadContextByTidLocked(tid)); +} + +void HeapAddressDescription::Print() { + PrintHeapChunkAccess(addr, chunk_access); + + asanThreadRegistry().CheckLocked(); + AsanThreadContext *alloc_thread = GetThreadContextByTidLocked(alloc_tid); + StackTrace alloc_stack = GetStackTraceFromId(alloc_stack_id); + + char tname[128]; + Decorator d; + AsanThreadContext *free_thread = nullptr; + if (free_tid != kInvalidTid) { + free_thread = GetThreadContextByTidLocked(free_tid); + Printf("%sfreed by thread T%d%s here:%s\n", d.Allocation(), + free_thread->tid, + ThreadNameWithParenthesis(free_thread, tname, sizeof(tname)), + d.EndAllocation()); + StackTrace free_stack = GetStackTraceFromId(free_stack_id); + free_stack.Print(); + Printf("%spreviously allocated by thread T%d%s here:%s\n", d.Allocation(), + alloc_thread->tid, + ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)), + d.EndAllocation()); + } else { + Printf("%sallocated by thread T%d%s here:%s\n", d.Allocation(), + alloc_thread->tid, + ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)), + d.EndAllocation()); + } + alloc_stack.Print(); + DescribeThread(GetCurrentThread()); + if (free_thread) DescribeThread(free_thread); + DescribeThread(alloc_thread); +} + +void PrintAddressDescription(uptr addr, uptr access_size, + const char *bug_type) { + ShadowAddressDescription shadow_descr; + if (GetShadowAddressInformation(addr, &shadow_descr)) { + shadow_descr.Print(); + return; + } + + GlobalAddressDescription global_descr; + if (GetGlobalAddressInformation(addr, &global_descr)) { + global_descr.Print(access_size, bug_type); + return; + } + + StackAddressDescription stack_descr; + if (GetStackAddressInformation(addr, &stack_descr)) { + stack_descr.Print(access_size); + return; + } + + HeapAddressDescription heap_descr; + if (GetHeapAddressInformation(addr, access_size, &heap_descr)) { + heap_descr.Print(); + return; + } + + // We exhausted our possibilities. Bail out. + Printf( + "AddressSanitizer can not describe address in more detail " + "(wild memory access suspected).\n"); +} } // namespace __asan Index: lib/asan/asan_report.cc =================================================================== --- lib/asan/asan_report.cc +++ lib/asan/asan_report.cc @@ -212,19 +212,6 @@ return true; } -static void DescribeAddress(uptr addr, uptr access_size, const char *bug_type) { - // Check if this is shadow or shadow gap. - if (DescribeAddressIfShadow(addr)) - return; - CHECK(AddrIsInMem(addr)); - if (DescribeAddressIfGlobal(addr, access_size, bug_type)) - return; - if (DescribeAddressIfStack(addr, access_size)) - return; - // Assume it is a heap address. - DescribeAddressIfHeap(addr, access_size); -} - // -------------------- Different kinds of reports ----------------- {{{1 // Use ScopedInErrorReport to run common actions just before and @@ -526,8 +513,8 @@ Printf("%s", d.EndWarning()); ScarinessScore::PrintSimple(10, bug_type); stack->Print(); - DescribeAddress((uptr)offset1, length1, bug_type); - DescribeAddress((uptr)offset2, length2, bug_type); + PrintAddressDescription((uptr)offset1, length1, bug_type); + PrintAddressDescription((uptr)offset2, length2, bug_type); ReportErrorSummary(bug_type, stack); } @@ -541,7 +528,7 @@ Printf("%s", d.EndWarning()); ScarinessScore::PrintSimple(10, bug_type); stack->Print(); - DescribeAddress(offset, size, bug_type); + PrintAddressDescription(offset, size, bug_type); ReportErrorSummary(bug_type, stack); } @@ -603,8 +590,8 @@ Printf("%s", d.EndWarning()); GET_STACK_TRACE_FATAL(pc, bp); stack.Print(); - DescribeAddress(a1, 1, bug_type); - DescribeAddress(a2, 1, bug_type); + PrintAddressDescription(a1, 1, bug_type); + PrintAddressDescription(a2, 1, bug_type); ReportErrorSummary(bug_type, &stack); } @@ -792,7 +779,7 @@ GET_STACK_TRACE_FATAL(pc, bp); stack.Print(); - DescribeAddress(addr, access_size, bug_descr); + PrintAddressDescription(addr, access_size, bug_descr); if (shadow_val == kAsanContiguousContainerOOBMagic) PrintContainerOverflowHint(); ReportErrorSummary(bug_descr, &stack); @@ -819,7 +806,7 @@ void __asan_describe_address(uptr addr) { // Thread registry must be locked while we're describing an address. asanThreadRegistry().Lock(); - DescribeAddress(addr, 1, ""); + PrintAddressDescription(addr, 1, ""); asanThreadRegistry().Unlock(); }