asan_report.cc revision e4bfca2b154a6ab4eda921aff454035f33f3551a
1//===-- asan_report.cc ----------------------------------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file is a part of AddressSanitizer, an address sanity checker. 11// 12// This file contains error reporting code. 13//===----------------------------------------------------------------------===// 14#include "asan_internal.h" 15#include "asan_mapping.h" 16#include "asan_report.h" 17#include "asan_stack.h" 18#include "asan_thread.h" 19#include "asan_thread_registry.h" 20 21namespace __asan { 22 23// ---------------------- Address Descriptions ------------------- {{{1 24 25static bool IsASCII(unsigned char c) { 26 return 0x00 <= c && c <= 0x7F; 27} 28 29// Check if the global is a zero-terminated ASCII string. If so, print it. 30static void PrintGlobalNameIfASCII(const __asan_global &g) { 31 for (uptr p = g.beg; p < g.beg + g.size - 1; p++) { 32 if (!IsASCII(*(unsigned char*)p)) return; 33 } 34 if (*(char*)(g.beg + g.size - 1) != 0) return; 35 AsanPrintf(" '%s' is ascii string '%s'\n", g.name, (char*)g.beg); 36} 37 38bool DescribeAddressRelativeToGlobal(uptr addr, const __asan_global &g) { 39 if (addr < g.beg - kGlobalAndStackRedzone) return false; 40 if (addr >= g.beg + g.size_with_redzone) return false; 41 AsanPrintf("%p is located ", (void*)addr); 42 if (addr < g.beg) { 43 AsanPrintf("%zd bytes to the left", g.beg - addr); 44 } else if (addr >= g.beg + g.size) { 45 AsanPrintf("%zd bytes to the right", addr - (g.beg + g.size)); 46 } else { 47 AsanPrintf("%zd bytes inside", addr - g.beg); // Can it happen? 48 } 49 AsanPrintf(" of global variable '%s' (0x%zx) of size %zu\n", 50 g.name, g.beg, g.size); 51 PrintGlobalNameIfASCII(g); 52 return true; 53} 54 55bool DescribeAddressIfShadow(uptr addr) { 56 if (AddrIsInMem(addr)) 57 return false; 58 static const char kAddrInShadowReport[] = 59 "Address %p is located in the %s.\n"; 60 if (AddrIsInShadowGap(addr)) { 61 AsanPrintf(kAddrInShadowReport, addr, "shadow gap area"); 62 return true; 63 } 64 if (AddrIsInHighShadow(addr)) { 65 AsanPrintf(kAddrInShadowReport, addr, "high shadow area"); 66 return true; 67 } 68 if (AddrIsInLowShadow(addr)) { 69 AsanPrintf(kAddrInShadowReport, addr, "low shadow area"); 70 return true; 71 } 72 CHECK(0 && "Address is not in memory and not in shadow?"); 73 return false; 74} 75 76bool DescribeAddressIfStack(uptr addr, uptr access_size) { 77 AsanThread *t = asanThreadRegistry().FindThreadByStackAddress(addr); 78 if (!t) return false; 79 const sptr kBufSize = 4095; 80 char buf[kBufSize]; 81 uptr offset = 0; 82 const char *frame_descr = t->GetFrameNameByAddr(addr, &offset); 83 // This string is created by the compiler and has the following form: 84 // "FunctioName n alloc_1 alloc_2 ... alloc_n" 85 // where alloc_i looks like "offset size len ObjectName ". 86 CHECK(frame_descr); 87 // Report the function name and the offset. 88 const char *name_end = internal_strchr(frame_descr, ' '); 89 CHECK(name_end); 90 buf[0] = 0; 91 internal_strncat(buf, frame_descr, 92 Min(kBufSize, 93 static_cast<sptr>(name_end - frame_descr))); 94 AsanPrintf("Address %p is located at offset %zu " 95 "in frame <%s> of T%d's stack:\n", 96 (void*)addr, offset, buf, t->tid()); 97 // Report the number of stack objects. 98 char *p; 99 uptr n_objects = internal_simple_strtoll(name_end, &p, 10); 100 CHECK(n_objects > 0); 101 AsanPrintf(" This frame has %zu object(s):\n", n_objects); 102 // Report all objects in this frame. 103 for (uptr i = 0; i < n_objects; i++) { 104 uptr beg, size; 105 sptr len; 106 beg = internal_simple_strtoll(p, &p, 10); 107 size = internal_simple_strtoll(p, &p, 10); 108 len = internal_simple_strtoll(p, &p, 10); 109 if (beg <= 0 || size <= 0 || len < 0 || *p != ' ') { 110 AsanPrintf("AddressSanitizer can't parse the stack frame " 111 "descriptor: |%s|\n", frame_descr); 112 break; 113 } 114 p++; 115 buf[0] = 0; 116 internal_strncat(buf, p, Min(kBufSize, len)); 117 p += len; 118 AsanPrintf(" [%zu, %zu) '%s'\n", beg, beg + size, buf); 119 } 120 AsanPrintf("HINT: this may be a false positive if your program uses " 121 "some custom stack unwind mechanism\n" 122 " (longjmp and C++ exceptions *are* supported)\n"); 123 t->summary()->Announce(); 124 return true; 125} 126 127void DescribeAddress(uptr addr, uptr access_size) { 128 // Check if this is shadow or shadow gap. 129 if (DescribeAddressIfShadow(addr)) 130 return; 131 CHECK(AddrIsInMem(addr)); 132 if (DescribeAddressIfGlobal(addr)) 133 return; 134 if (DescribeAddressIfStack(addr, access_size)) 135 return; 136 // Assume it is a heap address. 137 DescribeHeapAddress(addr, access_size); 138} 139 140// -------------------- Different kinds of reports ----------------- {{{1 141 142void ReportSIGSEGV(uptr pc, uptr sp, uptr bp, uptr addr) { 143 AsanReport("ERROR: AddressSanitizer crashed on unknown address %p" 144 " (pc %p sp %p bp %p T%d)\n", 145 (void*)addr, (void*)pc, (void*)sp, (void*)bp, 146 asanThreadRegistry().GetCurrentTidOrInvalid()); 147 AsanPrintf("AddressSanitizer can not provide additional info. ABORTING\n"); 148 GET_STACK_TRACE_WITH_PC_AND_BP(kStackTraceMax, pc, bp); 149 stack.PrintStack(); 150 ShowStatsAndAbort(); 151} 152 153void ReportDoubleFree(uptr addr, AsanStackTrace *stack) { 154 AsanReport("ERROR: AddressSanitizer attempting double-free on %p:\n", addr); 155 stack->PrintStack(); 156 DescribeHeapAddress(addr, 1); 157 ShowStatsAndAbort(); 158} 159 160void ReportFreeNotMalloced(uptr addr, AsanStackTrace *stack) { 161 AsanReport("ERROR: AddressSanitizer attempting free on address " 162 "which was not malloc()-ed: %p\n", addr); 163 stack->PrintStack(); 164 ShowStatsAndAbort(); 165} 166 167void ReportMallocUsableSizeNotOwned(uptr addr, AsanStackTrace *stack) { 168 AsanReport("ERROR: AddressSanitizer attempting to call " 169 "malloc_usable_size() for pointer which is " 170 "not owned: %p\n", addr); 171 stack->PrintStack(); 172 DescribeHeapAddress(addr, 1); 173 ShowStatsAndAbort(); 174} 175 176void ReportAsanGetAllocatedSizeNotOwned(uptr addr, AsanStackTrace *stack) { 177 AsanReport("ERROR: AddressSanitizer attempting to call " 178 "__asan_get_allocated_size() for pointer which is " 179 "not owned: %p\n", addr); 180 stack->PrintStack(); 181 DescribeHeapAddress(addr, 1); 182 ShowStatsAndAbort(); 183} 184 185void ReportStringFunctionMemoryRangesOverlap( 186 const char *function, const char *offset1, uptr length1, 187 const char *offset2, uptr length2, AsanStackTrace *stack) { 188 AsanReport("ERROR: AddressSanitizer %s-param-overlap: " 189 "memory ranges [%p,%p) and [%p, %p) overlap\n", \ 190 function, offset1, offset1 + length1, offset2, offset2 + length2); 191 stack->PrintStack(); 192 ShowStatsAndAbort(); 193} 194 195} // namespace __asan 196