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 15 #include "asan_flags.h" 16 #include "asan_internal.h" 17 #include "asan_mapping.h" 18 #include "asan_report.h" 19 #include "asan_scariness_score.h" 20 #include "asan_stack.h" 21 #include "asan_thread.h" 22 #include "sanitizer_common/sanitizer_common.h" 23 #include "sanitizer_common/sanitizer_flags.h" 24 #include "sanitizer_common/sanitizer_report_decorator.h" 25 #include "sanitizer_common/sanitizer_stackdepot.h" 26 #include "sanitizer_common/sanitizer_symbolizer.h" 27 28 namespace __asan { 29 30 // -------------------- User-specified callbacks ----------------- {{{1 31 static void (*error_report_callback)(const char*); 32 static char *error_message_buffer = nullptr; 33 static uptr error_message_buffer_pos = 0; 34 static BlockingMutex error_message_buf_mutex(LINKER_INITIALIZED); 35 static const unsigned kAsanBuggyPcPoolSize = 25; 36 static __sanitizer::atomic_uintptr_t AsanBuggyPcPool[kAsanBuggyPcPoolSize]; 37 38 struct ReportData { 39 uptr pc; 40 uptr sp; 41 uptr bp; 42 uptr addr; 43 bool is_write; 44 uptr access_size; 45 const char *description; 46 }; 47 48 static bool report_happened = false; 49 static ReportData report_data = {}; 50 51 void AppendToErrorMessageBuffer(const char *buffer) { 52 BlockingMutexLock l(&error_message_buf_mutex); 53 if (!error_message_buffer) { 54 error_message_buffer = 55 (char*)MmapOrDieQuietly(kErrorMessageBufferSize, __func__); 56 error_message_buffer_pos = 0; 57 } 58 uptr length = internal_strlen(buffer); 59 RAW_CHECK(kErrorMessageBufferSize >= error_message_buffer_pos); 60 uptr remaining = kErrorMessageBufferSize - error_message_buffer_pos; 61 internal_strncpy(error_message_buffer + error_message_buffer_pos, 62 buffer, remaining); 63 error_message_buffer[kErrorMessageBufferSize - 1] = '\0'; 64 // FIXME: reallocate the buffer instead of truncating the message. 65 error_message_buffer_pos += Min(remaining, length); 66 } 67 68 // ---------------------- Decorator ------------------------------ {{{1 69 class Decorator: public __sanitizer::SanitizerCommonDecorator { 70 public: 71 Decorator() : SanitizerCommonDecorator() { } 72 const char *Access() { return Blue(); } 73 const char *EndAccess() { return Default(); } 74 const char *Location() { return Green(); } 75 const char *EndLocation() { return Default(); } 76 const char *Allocation() { return Magenta(); } 77 const char *EndAllocation() { return Default(); } 78 79 const char *ShadowByte(u8 byte) { 80 switch (byte) { 81 case kAsanHeapLeftRedzoneMagic: 82 case kAsanHeapRightRedzoneMagic: 83 case kAsanArrayCookieMagic: 84 return Red(); 85 case kAsanHeapFreeMagic: 86 return Magenta(); 87 case kAsanStackLeftRedzoneMagic: 88 case kAsanStackMidRedzoneMagic: 89 case kAsanStackRightRedzoneMagic: 90 case kAsanStackPartialRedzoneMagic: 91 return Red(); 92 case kAsanStackAfterReturnMagic: 93 return Magenta(); 94 case kAsanInitializationOrderMagic: 95 return Cyan(); 96 case kAsanUserPoisonedMemoryMagic: 97 case kAsanContiguousContainerOOBMagic: 98 case kAsanAllocaLeftMagic: 99 case kAsanAllocaRightMagic: 100 return Blue(); 101 case kAsanStackUseAfterScopeMagic: 102 return Magenta(); 103 case kAsanGlobalRedzoneMagic: 104 return Red(); 105 case kAsanInternalHeapMagic: 106 return Yellow(); 107 case kAsanIntraObjectRedzone: 108 return Yellow(); 109 default: 110 return Default(); 111 } 112 } 113 const char *EndShadowByte() { return Default(); } 114 const char *MemoryByte() { return Magenta(); } 115 const char *EndMemoryByte() { return Default(); } 116 }; 117 118 // ---------------------- Helper functions ----------------------- {{{1 119 120 static void PrintMemoryByte(InternalScopedString *str, const char *before, 121 u8 byte, bool in_shadow, const char *after = "\n") { 122 Decorator d; 123 str->append("%s%s%x%x%s%s", before, 124 in_shadow ? d.ShadowByte(byte) : d.MemoryByte(), 125 byte >> 4, byte & 15, 126 in_shadow ? d.EndShadowByte() : d.EndMemoryByte(), after); 127 } 128 129 static void PrintShadowByte(InternalScopedString *str, const char *before, 130 u8 byte, const char *after = "\n") { 131 PrintMemoryByte(str, before, byte, /*in_shadow*/true, after); 132 } 133 134 static void PrintShadowBytes(InternalScopedString *str, const char *before, 135 u8 *bytes, u8 *guilty, uptr n) { 136 Decorator d; 137 if (before) str->append("%s%p:", before, bytes); 138 for (uptr i = 0; i < n; i++) { 139 u8 *p = bytes + i; 140 const char *before = 141 p == guilty ? "[" : (p - 1 == guilty && i != 0) ? "" : " "; 142 const char *after = p == guilty ? "]" : ""; 143 PrintShadowByte(str, before, *p, after); 144 } 145 str->append("\n"); 146 } 147 148 static void PrintLegend(InternalScopedString *str) { 149 str->append( 150 "Shadow byte legend (one shadow byte represents %d " 151 "application bytes):\n", 152 (int)SHADOW_GRANULARITY); 153 PrintShadowByte(str, " Addressable: ", 0); 154 str->append(" Partially addressable: "); 155 for (u8 i = 1; i < SHADOW_GRANULARITY; i++) PrintShadowByte(str, "", i, " "); 156 str->append("\n"); 157 PrintShadowByte(str, " Heap left redzone: ", 158 kAsanHeapLeftRedzoneMagic); 159 PrintShadowByte(str, " Heap right redzone: ", 160 kAsanHeapRightRedzoneMagic); 161 PrintShadowByte(str, " Freed heap region: ", kAsanHeapFreeMagic); 162 PrintShadowByte(str, " Stack left redzone: ", 163 kAsanStackLeftRedzoneMagic); 164 PrintShadowByte(str, " Stack mid redzone: ", 165 kAsanStackMidRedzoneMagic); 166 PrintShadowByte(str, " Stack right redzone: ", 167 kAsanStackRightRedzoneMagic); 168 PrintShadowByte(str, " Stack partial redzone: ", 169 kAsanStackPartialRedzoneMagic); 170 PrintShadowByte(str, " Stack after return: ", 171 kAsanStackAfterReturnMagic); 172 PrintShadowByte(str, " Stack use after scope: ", 173 kAsanStackUseAfterScopeMagic); 174 PrintShadowByte(str, " Global redzone: ", kAsanGlobalRedzoneMagic); 175 PrintShadowByte(str, " Global init order: ", 176 kAsanInitializationOrderMagic); 177 PrintShadowByte(str, " Poisoned by user: ", 178 kAsanUserPoisonedMemoryMagic); 179 PrintShadowByte(str, " Container overflow: ", 180 kAsanContiguousContainerOOBMagic); 181 PrintShadowByte(str, " Array cookie: ", 182 kAsanArrayCookieMagic); 183 PrintShadowByte(str, " Intra object redzone: ", 184 kAsanIntraObjectRedzone); 185 PrintShadowByte(str, " ASan internal: ", kAsanInternalHeapMagic); 186 PrintShadowByte(str, " Left alloca redzone: ", kAsanAllocaLeftMagic); 187 PrintShadowByte(str, " Right alloca redzone: ", kAsanAllocaRightMagic); 188 } 189 190 void MaybeDumpInstructionBytes(uptr pc) { 191 if (!flags()->dump_instruction_bytes || (pc < GetPageSizeCached())) 192 return; 193 InternalScopedString str(1024); 194 str.append("First 16 instruction bytes at pc: "); 195 if (IsAccessibleMemoryRange(pc, 16)) { 196 for (int i = 0; i < 16; ++i) { 197 PrintMemoryByte(&str, "", ((u8 *)pc)[i], /*in_shadow*/false, " "); 198 } 199 str.append("\n"); 200 } else { 201 str.append("unaccessible\n"); 202 } 203 Report("%s", str.data()); 204 } 205 206 static void PrintShadowMemoryForAddress(uptr addr) { 207 if (!AddrIsInMem(addr)) return; 208 uptr shadow_addr = MemToShadow(addr); 209 const uptr n_bytes_per_row = 16; 210 uptr aligned_shadow = shadow_addr & ~(n_bytes_per_row - 1); 211 InternalScopedString str(4096 * 8); 212 str.append("Shadow bytes around the buggy address:\n"); 213 for (int i = -5; i <= 5; i++) { 214 const char *prefix = (i == 0) ? "=>" : " "; 215 PrintShadowBytes(&str, prefix, (u8 *)(aligned_shadow + i * n_bytes_per_row), 216 (u8 *)shadow_addr, n_bytes_per_row); 217 } 218 if (flags()->print_legend) PrintLegend(&str); 219 Printf("%s", str.data()); 220 } 221 222 static void PrintZoneForPointer(uptr ptr, uptr zone_ptr, 223 const char *zone_name) { 224 if (zone_ptr) { 225 if (zone_name) { 226 Printf("malloc_zone_from_ptr(%p) = %p, which is %s\n", 227 ptr, zone_ptr, zone_name); 228 } else { 229 Printf("malloc_zone_from_ptr(%p) = %p, which doesn't have a name\n", 230 ptr, zone_ptr); 231 } 232 } else { 233 Printf("malloc_zone_from_ptr(%p) = 0\n", ptr); 234 } 235 } 236 237 static void DescribeThread(AsanThread *t) { 238 if (t) 239 DescribeThread(t->context()); 240 } 241 242 // ---------------------- Address Descriptions ------------------- {{{1 243 244 static bool IsASCII(unsigned char c) { 245 return /*0x00 <= c &&*/ c <= 0x7F; 246 } 247 248 static const char *MaybeDemangleGlobalName(const char *name) { 249 // We can spoil names of globals with C linkage, so use an heuristic 250 // approach to check if the name should be demangled. 251 bool should_demangle = false; 252 if (name[0] == '_' && name[1] == 'Z') 253 should_demangle = true; 254 else if (SANITIZER_WINDOWS && name[0] == '\01' && name[1] == '?') 255 should_demangle = true; 256 257 return should_demangle ? Symbolizer::GetOrInit()->Demangle(name) : name; 258 } 259 260 // Check if the global is a zero-terminated ASCII string. If so, print it. 261 static void PrintGlobalNameIfASCII(InternalScopedString *str, 262 const __asan_global &g) { 263 for (uptr p = g.beg; p < g.beg + g.size - 1; p++) { 264 unsigned char c = *(unsigned char*)p; 265 if (c == '\0' || !IsASCII(c)) return; 266 } 267 if (*(char*)(g.beg + g.size - 1) != '\0') return; 268 str->append(" '%s' is ascii string '%s'\n", MaybeDemangleGlobalName(g.name), 269 (char *)g.beg); 270 } 271 272 static const char *GlobalFilename(const __asan_global &g) { 273 const char *res = g.module_name; 274 // Prefer the filename from source location, if is available. 275 if (g.location) 276 res = g.location->filename; 277 CHECK(res); 278 return res; 279 } 280 281 static void PrintGlobalLocation(InternalScopedString *str, 282 const __asan_global &g) { 283 str->append("%s", GlobalFilename(g)); 284 if (!g.location) 285 return; 286 if (g.location->line_no) 287 str->append(":%d", g.location->line_no); 288 if (g.location->column_no) 289 str->append(":%d", g.location->column_no); 290 } 291 292 static void DescribeAddressRelativeToGlobal(uptr addr, uptr size, 293 const __asan_global &g) { 294 InternalScopedString str(4096); 295 Decorator d; 296 str.append("%s", d.Location()); 297 if (addr < g.beg) { 298 str.append("%p is located %zd bytes to the left", (void *)addr, 299 g.beg - addr); 300 } else if (addr + size > g.beg + g.size) { 301 if (addr < g.beg + g.size) 302 addr = g.beg + g.size; 303 str.append("%p is located %zd bytes to the right", (void *)addr, 304 addr - (g.beg + g.size)); 305 } else { 306 // Can it happen? 307 str.append("%p is located %zd bytes inside", (void *)addr, addr - g.beg); 308 } 309 str.append(" of global variable '%s' defined in '", 310 MaybeDemangleGlobalName(g.name)); 311 PrintGlobalLocation(&str, g); 312 str.append("' (0x%zx) of size %zu\n", g.beg, g.size); 313 str.append("%s", d.EndLocation()); 314 PrintGlobalNameIfASCII(&str, g); 315 Printf("%s", str.data()); 316 } 317 318 static bool DescribeAddressIfGlobal(uptr addr, uptr size, 319 const char *bug_type) { 320 // Assume address is close to at most four globals. 321 const int kMaxGlobalsInReport = 4; 322 __asan_global globals[kMaxGlobalsInReport]; 323 u32 reg_sites[kMaxGlobalsInReport]; 324 int globals_num = 325 GetGlobalsForAddress(addr, globals, reg_sites, ARRAY_SIZE(globals)); 326 if (globals_num == 0) 327 return false; 328 for (int i = 0; i < globals_num; i++) { 329 DescribeAddressRelativeToGlobal(addr, size, globals[i]); 330 if (0 == internal_strcmp(bug_type, "initialization-order-fiasco") && 331 reg_sites[i]) { 332 Printf(" registered at:\n"); 333 StackDepotGet(reg_sites[i]).Print(); 334 } 335 } 336 return true; 337 } 338 339 bool DescribeAddressIfShadow(uptr addr, AddressDescription *descr, bool print) { 340 if (AddrIsInMem(addr)) 341 return false; 342 const char *area_type = nullptr; 343 if (AddrIsInShadowGap(addr)) area_type = "shadow gap"; 344 else if (AddrIsInHighShadow(addr)) area_type = "high shadow"; 345 else if (AddrIsInLowShadow(addr)) area_type = "low shadow"; 346 if (area_type != nullptr) { 347 if (print) { 348 Printf("Address %p is located in the %s area.\n", addr, area_type); 349 } else { 350 CHECK(descr); 351 descr->region_kind = area_type; 352 } 353 return true; 354 } 355 CHECK(0 && "Address is not in memory and not in shadow?"); 356 return false; 357 } 358 359 // Return " (thread_name) " or an empty string if the name is empty. 360 const char *ThreadNameWithParenthesis(AsanThreadContext *t, char buff[], 361 uptr buff_len) { 362 const char *name = t->name; 363 if (name[0] == '\0') return ""; 364 buff[0] = 0; 365 internal_strncat(buff, " (", 3); 366 internal_strncat(buff, name, buff_len - 4); 367 internal_strncat(buff, ")", 2); 368 return buff; 369 } 370 371 const char *ThreadNameWithParenthesis(u32 tid, char buff[], 372 uptr buff_len) { 373 if (tid == kInvalidTid) return ""; 374 asanThreadRegistry().CheckLocked(); 375 AsanThreadContext *t = GetThreadContextByTidLocked(tid); 376 return ThreadNameWithParenthesis(t, buff, buff_len); 377 } 378 379 static void PrintAccessAndVarIntersection(const StackVarDescr &var, uptr addr, 380 uptr access_size, uptr prev_var_end, 381 uptr next_var_beg) { 382 uptr var_end = var.beg + var.size; 383 uptr addr_end = addr + access_size; 384 const char *pos_descr = nullptr; 385 // If the variable [var.beg, var_end) is the nearest variable to the 386 // current memory access, indicate it in the log. 387 if (addr >= var.beg) { 388 if (addr_end <= var_end) 389 pos_descr = "is inside"; // May happen if this is a use-after-return. 390 else if (addr < var_end) 391 pos_descr = "partially overflows"; 392 else if (addr_end <= next_var_beg && 393 next_var_beg - addr_end >= addr - var_end) 394 pos_descr = "overflows"; 395 } else { 396 if (addr_end > var.beg) 397 pos_descr = "partially underflows"; 398 else if (addr >= prev_var_end && 399 addr - prev_var_end >= var.beg - addr_end) 400 pos_descr = "underflows"; 401 } 402 InternalScopedString str(1024); 403 str.append(" [%zd, %zd)", var.beg, var_end); 404 // Render variable name. 405 str.append(" '"); 406 for (uptr i = 0; i < var.name_len; ++i) { 407 str.append("%c", var.name_pos[i]); 408 } 409 str.append("'"); 410 if (pos_descr) { 411 Decorator d; 412 // FIXME: we may want to also print the size of the access here, 413 // but in case of accesses generated by memset it may be confusing. 414 str.append("%s <== Memory access at offset %zd %s this variable%s\n", 415 d.Location(), addr, pos_descr, d.EndLocation()); 416 } else { 417 str.append("\n"); 418 } 419 Printf("%s", str.data()); 420 } 421 422 bool ParseFrameDescription(const char *frame_descr, 423 InternalMmapVector<StackVarDescr> *vars) { 424 CHECK(frame_descr); 425 char *p; 426 // This string is created by the compiler and has the following form: 427 // "n alloc_1 alloc_2 ... alloc_n" 428 // where alloc_i looks like "offset size len ObjectName". 429 uptr n_objects = (uptr)internal_simple_strtoll(frame_descr, &p, 10); 430 if (n_objects == 0) 431 return false; 432 433 for (uptr i = 0; i < n_objects; i++) { 434 uptr beg = (uptr)internal_simple_strtoll(p, &p, 10); 435 uptr size = (uptr)internal_simple_strtoll(p, &p, 10); 436 uptr len = (uptr)internal_simple_strtoll(p, &p, 10); 437 if (beg == 0 || size == 0 || *p != ' ') { 438 return false; 439 } 440 p++; 441 StackVarDescr var = {beg, size, p, len}; 442 vars->push_back(var); 443 p += len; 444 } 445 446 return true; 447 } 448 449 bool DescribeAddressIfStack(uptr addr, uptr access_size) { 450 AsanThread *t = FindThreadByStackAddress(addr); 451 if (!t) return false; 452 453 Decorator d; 454 char tname[128]; 455 Printf("%s", d.Location()); 456 Printf("Address %p is located in stack of thread T%d%s", addr, t->tid(), 457 ThreadNameWithParenthesis(t->tid(), tname, sizeof(tname))); 458 459 // Try to fetch precise stack frame for this access. 460 AsanThread::StackFrameAccess access; 461 if (!t->GetStackFrameAccessByAddr(addr, &access)) { 462 Printf("%s\n", d.EndLocation()); 463 return true; 464 } 465 Printf(" at offset %zu in frame%s\n", access.offset, d.EndLocation()); 466 467 // Now we print the frame where the alloca has happened. 468 // We print this frame as a stack trace with one element. 469 // The symbolizer may print more than one frame if inlining was involved. 470 // The frame numbers may be different than those in the stack trace printed 471 // previously. That's unfortunate, but I have no better solution, 472 // especially given that the alloca may be from entirely different place 473 // (e.g. use-after-scope, or different thread's stack). 474 #if SANITIZER_PPC64V1 475 // On PowerPC64 ELFv1, the address of a function actually points to a 476 // three-doubleword data structure with the first field containing 477 // the address of the function's code. 478 access.frame_pc = *reinterpret_cast<uptr *>(access.frame_pc); 479 #endif 480 access.frame_pc += 16; 481 Printf("%s", d.EndLocation()); 482 StackTrace alloca_stack(&access.frame_pc, 1); 483 alloca_stack.Print(); 484 485 InternalMmapVector<StackVarDescr> vars(16); 486 if (!ParseFrameDescription(access.frame_descr, &vars)) { 487 Printf("AddressSanitizer can't parse the stack frame " 488 "descriptor: |%s|\n", access.frame_descr); 489 // 'addr' is a stack address, so return true even if we can't parse frame 490 return true; 491 } 492 uptr n_objects = vars.size(); 493 // Report the number of stack objects. 494 Printf(" This frame has %zu object(s):\n", n_objects); 495 496 // Report all objects in this frame. 497 for (uptr i = 0; i < n_objects; i++) { 498 uptr prev_var_end = i ? vars[i - 1].beg + vars[i - 1].size : 0; 499 uptr next_var_beg = i + 1 < n_objects ? vars[i + 1].beg : ~(0UL); 500 PrintAccessAndVarIntersection(vars[i], access.offset, access_size, 501 prev_var_end, next_var_beg); 502 } 503 Printf("HINT: this may be a false positive if your program uses " 504 "some custom stack unwind mechanism or swapcontext\n"); 505 if (SANITIZER_WINDOWS) 506 Printf(" (longjmp, SEH and C++ exceptions *are* supported)\n"); 507 else 508 Printf(" (longjmp and C++ exceptions *are* supported)\n"); 509 510 DescribeThread(t); 511 return true; 512 } 513 514 static void DescribeAccessToHeapChunk(AsanChunkView chunk, uptr addr, 515 uptr access_size) { 516 sptr offset; 517 Decorator d; 518 InternalScopedString str(4096); 519 str.append("%s", d.Location()); 520 if (chunk.AddrIsAtLeft(addr, access_size, &offset)) { 521 str.append("%p is located %zd bytes to the left of", (void *)addr, offset); 522 } else if (chunk.AddrIsAtRight(addr, access_size, &offset)) { 523 if (offset < 0) { 524 addr -= offset; 525 offset = 0; 526 } 527 str.append("%p is located %zd bytes to the right of", (void *)addr, offset); 528 } else if (chunk.AddrIsInside(addr, access_size, &offset)) { 529 str.append("%p is located %zd bytes inside of", (void*)addr, offset); 530 } else { 531 str.append("%p is located somewhere around (this is AddressSanitizer bug!)", 532 (void *)addr); 533 } 534 str.append(" %zu-byte region [%p,%p)\n", chunk.UsedSize(), 535 (void *)(chunk.Beg()), (void *)(chunk.End())); 536 str.append("%s", d.EndLocation()); 537 Printf("%s", str.data()); 538 } 539 540 void DescribeHeapAddress(uptr addr, uptr access_size) { 541 AsanChunkView chunk = FindHeapChunkByAddress(addr); 542 if (!chunk.IsValid()) { 543 Printf("AddressSanitizer can not describe address in more detail " 544 "(wild memory access suspected).\n"); 545 return; 546 } 547 DescribeAccessToHeapChunk(chunk, addr, access_size); 548 CHECK(chunk.AllocTid() != kInvalidTid); 549 asanThreadRegistry().CheckLocked(); 550 AsanThreadContext *alloc_thread = 551 GetThreadContextByTidLocked(chunk.AllocTid()); 552 StackTrace alloc_stack = chunk.GetAllocStack(); 553 char tname[128]; 554 Decorator d; 555 AsanThreadContext *free_thread = nullptr; 556 if (chunk.FreeTid() != kInvalidTid) { 557 free_thread = GetThreadContextByTidLocked(chunk.FreeTid()); 558 Printf("%sfreed by thread T%d%s here:%s\n", d.Allocation(), 559 free_thread->tid, 560 ThreadNameWithParenthesis(free_thread, tname, sizeof(tname)), 561 d.EndAllocation()); 562 StackTrace free_stack = chunk.GetFreeStack(); 563 free_stack.Print(); 564 Printf("%spreviously allocated by thread T%d%s here:%s\n", 565 d.Allocation(), alloc_thread->tid, 566 ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)), 567 d.EndAllocation()); 568 } else { 569 Printf("%sallocated by thread T%d%s here:%s\n", d.Allocation(), 570 alloc_thread->tid, 571 ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)), 572 d.EndAllocation()); 573 } 574 alloc_stack.Print(); 575 DescribeThread(GetCurrentThread()); 576 if (free_thread) 577 DescribeThread(free_thread); 578 DescribeThread(alloc_thread); 579 } 580 581 static void DescribeAddress(uptr addr, uptr access_size, const char *bug_type) { 582 // Check if this is shadow or shadow gap. 583 if (DescribeAddressIfShadow(addr)) 584 return; 585 CHECK(AddrIsInMem(addr)); 586 if (DescribeAddressIfGlobal(addr, access_size, bug_type)) 587 return; 588 if (DescribeAddressIfStack(addr, access_size)) 589 return; 590 // Assume it is a heap address. 591 DescribeHeapAddress(addr, access_size); 592 } 593 594 // ------------------- Thread description -------------------- {{{1 595 596 void DescribeThread(AsanThreadContext *context) { 597 CHECK(context); 598 asanThreadRegistry().CheckLocked(); 599 // No need to announce the main thread. 600 if (context->tid == 0 || context->announced) { 601 return; 602 } 603 context->announced = true; 604 char tname[128]; 605 InternalScopedString str(1024); 606 str.append("Thread T%d%s", context->tid, 607 ThreadNameWithParenthesis(context->tid, tname, sizeof(tname))); 608 if (context->parent_tid == kInvalidTid) { 609 str.append(" created by unknown thread\n"); 610 Printf("%s", str.data()); 611 return; 612 } 613 str.append( 614 " created by T%d%s here:\n", context->parent_tid, 615 ThreadNameWithParenthesis(context->parent_tid, tname, sizeof(tname))); 616 Printf("%s", str.data()); 617 StackDepotGet(context->stack_id).Print(); 618 // Recursively described parent thread if needed. 619 if (flags()->print_full_thread_history) { 620 AsanThreadContext *parent_context = 621 GetThreadContextByTidLocked(context->parent_tid); 622 DescribeThread(parent_context); 623 } 624 } 625 626 // -------------------- Different kinds of reports ----------------- {{{1 627 628 // Use ScopedInErrorReport to run common actions just before and 629 // immediately after printing error report. 630 class ScopedInErrorReport { 631 public: 632 explicit ScopedInErrorReport(ReportData *report = nullptr, 633 bool fatal = false) { 634 halt_on_error_ = fatal || flags()->halt_on_error; 635 636 if (lock_.TryLock()) { 637 StartReporting(report); 638 return; 639 } 640 641 // ASan found two bugs in different threads simultaneously. 642 643 u32 current_tid = GetCurrentTidOrInvalid(); 644 if (reporting_thread_tid_ == current_tid || 645 reporting_thread_tid_ == kInvalidTid) { 646 // This is either asynch signal or nested error during error reporting. 647 // Fail simple to avoid deadlocks in Report(). 648 649 // Can't use Report() here because of potential deadlocks 650 // in nested signal handlers. 651 const char msg[] = "AddressSanitizer: nested bug in the same thread, " 652 "aborting.\n"; 653 WriteToFile(kStderrFd, msg, sizeof(msg)); 654 655 internal__exit(common_flags()->exitcode); 656 } 657 658 if (halt_on_error_) { 659 // Do not print more than one report, otherwise they will mix up. 660 // Error reporting functions shouldn't return at this situation, as 661 // they are effectively no-returns. 662 663 Report("AddressSanitizer: while reporting a bug found another one. " 664 "Ignoring.\n"); 665 666 // Sleep long enough to make sure that the thread which started 667 // to print an error report will finish doing it. 668 SleepForSeconds(Max(100, flags()->sleep_before_dying + 1)); 669 670 // If we're still not dead for some reason, use raw _exit() instead of 671 // Die() to bypass any additional checks. 672 internal__exit(common_flags()->exitcode); 673 } else { 674 // The other thread will eventually finish reporting 675 // so it's safe to wait 676 lock_.Lock(); 677 } 678 679 StartReporting(report); 680 } 681 682 ~ScopedInErrorReport() { 683 // Make sure the current thread is announced. 684 DescribeThread(GetCurrentThread()); 685 // We may want to grab this lock again when printing stats. 686 asanThreadRegistry().Unlock(); 687 // Print memory stats. 688 if (flags()->print_stats) 689 __asan_print_accumulated_stats(); 690 691 if (common_flags()->print_cmdline) 692 PrintCmdline(); 693 694 // Copy the message buffer so that we could start logging without holding a 695 // lock that gets aquired during printing. 696 InternalScopedBuffer<char> buffer_copy(kErrorMessageBufferSize); 697 { 698 BlockingMutexLock l(&error_message_buf_mutex); 699 internal_memcpy(buffer_copy.data(), 700 error_message_buffer, kErrorMessageBufferSize); 701 } 702 703 LogFullErrorReport(buffer_copy.data()); 704 705 if (error_report_callback) { 706 error_report_callback(buffer_copy.data()); 707 } 708 CommonSanitizerReportMutex.Unlock(); 709 reporting_thread_tid_ = kInvalidTid; 710 lock_.Unlock(); 711 if (halt_on_error_) { 712 Report("ABORTING\n"); 713 Die(); 714 } 715 } 716 717 private: 718 void StartReporting(ReportData *report) { 719 if (report) report_data = *report; 720 report_happened = true; 721 ASAN_ON_ERROR(); 722 // Make sure the registry and sanitizer report mutexes are locked while 723 // we're printing an error report. 724 // We can lock them only here to avoid self-deadlock in case of 725 // recursive reports. 726 asanThreadRegistry().Lock(); 727 CommonSanitizerReportMutex.Lock(); 728 reporting_thread_tid_ = GetCurrentTidOrInvalid(); 729 Printf("====================================================" 730 "=============\n"); 731 } 732 733 static StaticSpinMutex lock_; 734 static u32 reporting_thread_tid_; 735 bool halt_on_error_; 736 }; 737 738 StaticSpinMutex ScopedInErrorReport::lock_; 739 u32 ScopedInErrorReport::reporting_thread_tid_ = kInvalidTid; 740 741 void ReportStackOverflow(const SignalContext &sig) { 742 ScopedInErrorReport in_report(/*report*/ nullptr, /*fatal*/ true); 743 Decorator d; 744 Printf("%s", d.Warning()); 745 Report( 746 "ERROR: AddressSanitizer: stack-overflow on address %p" 747 " (pc %p bp %p sp %p T%d)\n", 748 (void *)sig.addr, (void *)sig.pc, (void *)sig.bp, (void *)sig.sp, 749 GetCurrentTidOrInvalid()); 750 Printf("%s", d.EndWarning()); 751 ScarinessScore::PrintSimple(10, "stack-overflow"); 752 GET_STACK_TRACE_SIGNAL(sig); 753 stack.Print(); 754 ReportErrorSummary("stack-overflow", &stack); 755 } 756 757 void ReportDeadlySignal(const char *description, const SignalContext &sig) { 758 ScopedInErrorReport in_report(/*report*/ nullptr, /*fatal*/ true); 759 Decorator d; 760 Printf("%s", d.Warning()); 761 Report( 762 "ERROR: AddressSanitizer: %s on unknown address %p" 763 " (pc %p bp %p sp %p T%d)\n", 764 description, (void *)sig.addr, (void *)sig.pc, (void *)sig.bp, 765 (void *)sig.sp, GetCurrentTidOrInvalid()); 766 Printf("%s", d.EndWarning()); 767 ScarinessScore SS; 768 if (sig.pc < GetPageSizeCached()) 769 Report("Hint: pc points to the zero page.\n"); 770 if (sig.is_memory_access) { 771 const char *access_type = 772 sig.write_flag == SignalContext::WRITE 773 ? "WRITE" 774 : (sig.write_flag == SignalContext::READ ? "READ" : "UNKNOWN"); 775 Report("The signal is caused by a %s memory access.\n", access_type); 776 if (sig.addr < GetPageSizeCached()) { 777 Report("Hint: address points to the zero page.\n"); 778 SS.Scare(10, "null-deref"); 779 } else if (sig.addr == sig.pc) { 780 SS.Scare(60, "wild-jump"); 781 } else if (sig.write_flag == SignalContext::WRITE) { 782 SS.Scare(30, "wild-addr-write"); 783 } else if (sig.write_flag == SignalContext::READ) { 784 SS.Scare(20, "wild-addr-read"); 785 } else { 786 SS.Scare(25, "wild-addr"); 787 } 788 } else { 789 SS.Scare(10, "signal"); 790 } 791 SS.Print(); 792 GET_STACK_TRACE_SIGNAL(sig); 793 stack.Print(); 794 MaybeDumpInstructionBytes(sig.pc); 795 Printf("AddressSanitizer can not provide additional info.\n"); 796 ReportErrorSummary(description, &stack); 797 } 798 799 void ReportDoubleFree(uptr addr, BufferedStackTrace *free_stack) { 800 ScopedInErrorReport in_report; 801 Decorator d; 802 Printf("%s", d.Warning()); 803 char tname[128]; 804 u32 curr_tid = GetCurrentTidOrInvalid(); 805 Report("ERROR: AddressSanitizer: attempting double-free on %p in " 806 "thread T%d%s:\n", 807 addr, curr_tid, 808 ThreadNameWithParenthesis(curr_tid, tname, sizeof(tname))); 809 Printf("%s", d.EndWarning()); 810 CHECK_GT(free_stack->size, 0); 811 ScarinessScore::PrintSimple(42, "double-free"); 812 GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp); 813 stack.Print(); 814 DescribeHeapAddress(addr, 1); 815 ReportErrorSummary("double-free", &stack); 816 } 817 818 void ReportNewDeleteSizeMismatch(uptr addr, uptr alloc_size, uptr delete_size, 819 BufferedStackTrace *free_stack) { 820 ScopedInErrorReport in_report; 821 Decorator d; 822 Printf("%s", d.Warning()); 823 char tname[128]; 824 u32 curr_tid = GetCurrentTidOrInvalid(); 825 Report("ERROR: AddressSanitizer: new-delete-type-mismatch on %p in " 826 "thread T%d%s:\n", 827 addr, curr_tid, 828 ThreadNameWithParenthesis(curr_tid, tname, sizeof(tname))); 829 Printf("%s object passed to delete has wrong type:\n", d.EndWarning()); 830 Printf(" size of the allocated type: %zd bytes;\n" 831 " size of the deallocated type: %zd bytes.\n", 832 alloc_size, delete_size); 833 CHECK_GT(free_stack->size, 0); 834 ScarinessScore::PrintSimple(10, "new-delete-type-mismatch"); 835 GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp); 836 stack.Print(); 837 DescribeHeapAddress(addr, 1); 838 ReportErrorSummary("new-delete-type-mismatch", &stack); 839 Report("HINT: if you don't care about these errors you may set " 840 "ASAN_OPTIONS=new_delete_type_mismatch=0\n"); 841 } 842 843 void ReportFreeNotMalloced(uptr addr, BufferedStackTrace *free_stack) { 844 ScopedInErrorReport in_report; 845 Decorator d; 846 Printf("%s", d.Warning()); 847 char tname[128]; 848 u32 curr_tid = GetCurrentTidOrInvalid(); 849 Report("ERROR: AddressSanitizer: attempting free on address " 850 "which was not malloc()-ed: %p in thread T%d%s\n", addr, 851 curr_tid, ThreadNameWithParenthesis(curr_tid, tname, sizeof(tname))); 852 Printf("%s", d.EndWarning()); 853 CHECK_GT(free_stack->size, 0); 854 ScarinessScore::PrintSimple(40, "bad-free"); 855 GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp); 856 stack.Print(); 857 DescribeHeapAddress(addr, 1); 858 ReportErrorSummary("bad-free", &stack); 859 } 860 861 void ReportAllocTypeMismatch(uptr addr, BufferedStackTrace *free_stack, 862 AllocType alloc_type, 863 AllocType dealloc_type) { 864 static const char *alloc_names[] = 865 {"INVALID", "malloc", "operator new", "operator new []"}; 866 static const char *dealloc_names[] = 867 {"INVALID", "free", "operator delete", "operator delete []"}; 868 CHECK_NE(alloc_type, dealloc_type); 869 ScopedInErrorReport in_report; 870 Decorator d; 871 Printf("%s", d.Warning()); 872 Report("ERROR: AddressSanitizer: alloc-dealloc-mismatch (%s vs %s) on %p\n", 873 alloc_names[alloc_type], dealloc_names[dealloc_type], addr); 874 Printf("%s", d.EndWarning()); 875 CHECK_GT(free_stack->size, 0); 876 ScarinessScore::PrintSimple(10, "alloc-dealloc-mismatch"); 877 GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp); 878 stack.Print(); 879 DescribeHeapAddress(addr, 1); 880 ReportErrorSummary("alloc-dealloc-mismatch", &stack); 881 Report("HINT: if you don't care about these errors you may set " 882 "ASAN_OPTIONS=alloc_dealloc_mismatch=0\n"); 883 } 884 885 void ReportMallocUsableSizeNotOwned(uptr addr, BufferedStackTrace *stack) { 886 ScopedInErrorReport in_report; 887 Decorator d; 888 Printf("%s", d.Warning()); 889 Report("ERROR: AddressSanitizer: attempting to call " 890 "malloc_usable_size() for pointer which is " 891 "not owned: %p\n", addr); 892 Printf("%s", d.EndWarning()); 893 stack->Print(); 894 DescribeHeapAddress(addr, 1); 895 ReportErrorSummary("bad-malloc_usable_size", stack); 896 } 897 898 void ReportSanitizerGetAllocatedSizeNotOwned(uptr addr, 899 BufferedStackTrace *stack) { 900 ScopedInErrorReport in_report; 901 Decorator d; 902 Printf("%s", d.Warning()); 903 Report("ERROR: AddressSanitizer: attempting to call " 904 "__sanitizer_get_allocated_size() for pointer which is " 905 "not owned: %p\n", addr); 906 Printf("%s", d.EndWarning()); 907 stack->Print(); 908 DescribeHeapAddress(addr, 1); 909 ReportErrorSummary("bad-__sanitizer_get_allocated_size", stack); 910 } 911 912 void ReportStringFunctionMemoryRangesOverlap(const char *function, 913 const char *offset1, uptr length1, 914 const char *offset2, uptr length2, 915 BufferedStackTrace *stack) { 916 ScopedInErrorReport in_report; 917 Decorator d; 918 char bug_type[100]; 919 internal_snprintf(bug_type, sizeof(bug_type), "%s-param-overlap", function); 920 Printf("%s", d.Warning()); 921 Report("ERROR: AddressSanitizer: %s: " 922 "memory ranges [%p,%p) and [%p, %p) overlap\n", \ 923 bug_type, offset1, offset1 + length1, offset2, offset2 + length2); 924 Printf("%s", d.EndWarning()); 925 ScarinessScore::PrintSimple(10, bug_type); 926 stack->Print(); 927 DescribeAddress((uptr)offset1, length1, bug_type); 928 DescribeAddress((uptr)offset2, length2, bug_type); 929 ReportErrorSummary(bug_type, stack); 930 } 931 932 void ReportStringFunctionSizeOverflow(uptr offset, uptr size, 933 BufferedStackTrace *stack) { 934 ScopedInErrorReport in_report; 935 Decorator d; 936 const char *bug_type = "negative-size-param"; 937 Printf("%s", d.Warning()); 938 Report("ERROR: AddressSanitizer: %s: (size=%zd)\n", bug_type, size); 939 Printf("%s", d.EndWarning()); 940 ScarinessScore::PrintSimple(10, bug_type); 941 stack->Print(); 942 DescribeAddress(offset, size, bug_type); 943 ReportErrorSummary(bug_type, stack); 944 } 945 946 void ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end, 947 uptr old_mid, uptr new_mid, 948 BufferedStackTrace *stack) { 949 ScopedInErrorReport in_report; 950 Report("ERROR: AddressSanitizer: bad parameters to " 951 "__sanitizer_annotate_contiguous_container:\n" 952 " beg : %p\n" 953 " end : %p\n" 954 " old_mid : %p\n" 955 " new_mid : %p\n", 956 beg, end, old_mid, new_mid); 957 uptr granularity = SHADOW_GRANULARITY; 958 if (!IsAligned(beg, granularity)) 959 Report("ERROR: beg is not aligned by %d\n", granularity); 960 stack->Print(); 961 ReportErrorSummary("bad-__sanitizer_annotate_contiguous_container", stack); 962 } 963 964 void ReportODRViolation(const __asan_global *g1, u32 stack_id1, 965 const __asan_global *g2, u32 stack_id2) { 966 ScopedInErrorReport in_report; 967 Decorator d; 968 Printf("%s", d.Warning()); 969 Report("ERROR: AddressSanitizer: odr-violation (%p):\n", g1->beg); 970 Printf("%s", d.EndWarning()); 971 InternalScopedString g1_loc(256), g2_loc(256); 972 PrintGlobalLocation(&g1_loc, *g1); 973 PrintGlobalLocation(&g2_loc, *g2); 974 Printf(" [1] size=%zd '%s' %s\n", g1->size, 975 MaybeDemangleGlobalName(g1->name), g1_loc.data()); 976 Printf(" [2] size=%zd '%s' %s\n", g2->size, 977 MaybeDemangleGlobalName(g2->name), g2_loc.data()); 978 if (stack_id1 && stack_id2) { 979 Printf("These globals were registered at these points:\n"); 980 Printf(" [1]:\n"); 981 StackDepotGet(stack_id1).Print(); 982 Printf(" [2]:\n"); 983 StackDepotGet(stack_id2).Print(); 984 } 985 Report("HINT: if you don't care about these errors you may set " 986 "ASAN_OPTIONS=detect_odr_violation=0\n"); 987 InternalScopedString error_msg(256); 988 error_msg.append("odr-violation: global '%s' at %s", 989 MaybeDemangleGlobalName(g1->name), g1_loc.data()); 990 ReportErrorSummary(error_msg.data()); 991 } 992 993 // ----------------------- CheckForInvalidPointerPair ----------- {{{1 994 static NOINLINE void 995 ReportInvalidPointerPair(uptr pc, uptr bp, uptr sp, uptr a1, uptr a2) { 996 ScopedInErrorReport in_report; 997 const char *bug_type = "invalid-pointer-pair"; 998 Decorator d; 999 Printf("%s", d.Warning()); 1000 Report("ERROR: AddressSanitizer: invalid-pointer-pair: %p %p\n", a1, a2); 1001 Printf("%s", d.EndWarning()); 1002 GET_STACK_TRACE_FATAL(pc, bp); 1003 stack.Print(); 1004 DescribeAddress(a1, 1, bug_type); 1005 DescribeAddress(a2, 1, bug_type); 1006 ReportErrorSummary(bug_type, &stack); 1007 } 1008 1009 static INLINE void CheckForInvalidPointerPair(void *p1, void *p2) { 1010 if (!flags()->detect_invalid_pointer_pairs) return; 1011 uptr a1 = reinterpret_cast<uptr>(p1); 1012 uptr a2 = reinterpret_cast<uptr>(p2); 1013 AsanChunkView chunk1 = FindHeapChunkByAddress(a1); 1014 AsanChunkView chunk2 = FindHeapChunkByAddress(a2); 1015 bool valid1 = chunk1.IsAllocated(); 1016 bool valid2 = chunk2.IsAllocated(); 1017 if (!valid1 || !valid2 || !chunk1.Eq(chunk2)) { 1018 GET_CALLER_PC_BP_SP; 1019 return ReportInvalidPointerPair(pc, bp, sp, a1, a2); 1020 } 1021 } 1022 // ----------------------- Mac-specific reports ----------------- {{{1 1023 1024 void ReportMacMzReallocUnknown(uptr addr, uptr zone_ptr, const char *zone_name, 1025 BufferedStackTrace *stack) { 1026 ScopedInErrorReport in_report; 1027 Printf("mz_realloc(%p) -- attempting to realloc unallocated memory.\n" 1028 "This is an unrecoverable problem, exiting now.\n", 1029 addr); 1030 PrintZoneForPointer(addr, zone_ptr, zone_name); 1031 stack->Print(); 1032 DescribeHeapAddress(addr, 1); 1033 } 1034 1035 // -------------- SuppressErrorReport -------------- {{{1 1036 // Avoid error reports duplicating for ASan recover mode. 1037 static bool SuppressErrorReport(uptr pc) { 1038 if (!common_flags()->suppress_equal_pcs) return false; 1039 for (unsigned i = 0; i < kAsanBuggyPcPoolSize; i++) { 1040 uptr cmp = atomic_load_relaxed(&AsanBuggyPcPool[i]); 1041 if (cmp == 0 && atomic_compare_exchange_strong(&AsanBuggyPcPool[i], &cmp, 1042 pc, memory_order_relaxed)) 1043 return false; 1044 if (cmp == pc) return true; 1045 } 1046 Die(); 1047 } 1048 1049 static void PrintContainerOverflowHint() { 1050 Printf("HINT: if you don't care about these errors you may set " 1051 "ASAN_OPTIONS=detect_container_overflow=0.\n" 1052 "If you suspect a false positive see also: " 1053 "https://github.com/google/sanitizers/wiki/" 1054 "AddressSanitizerContainerOverflow.\n"); 1055 } 1056 1057 static bool AdjacentShadowValuesAreFullyPoisoned(u8 *s) { 1058 return s[-1] > 127 && s[1] > 127; 1059 } 1060 1061 void ReportGenericError(uptr pc, uptr bp, uptr sp, uptr addr, bool is_write, 1062 uptr access_size, u32 exp, bool fatal) { 1063 if (!fatal && SuppressErrorReport(pc)) return; 1064 ENABLE_FRAME_POINTER; 1065 ScarinessScore SS; 1066 1067 if (access_size) { 1068 if (access_size <= 9) { 1069 char desr[] = "?-byte"; 1070 desr[0] = '0' + access_size; 1071 SS.Scare(access_size + access_size / 2, desr); 1072 } else if (access_size >= 10) { 1073 SS.Scare(15, "multi-byte"); 1074 } 1075 is_write ? SS.Scare(20, "write") : SS.Scare(1, "read"); 1076 } 1077 1078 // Optimization experiments. 1079 // The experiments can be used to evaluate potential optimizations that remove 1080 // instrumentation (assess false negatives). Instead of completely removing 1081 // some instrumentation, compiler can emit special calls into runtime 1082 // (e.g. __asan_report_exp_load1 instead of __asan_report_load1) and pass 1083 // mask of experiments (exp). 1084 // The reaction to a non-zero value of exp is to be defined. 1085 (void)exp; 1086 1087 // Determine the error type. 1088 const char *bug_descr = "unknown-crash"; 1089 u8 shadow_val = 0; 1090 if (AddrIsInMem(addr)) { 1091 u8 *shadow_addr = (u8*)MemToShadow(addr); 1092 // If we are accessing 16 bytes, look at the second shadow byte. 1093 if (*shadow_addr == 0 && access_size > SHADOW_GRANULARITY) 1094 shadow_addr++; 1095 // If we are in the partial right redzone, look at the next shadow byte. 1096 if (*shadow_addr > 0 && *shadow_addr < 128) 1097 shadow_addr++; 1098 bool far_from_bounds = false; 1099 shadow_val = *shadow_addr; 1100 int bug_type_score = 0; 1101 // For use-after-frees reads are almost as bad as writes. 1102 int read_after_free_bonus = 0; 1103 switch (shadow_val) { 1104 case kAsanHeapLeftRedzoneMagic: 1105 case kAsanHeapRightRedzoneMagic: 1106 case kAsanArrayCookieMagic: 1107 bug_descr = "heap-buffer-overflow"; 1108 bug_type_score = 10; 1109 far_from_bounds = AdjacentShadowValuesAreFullyPoisoned(shadow_addr); 1110 break; 1111 case kAsanHeapFreeMagic: 1112 bug_descr = "heap-use-after-free"; 1113 bug_type_score = 20; 1114 if (!is_write) read_after_free_bonus = 18; 1115 break; 1116 case kAsanStackLeftRedzoneMagic: 1117 bug_descr = "stack-buffer-underflow"; 1118 bug_type_score = 25; 1119 far_from_bounds = AdjacentShadowValuesAreFullyPoisoned(shadow_addr); 1120 break; 1121 case kAsanInitializationOrderMagic: 1122 bug_descr = "initialization-order-fiasco"; 1123 bug_type_score = 1; 1124 break; 1125 case kAsanStackMidRedzoneMagic: 1126 case kAsanStackRightRedzoneMagic: 1127 case kAsanStackPartialRedzoneMagic: 1128 bug_descr = "stack-buffer-overflow"; 1129 bug_type_score = 25; 1130 far_from_bounds = AdjacentShadowValuesAreFullyPoisoned(shadow_addr); 1131 break; 1132 case kAsanStackAfterReturnMagic: 1133 bug_descr = "stack-use-after-return"; 1134 bug_type_score = 30; 1135 if (!is_write) read_after_free_bonus = 18; 1136 break; 1137 case kAsanUserPoisonedMemoryMagic: 1138 bug_descr = "use-after-poison"; 1139 bug_type_score = 20; 1140 break; 1141 case kAsanContiguousContainerOOBMagic: 1142 bug_descr = "container-overflow"; 1143 bug_type_score = 10; 1144 break; 1145 case kAsanStackUseAfterScopeMagic: 1146 bug_descr = "stack-use-after-scope"; 1147 bug_type_score = 10; 1148 break; 1149 case kAsanGlobalRedzoneMagic: 1150 bug_descr = "global-buffer-overflow"; 1151 bug_type_score = 10; 1152 far_from_bounds = AdjacentShadowValuesAreFullyPoisoned(shadow_addr); 1153 break; 1154 case kAsanIntraObjectRedzone: 1155 bug_descr = "intra-object-overflow"; 1156 bug_type_score = 10; 1157 break; 1158 case kAsanAllocaLeftMagic: 1159 case kAsanAllocaRightMagic: 1160 bug_descr = "dynamic-stack-buffer-overflow"; 1161 bug_type_score = 25; 1162 far_from_bounds = AdjacentShadowValuesAreFullyPoisoned(shadow_addr); 1163 break; 1164 } 1165 SS.Scare(bug_type_score + read_after_free_bonus, bug_descr); 1166 if (far_from_bounds) 1167 SS.Scare(10, "far-from-bounds"); 1168 } 1169 1170 ReportData report = { pc, sp, bp, addr, (bool)is_write, access_size, 1171 bug_descr }; 1172 ScopedInErrorReport in_report(&report, fatal); 1173 1174 Decorator d; 1175 Printf("%s", d.Warning()); 1176 Report("ERROR: AddressSanitizer: %s on address " 1177 "%p at pc %p bp %p sp %p\n", 1178 bug_descr, (void*)addr, pc, bp, sp); 1179 Printf("%s", d.EndWarning()); 1180 1181 u32 curr_tid = GetCurrentTidOrInvalid(); 1182 char tname[128]; 1183 Printf("%s%s of size %zu at %p thread T%d%s%s\n", 1184 d.Access(), 1185 access_size ? (is_write ? "WRITE" : "READ") : "ACCESS", 1186 access_size, (void*)addr, curr_tid, 1187 ThreadNameWithParenthesis(curr_tid, tname, sizeof(tname)), 1188 d.EndAccess()); 1189 1190 SS.Print(); 1191 GET_STACK_TRACE_FATAL(pc, bp); 1192 stack.Print(); 1193 1194 DescribeAddress(addr, access_size, bug_descr); 1195 if (shadow_val == kAsanContiguousContainerOOBMagic) 1196 PrintContainerOverflowHint(); 1197 ReportErrorSummary(bug_descr, &stack); 1198 PrintShadowMemoryForAddress(addr); 1199 } 1200 1201 } // namespace __asan 1202 1203 // --------------------------- Interface --------------------- {{{1 1204 using namespace __asan; // NOLINT 1205 1206 void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write, 1207 uptr access_size, u32 exp) { 1208 ENABLE_FRAME_POINTER; 1209 bool fatal = flags()->halt_on_error; 1210 ReportGenericError(pc, bp, sp, addr, is_write, access_size, exp, fatal); 1211 } 1212 1213 void NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) { 1214 BlockingMutexLock l(&error_message_buf_mutex); 1215 error_report_callback = callback; 1216 } 1217 1218 void __asan_describe_address(uptr addr) { 1219 // Thread registry must be locked while we're describing an address. 1220 asanThreadRegistry().Lock(); 1221 DescribeAddress(addr, 1, ""); 1222 asanThreadRegistry().Unlock(); 1223 } 1224 1225 int __asan_report_present() { 1226 return report_happened ? 1 : 0; 1227 } 1228 1229 uptr __asan_get_report_pc() { 1230 return report_data.pc; 1231 } 1232 1233 uptr __asan_get_report_bp() { 1234 return report_data.bp; 1235 } 1236 1237 uptr __asan_get_report_sp() { 1238 return report_data.sp; 1239 } 1240 1241 uptr __asan_get_report_address() { 1242 return report_data.addr; 1243 } 1244 1245 int __asan_get_report_access_type() { 1246 return report_data.is_write ? 1 : 0; 1247 } 1248 1249 uptr __asan_get_report_access_size() { 1250 return report_data.access_size; 1251 } 1252 1253 const char *__asan_get_report_description() { 1254 return report_data.description; 1255 } 1256 1257 extern "C" { 1258 SANITIZER_INTERFACE_ATTRIBUTE 1259 void __sanitizer_ptr_sub(void *a, void *b) { 1260 CheckForInvalidPointerPair(a, b); 1261 } 1262 SANITIZER_INTERFACE_ATTRIBUTE 1263 void __sanitizer_ptr_cmp(void *a, void *b) { 1264 CheckForInvalidPointerPair(a, b); 1265 } 1266 } // extern "C" 1267 1268 #if !SANITIZER_SUPPORTS_WEAK_HOOKS 1269 // Provide default implementation of __asan_on_error that does nothing 1270 // and may be overriden by user. 1271 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE NOINLINE 1272 void __asan_on_error() {} 1273 #endif 1274