asan_report.cc revision 58f54555c2528f863e211a0679c2c423cfa55fb2
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_flags.h" 15#include "asan_internal.h" 16#include "asan_mapping.h" 17#include "asan_report.h" 18#include "asan_stack.h" 19#include "asan_thread.h" 20#include "asan_thread_registry.h" 21#include "sanitizer_common/sanitizer_common.h" 22#include "sanitizer_common/sanitizer_report_decorator.h" 23 24namespace __asan { 25 26// -------------------- User-specified callbacks ----------------- {{{1 27static void (*error_report_callback)(const char*); 28static char *error_message_buffer = 0; 29static uptr error_message_buffer_pos = 0; 30static uptr error_message_buffer_size = 0; 31 32void AppendToErrorMessageBuffer(const char *buffer) { 33 if (error_message_buffer) { 34 uptr length = internal_strlen(buffer); 35 CHECK_GE(error_message_buffer_size, error_message_buffer_pos); 36 uptr remaining = error_message_buffer_size - error_message_buffer_pos; 37 internal_strncpy(error_message_buffer + error_message_buffer_pos, 38 buffer, remaining); 39 error_message_buffer[error_message_buffer_size - 1] = '\0'; 40 // FIXME: reallocate the buffer instead of truncating the message. 41 error_message_buffer_pos += remaining > length ? length : remaining; 42 } 43} 44 45// ---------------------- Decorator ------------------------------ {{{1 46class Decorator: private __sanitizer::AnsiColorDecorator { 47 public: 48 Decorator() : __sanitizer::AnsiColorDecorator(PrintsToTty()) { } 49 const char *Warning() { return Red(); } 50 const char *EndWarning() { return Default(); } 51 const char *Access() { return Blue(); } 52 const char *EndAccess() { return Default(); } 53 const char *Location() { return Green(); } 54 const char *EndLocation() { return Default(); } 55 const char *Allocation() { return Magenta(); } 56 const char *EndAllocation() { return Default(); } 57}; 58 59// ---------------------- Helper functions ----------------------- {{{1 60 61static void PrintBytes(const char *before, uptr *a) { 62 u8 *bytes = (u8*)a; 63 uptr byte_num = (SANITIZER_WORDSIZE) / 8; 64 Printf("%s%p:", before, (void*)a); 65 for (uptr i = 0; i < byte_num; i++) { 66 Printf(" %x%x", bytes[i] >> 4, bytes[i] & 15); 67 } 68 Printf("\n"); 69} 70 71static void PrintShadowMemoryForAddress(uptr addr) { 72 if (!AddrIsInMem(addr)) 73 return; 74 uptr shadow_addr = MemToShadow(addr); 75 Printf("Shadow byte and word:\n"); 76 Printf(" %p: %x\n", (void*)shadow_addr, *(unsigned char*)shadow_addr); 77 uptr aligned_shadow = shadow_addr & ~(kWordSize - 1); 78 PrintBytes(" ", (uptr*)(aligned_shadow)); 79 Printf("More shadow bytes:\n"); 80 for (int i = -4; i <= 4; i++) { 81 const char *prefix = (i == 0) ? "=>" : " "; 82 PrintBytes(prefix, (uptr*)(aligned_shadow + i * kWordSize)); 83 } 84} 85 86static void PrintZoneForPointer(uptr ptr, uptr zone_ptr, 87 const char *zone_name) { 88 if (zone_ptr) { 89 if (zone_name) { 90 Printf("malloc_zone_from_ptr(%p) = %p, which is %s\n", 91 ptr, zone_ptr, zone_name); 92 } else { 93 Printf("malloc_zone_from_ptr(%p) = %p, which doesn't have a name\n", 94 ptr, zone_ptr); 95 } 96 } else { 97 Printf("malloc_zone_from_ptr(%p) = 0\n", ptr); 98 } 99} 100 101// ---------------------- Address Descriptions ------------------- {{{1 102 103static bool IsASCII(unsigned char c) { 104 return /*0x00 <= c &&*/ c <= 0x7F; 105} 106 107// Check if the global is a zero-terminated ASCII string. If so, print it. 108static void PrintGlobalNameIfASCII(const __asan_global &g) { 109 for (uptr p = g.beg; p < g.beg + g.size - 1; p++) { 110 if (!IsASCII(*(unsigned char*)p)) return; 111 } 112 if (*(char*)(g.beg + g.size - 1) != 0) return; 113 Printf(" '%s' is ascii string '%s'\n", g.name, (char*)g.beg); 114} 115 116bool DescribeAddressRelativeToGlobal(uptr addr, const __asan_global &g) { 117 if (addr < g.beg - kGlobalAndStackRedzone) return false; 118 if (addr >= g.beg + g.size_with_redzone) return false; 119 Decorator d; 120 Printf("%s", d.Location()); 121 Printf("%p is located ", (void*)addr); 122 if (addr < g.beg) { 123 Printf("%zd bytes to the left", g.beg - addr); 124 } else if (addr >= g.beg + g.size) { 125 Printf("%zd bytes to the right", addr - (g.beg + g.size)); 126 } else { 127 Printf("%zd bytes inside", addr - g.beg); // Can it happen? 128 } 129 Printf(" of global variable '%s' (0x%zx) of size %zu\n", 130 g.name, g.beg, g.size); 131 Printf("%s", d.EndLocation()); 132 PrintGlobalNameIfASCII(g); 133 return true; 134} 135 136bool DescribeAddressIfShadow(uptr addr) { 137 if (AddrIsInMem(addr)) 138 return false; 139 static const char kAddrInShadowReport[] = 140 "Address %p is located in the %s.\n"; 141 if (AddrIsInShadowGap(addr)) { 142 Printf(kAddrInShadowReport, addr, "shadow gap area"); 143 return true; 144 } 145 if (AddrIsInHighShadow(addr)) { 146 Printf(kAddrInShadowReport, addr, "high shadow area"); 147 return true; 148 } 149 if (AddrIsInLowShadow(addr)) { 150 Printf(kAddrInShadowReport, addr, "low shadow area"); 151 return true; 152 } 153 CHECK(0 && "Address is not in memory and not in shadow?"); 154 return false; 155} 156 157bool DescribeAddressIfStack(uptr addr, uptr access_size) { 158 AsanThread *t = asanThreadRegistry().FindThreadByStackAddress(addr); 159 if (!t) return false; 160 const sptr kBufSize = 4095; 161 char buf[kBufSize]; 162 uptr offset = 0; 163 const char *frame_descr = t->GetFrameNameByAddr(addr, &offset); 164 // This string is created by the compiler and has the following form: 165 // "FunctioName n alloc_1 alloc_2 ... alloc_n" 166 // where alloc_i looks like "offset size len ObjectName ". 167 CHECK(frame_descr); 168 // Report the function name and the offset. 169 const char *name_end = internal_strchr(frame_descr, ' '); 170 CHECK(name_end); 171 buf[0] = 0; 172 internal_strncat(buf, frame_descr, 173 Min(kBufSize, 174 static_cast<sptr>(name_end - frame_descr))); 175 Decorator d; 176 Printf("%s", d.Location()); 177 Printf("Address %p is located at offset %zu " 178 "in frame <%s> of T%d's stack:\n", 179 (void*)addr, offset, buf, t->tid()); 180 Printf("%s", d.EndLocation()); 181 // Report the number of stack objects. 182 char *p; 183 uptr n_objects = internal_simple_strtoll(name_end, &p, 10); 184 CHECK(n_objects > 0); 185 Printf(" This frame has %zu object(s):\n", n_objects); 186 // Report all objects in this frame. 187 for (uptr i = 0; i < n_objects; i++) { 188 uptr beg, size; 189 sptr len; 190 beg = internal_simple_strtoll(p, &p, 10); 191 size = internal_simple_strtoll(p, &p, 10); 192 len = internal_simple_strtoll(p, &p, 10); 193 if (beg <= 0 || size <= 0 || len < 0 || *p != ' ') { 194 Printf("AddressSanitizer can't parse the stack frame " 195 "descriptor: |%s|\n", frame_descr); 196 break; 197 } 198 p++; 199 buf[0] = 0; 200 internal_strncat(buf, p, Min(kBufSize, len)); 201 p += len; 202 Printf(" [%zu, %zu) '%s'\n", beg, beg + size, buf); 203 } 204 Printf("HINT: this may be a false positive if your program uses " 205 "some custom stack unwind mechanism or swapcontext\n" 206 " (longjmp and C++ exceptions *are* supported)\n"); 207 DescribeThread(t->summary()); 208 return true; 209} 210 211static void DescribeAccessToHeapChunk(AsanChunkView chunk, uptr addr, 212 uptr access_size) { 213 uptr offset; 214 Decorator d; 215 Printf("%s", d.Location()); 216 Printf("%p is located ", (void*)addr); 217 if (chunk.AddrIsInside(addr, access_size, &offset)) { 218 Printf("%zu bytes inside of", offset); 219 } else if (chunk.AddrIsAtLeft(addr, access_size, &offset)) { 220 Printf("%zu bytes to the left of", offset); 221 } else if (chunk.AddrIsAtRight(addr, access_size, &offset)) { 222 Printf("%zu bytes to the right of", offset); 223 } else { 224 Printf(" somewhere around (this is AddressSanitizer bug!)"); 225 } 226 Printf(" %zu-byte region [%p,%p)\n", chunk.UsedSize(), 227 (void*)(chunk.Beg()), (void*)(chunk.End())); 228 Printf("%s", d.EndLocation()); 229} 230 231// Return " (thread_name) " or an empty string if the name is empty. 232const char *ThreadNameWithParenthesis(AsanThreadSummary *t, char buff[], 233 uptr buff_len) { 234 const char *name = t->name(); 235 if (*name == 0) return ""; 236 buff[0] = 0; 237 internal_strncat(buff, " (", 3); 238 internal_strncat(buff, name, buff_len - 4); 239 internal_strncat(buff, ")", 2); 240 return buff; 241} 242 243const char *ThreadNameWithParenthesis(u32 tid, char buff[], 244 uptr buff_len) { 245 if (tid == kInvalidTid) return ""; 246 AsanThreadSummary *t = asanThreadRegistry().FindByTid(tid); 247 return ThreadNameWithParenthesis(t, buff, buff_len); 248} 249 250void DescribeHeapAddress(uptr addr, uptr access_size) { 251 AsanChunkView chunk = FindHeapChunkByAddress(addr); 252 if (!chunk.IsValid()) return; 253 DescribeAccessToHeapChunk(chunk, addr, access_size); 254 CHECK(chunk.AllocTid() != kInvalidTid); 255 AsanThreadSummary *alloc_thread = 256 asanThreadRegistry().FindByTid(chunk.AllocTid()); 257 StackTrace alloc_stack; 258 chunk.GetAllocStack(&alloc_stack); 259 AsanThread *t = asanThreadRegistry().GetCurrent(); 260 CHECK(t); 261 char tname[128]; 262 Decorator d; 263 if (chunk.FreeTid() != kInvalidTid) { 264 AsanThreadSummary *free_thread = 265 asanThreadRegistry().FindByTid(chunk.FreeTid()); 266 Printf("%sfreed by thread T%d%s here:%s\n", d.Allocation(), 267 free_thread->tid(), 268 ThreadNameWithParenthesis(free_thread, tname, sizeof(tname)), 269 d.EndAllocation()); 270 StackTrace free_stack; 271 chunk.GetFreeStack(&free_stack); 272 PrintStack(&free_stack); 273 Printf("%spreviously allocated by thread T%d%s here:%s\n", 274 d.Allocation(), alloc_thread->tid(), 275 ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)), 276 d.EndAllocation()); 277 PrintStack(&alloc_stack); 278 DescribeThread(t->summary()); 279 DescribeThread(free_thread); 280 DescribeThread(alloc_thread); 281 } else { 282 Printf("%sallocated by thread T%d%s here:%s\n", d.Allocation(), 283 alloc_thread->tid(), 284 ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)), 285 d.EndAllocation()); 286 PrintStack(&alloc_stack); 287 DescribeThread(t->summary()); 288 DescribeThread(alloc_thread); 289 } 290} 291 292void DescribeAddress(uptr addr, uptr access_size) { 293 // Check if this is shadow or shadow gap. 294 if (DescribeAddressIfShadow(addr)) 295 return; 296 CHECK(AddrIsInMem(addr)); 297 if (DescribeAddressIfGlobal(addr)) 298 return; 299 if (DescribeAddressIfStack(addr, access_size)) 300 return; 301 // Assume it is a heap address. 302 DescribeHeapAddress(addr, access_size); 303} 304 305// ------------------- Thread description -------------------- {{{1 306 307void DescribeThread(AsanThreadSummary *summary) { 308 CHECK(summary); 309 // No need to announce the main thread. 310 if (summary->tid() == 0 || summary->announced()) { 311 return; 312 } 313 summary->set_announced(true); 314 char tname[128]; 315 Printf("Thread T%d%s", summary->tid(), 316 ThreadNameWithParenthesis(summary->tid(), tname, sizeof(tname))); 317 Printf(" created by T%d%s here:\n", 318 summary->parent_tid(), 319 ThreadNameWithParenthesis(summary->parent_tid(), 320 tname, sizeof(tname))); 321 PrintStack(summary->stack()); 322 // Recursively described parent thread if needed. 323 if (flags()->print_full_thread_history) { 324 AsanThreadSummary *parent_summary = 325 asanThreadRegistry().FindByTid(summary->parent_tid()); 326 DescribeThread(parent_summary); 327 } 328} 329 330// -------------------- Different kinds of reports ----------------- {{{1 331 332// Use ScopedInErrorReport to run common actions just before and 333// immediately after printing error report. 334class ScopedInErrorReport { 335 public: 336 ScopedInErrorReport() { 337 static atomic_uint32_t num_calls; 338 static u32 reporting_thread_tid; 339 if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) { 340 // Do not print more than one report, otherwise they will mix up. 341 // Error reporting functions shouldn't return at this situation, as 342 // they are defined as no-return. 343 Report("AddressSanitizer: while reporting a bug found another one." 344 "Ignoring.\n"); 345 u32 current_tid = asanThreadRegistry().GetCurrentTidOrInvalid(); 346 if (current_tid != reporting_thread_tid) { 347 // ASan found two bugs in different threads simultaneously. Sleep 348 // long enough to make sure that the thread which started to print 349 // an error report will finish doing it. 350 SleepForSeconds(Max(100, flags()->sleep_before_dying + 1)); 351 } 352 // If we're still not dead for some reason, use raw Exit() instead of 353 // Die() to bypass any additional checks. 354 Exit(flags()->exitcode); 355 } 356 ASAN_ON_ERROR(); 357 reporting_thread_tid = asanThreadRegistry().GetCurrentTidOrInvalid(); 358 Printf("====================================================" 359 "=============\n"); 360 if (reporting_thread_tid != kInvalidTid) { 361 // We started reporting an error message. Stop using the fake stack 362 // in case we call an instrumented function from a symbolizer. 363 AsanThread *curr_thread = asanThreadRegistry().GetCurrent(); 364 CHECK(curr_thread); 365 curr_thread->fake_stack().StopUsingFakeStack(); 366 } 367 } 368 // Destructor is NORETURN, as functions that report errors are. 369 NORETURN ~ScopedInErrorReport() { 370 // Make sure the current thread is announced. 371 AsanThread *curr_thread = asanThreadRegistry().GetCurrent(); 372 if (curr_thread) { 373 DescribeThread(curr_thread->summary()); 374 } 375 // Print memory stats. 376 __asan_print_accumulated_stats(); 377 if (error_report_callback) { 378 error_report_callback(error_message_buffer); 379 } 380 Report("ABORTING\n"); 381 Die(); 382 } 383}; 384 385void ReportSIGSEGV(uptr pc, uptr sp, uptr bp, uptr addr) { 386 ScopedInErrorReport in_report; 387 Decorator d; 388 Printf("%s", d.Warning()); 389 Report("ERROR: AddressSanitizer: SEGV on unknown address %p" 390 " (pc %p sp %p bp %p T%d)\n", 391 (void*)addr, (void*)pc, (void*)sp, (void*)bp, 392 asanThreadRegistry().GetCurrentTidOrInvalid()); 393 Printf("%s", d.EndWarning()); 394 Printf("AddressSanitizer can not provide additional info.\n"); 395 GET_STACK_TRACE_FATAL(pc, bp); 396 PrintStack(&stack); 397} 398 399void ReportDoubleFree(uptr addr, StackTrace *stack) { 400 ScopedInErrorReport in_report; 401 Decorator d; 402 Printf("%s", d.Warning()); 403 Report("ERROR: AddressSanitizer: attempting double-free on %p:\n", addr); 404 Printf("%s", d.EndWarning()); 405 PrintStack(stack); 406 DescribeHeapAddress(addr, 1); 407} 408 409void ReportFreeNotMalloced(uptr addr, StackTrace *stack) { 410 ScopedInErrorReport in_report; 411 Decorator d; 412 Printf("%s", d.Warning()); 413 Report("ERROR: AddressSanitizer: attempting free on address " 414 "which was not malloc()-ed: %p\n", addr); 415 Printf("%s", d.EndWarning()); 416 PrintStack(stack); 417 DescribeHeapAddress(addr, 1); 418} 419 420void ReportMallocUsableSizeNotOwned(uptr addr, StackTrace *stack) { 421 ScopedInErrorReport in_report; 422 Decorator d; 423 Printf("%s", d.Warning()); 424 Report("ERROR: AddressSanitizer: attempting to call " 425 "malloc_usable_size() for pointer which is " 426 "not owned: %p\n", addr); 427 Printf("%s", d.EndWarning()); 428 PrintStack(stack); 429 DescribeHeapAddress(addr, 1); 430} 431 432void ReportAsanGetAllocatedSizeNotOwned(uptr addr, StackTrace *stack) { 433 ScopedInErrorReport in_report; 434 Decorator d; 435 Printf("%s", d.Warning()); 436 Report("ERROR: AddressSanitizer: attempting to call " 437 "__asan_get_allocated_size() for pointer which is " 438 "not owned: %p\n", addr); 439 Printf("%s", d.EndWarning()); 440 PrintStack(stack); 441 DescribeHeapAddress(addr, 1); 442} 443 444void ReportStringFunctionMemoryRangesOverlap( 445 const char *function, const char *offset1, uptr length1, 446 const char *offset2, uptr length2, StackTrace *stack) { 447 ScopedInErrorReport in_report; 448 Decorator d; 449 Printf("%s", d.Warning()); 450 Report("ERROR: AddressSanitizer: %s-param-overlap: " 451 "memory ranges [%p,%p) and [%p, %p) overlap\n", \ 452 function, offset1, offset1 + length1, offset2, offset2 + length2); 453 Printf("%s", d.EndWarning()); 454 PrintStack(stack); 455 DescribeAddress((uptr)offset1, length1); 456 DescribeAddress((uptr)offset2, length2); 457} 458 459// ----------------------- Mac-specific reports ----------------- {{{1 460 461void WarnMacFreeUnallocated( 462 uptr addr, uptr zone_ptr, const char *zone_name, StackTrace *stack) { 463 // Just print a warning here. 464 Printf("free_common(%p) -- attempting to free unallocated memory.\n" 465 "AddressSanitizer is ignoring this error on Mac OS now.\n", 466 addr); 467 PrintZoneForPointer(addr, zone_ptr, zone_name); 468 PrintStack(stack); 469 DescribeHeapAddress(addr, 1); 470} 471 472void ReportMacMzReallocUnknown( 473 uptr addr, uptr zone_ptr, const char *zone_name, StackTrace *stack) { 474 ScopedInErrorReport in_report; 475 Printf("mz_realloc(%p) -- attempting to realloc unallocated memory.\n" 476 "This is an unrecoverable problem, exiting now.\n", 477 addr); 478 PrintZoneForPointer(addr, zone_ptr, zone_name); 479 PrintStack(stack); 480 DescribeHeapAddress(addr, 1); 481} 482 483void ReportMacCfReallocUnknown( 484 uptr addr, uptr zone_ptr, const char *zone_name, StackTrace *stack) { 485 ScopedInErrorReport in_report; 486 Printf("cf_realloc(%p) -- attempting to realloc unallocated memory.\n" 487 "This is an unrecoverable problem, exiting now.\n", 488 addr); 489 PrintZoneForPointer(addr, zone_ptr, zone_name); 490 PrintStack(stack); 491 DescribeHeapAddress(addr, 1); 492} 493 494} // namespace __asan 495 496// --------------------------- Interface --------------------- {{{1 497using namespace __asan; // NOLINT 498 499void __asan_report_error(uptr pc, uptr bp, uptr sp, 500 uptr addr, bool is_write, uptr access_size) { 501 ScopedInErrorReport in_report; 502 503 // Determine the error type. 504 const char *bug_descr = "unknown-crash"; 505 if (AddrIsInMem(addr)) { 506 u8 *shadow_addr = (u8*)MemToShadow(addr); 507 // If we are accessing 16 bytes, look at the second shadow byte. 508 if (*shadow_addr == 0 && access_size > SHADOW_GRANULARITY) 509 shadow_addr++; 510 // If we are in the partial right redzone, look at the next shadow byte. 511 if (*shadow_addr > 0 && *shadow_addr < 128) 512 shadow_addr++; 513 switch (*shadow_addr) { 514 case kAsanHeapLeftRedzoneMagic: 515 case kAsanHeapRightRedzoneMagic: 516 bug_descr = "heap-buffer-overflow"; 517 break; 518 case kAsanHeapFreeMagic: 519 bug_descr = "heap-use-after-free"; 520 break; 521 case kAsanStackLeftRedzoneMagic: 522 bug_descr = "stack-buffer-underflow"; 523 break; 524 case kAsanInitializationOrderMagic: 525 bug_descr = "initialization-order-fiasco"; 526 break; 527 case kAsanStackMidRedzoneMagic: 528 case kAsanStackRightRedzoneMagic: 529 case kAsanStackPartialRedzoneMagic: 530 bug_descr = "stack-buffer-overflow"; 531 break; 532 case kAsanStackAfterReturnMagic: 533 bug_descr = "stack-use-after-return"; 534 break; 535 case kAsanUserPoisonedMemoryMagic: 536 bug_descr = "use-after-poison"; 537 break; 538 case kAsanStackUseAfterScopeMagic: 539 bug_descr = "stack-use-after-scope"; 540 break; 541 case kAsanGlobalRedzoneMagic: 542 bug_descr = "global-buffer-overflow"; 543 break; 544 } 545 } 546 Decorator d; 547 Printf("%s", d.Warning()); 548 Report("ERROR: AddressSanitizer: %s on address " 549 "%p at pc 0x%zx bp 0x%zx sp 0x%zx\n", 550 bug_descr, (void*)addr, pc, bp, sp); 551 Printf("%s", d.EndWarning()); 552 553 u32 curr_tid = asanThreadRegistry().GetCurrentTidOrInvalid(); 554 char tname[128]; 555 Printf("%s%s of size %zu at %p thread T%d%s%s\n", 556 d.Access(), 557 access_size ? (is_write ? "WRITE" : "READ") : "ACCESS", 558 access_size, (void*)addr, curr_tid, 559 ThreadNameWithParenthesis(curr_tid, tname, sizeof(tname)), 560 d.EndAccess()); 561 562 GET_STACK_TRACE_FATAL(pc, bp); 563 PrintStack(&stack); 564 565 DescribeAddress(addr, access_size); 566 567 PrintShadowMemoryForAddress(addr); 568} 569 570void NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) { 571 error_report_callback = callback; 572 if (callback) { 573 error_message_buffer_size = 1 << 16; 574 error_message_buffer = 575 (char*)MmapOrDie(error_message_buffer_size, __FUNCTION__); 576 error_message_buffer_pos = 0; 577 } 578} 579 580#if !SANITIZER_SUPPORTS_WEAK_HOOKS 581// Provide default implementation of __asan_on_error that does nothing 582// and may be overriden by user. 583SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE NOINLINE 584void __asan_on_error() {} 585#endif 586