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_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