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