asan_report.cc revision def1be9b7ef4091ce465c0fbfb26cdb52128ade8
17354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov//===-- asan_report.cc ----------------------------------------------------===//
27354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov//
37354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov//                     The LLVM Compiler Infrastructure
47354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov//
57354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov// This file is distributed under the University of Illinois Open Source
67354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov// License. See LICENSE.TXT for details.
77354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov//
87354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov//===----------------------------------------------------------------------===//
97354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov//
107354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov// This file is a part of AddressSanitizer, an address sanity checker.
117354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov//
127354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov// This file contains error reporting code.
137354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov//===----------------------------------------------------------------------===//
149873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov#include "asan_flags.h"
157354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov#include "asan_internal.h"
16e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov#include "asan_mapping.h"
177354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov#include "asan_report.h"
187354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov#include "asan_stack.h"
19e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov#include "asan_thread.h"
2058f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany#include "sanitizer_common/sanitizer_common.h"
2158f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany#include "sanitizer_common/sanitizer_report_decorator.h"
229c92748b8fa3b833924138a6ae1e653972c9de3bAlexey Samsonov#include "sanitizer_common/sanitizer_symbolizer.h"
237354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov
247354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonovnamespace __asan {
257354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov
26f657a1977b6053c76ca8393f574da7593ea3ea12Alexey Samsonov// -------------------- User-specified callbacks ----------------- {{{1
27c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonovstatic void (*error_report_callback)(const char*);
28c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonovstatic char *error_message_buffer = 0;
29c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonovstatic uptr error_message_buffer_pos = 0;
30c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonovstatic uptr error_message_buffer_size = 0;
31c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov
32c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonovvoid AppendToErrorMessageBuffer(const char *buffer) {
33c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov  if (error_message_buffer) {
34c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    uptr length = internal_strlen(buffer);
35c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    CHECK_GE(error_message_buffer_size, error_message_buffer_pos);
36c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    uptr remaining = error_message_buffer_size - error_message_buffer_pos;
37c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    internal_strncpy(error_message_buffer + error_message_buffer_pos,
38c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov                     buffer, remaining);
39c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    error_message_buffer[error_message_buffer_size - 1] = '\0';
40c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    // FIXME: reallocate the buffer instead of truncating the message.
41c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    error_message_buffer_pos += remaining > length ? length : remaining;
42c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov  }
43c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov}
44c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov
4558f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany// ---------------------- Decorator ------------------------------ {{{1
469514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryanybool PrintsToTtyCached() {
479514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  static int cached = 0;
489514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  static bool prints_to_tty;
499514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  if (!cached) {  // Ok wrt threads since we are printing only from one thread.
509514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany    prints_to_tty = PrintsToTty();
519514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany    cached = 1;
529514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  }
539514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  return prints_to_tty;
549514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany}
5558f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryanyclass Decorator: private __sanitizer::AnsiColorDecorator {
5658f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany public:
579514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  Decorator() : __sanitizer::AnsiColorDecorator(PrintsToTtyCached()) { }
5858f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  const char *Warning()    { return Red(); }
5958f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  const char *EndWarning() { return Default(); }
6058f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  const char *Access()     { return Blue(); }
6158f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  const char *EndAccess()  { return Default(); }
6258f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  const char *Location()   { return Green(); }
6358f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  const char *EndLocation() { return Default(); }
6458f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  const char *Allocation()  { return Magenta(); }
6558f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  const char *EndAllocation()  { return Default(); }
669514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany
679514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  const char *ShadowByte(u8 byte) {
689514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany    switch (byte) {
699514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany      case kAsanHeapLeftRedzoneMagic:
709514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany      case kAsanHeapRightRedzoneMagic:
719514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany        return Red();
729514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany      case kAsanHeapFreeMagic:
739514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany        return Magenta();
749514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany      case kAsanStackLeftRedzoneMagic:
759514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany      case kAsanStackMidRedzoneMagic:
769514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany      case kAsanStackRightRedzoneMagic:
779514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany      case kAsanStackPartialRedzoneMagic:
789514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany        return Red();
799514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany      case kAsanStackAfterReturnMagic:
809514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany        return Magenta();
819514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany      case kAsanInitializationOrderMagic:
829514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany        return Cyan();
839514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany      case kAsanUserPoisonedMemoryMagic:
849514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany        return Blue();
859514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany      case kAsanStackUseAfterScopeMagic:
869514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany        return Magenta();
879514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany      case kAsanGlobalRedzoneMagic:
889514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany        return Red();
899514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany      case kAsanInternalHeapMagic:
909514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany        return Yellow();
919514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany      default:
929514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany        return Default();
939514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany    }
949514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  }
959514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  const char *EndShadowByte() { return Default(); }
9658f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany};
9758f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany
989873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov// ---------------------- Helper functions ----------------------- {{{1
999873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov
1009514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryanystatic void PrintShadowByte(const char *before, u8 byte,
1019514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany                            const char *after = "\n") {
1029514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  Decorator d;
1039514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  Printf("%s%s%x%x%s%s", before,
1049514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany         d.ShadowByte(byte), byte >> 4, byte & 15, d.EndShadowByte(), after);
1059514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany}
1069514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany
1079514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryanystatic void PrintShadowBytes(const char *before, u8 *bytes,
1089514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany                             u8 *guilty, uptr n) {
1099514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  Decorator d;
1109514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  if (before)
1119514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany    Printf("%s%p:", before, bytes);
1129514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  for (uptr i = 0; i < n; i++) {
1139514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany    u8 *p = bytes + i;
1149514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany    const char *before = p == guilty ? "[" :
1159514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany        p - 1 == guilty ? "" : " ";
1169514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany    const char *after = p == guilty ? "]" : "";
1179514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany    PrintShadowByte(before, *p, after);
1189873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  }
119283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Printf("\n");
1209873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov}
1219873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov
12295f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryanystatic void PrintLegend() {
1239514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  Printf("Shadow byte legend (one shadow byte represents %d "
1249514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany         "application bytes):\n", (int)SHADOW_GRANULARITY);
1259514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  PrintShadowByte("  Addressable:           ", 0);
1269514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  Printf("  Partially addressable: ");
1279514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  for (uptr i = 1; i < SHADOW_GRANULARITY; i++)
1289514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany    PrintShadowByte("", i, " ");
1299514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  Printf("\n");
1309514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  PrintShadowByte("  Heap left redzone:     ", kAsanHeapLeftRedzoneMagic);
1319514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  PrintShadowByte("  Heap righ redzone:     ", kAsanHeapRightRedzoneMagic);
1329514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  PrintShadowByte("  Freed Heap region:     ", kAsanHeapFreeMagic);
1339514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  PrintShadowByte("  Stack left redzone:    ", kAsanStackLeftRedzoneMagic);
1349514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  PrintShadowByte("  Stack mid redzone:     ", kAsanStackMidRedzoneMagic);
1359514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  PrintShadowByte("  Stack right redzone:   ", kAsanStackRightRedzoneMagic);
1369514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  PrintShadowByte("  Stack partial redzone: ", kAsanStackPartialRedzoneMagic);
1379514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  PrintShadowByte("  Stack after return:    ", kAsanStackAfterReturnMagic);
1389514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  PrintShadowByte("  Stack use after scope: ", kAsanStackUseAfterScopeMagic);
1399514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  PrintShadowByte("  Global redzone:        ", kAsanGlobalRedzoneMagic);
1409514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  PrintShadowByte("  Global init order:     ", kAsanInitializationOrderMagic);
1419514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  PrintShadowByte("  Poisoned by user:      ", kAsanUserPoisonedMemoryMagic);
1429514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  PrintShadowByte("  ASan internal:         ", kAsanInternalHeapMagic);
1439873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov}
1449873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov
14595f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryanystatic void PrintShadowMemoryForAddress(uptr addr) {
14695f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryany  if (!AddrIsInMem(addr))
14795f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryany    return;
14895f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryany  uptr shadow_addr = MemToShadow(addr);
14995f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryany  const uptr n_bytes_per_row = 16;
15095f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryany  uptr aligned_shadow = shadow_addr & ~(n_bytes_per_row - 1);
15195f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryany  Printf("Shadow bytes around the buggy address:\n");
15295f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryany  for (int i = -5; i <= 5; i++) {
15395f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryany    const char *prefix = (i == 0) ? "=>" : "  ";
15495f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryany    PrintShadowBytes(prefix,
15595f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryany                     (u8*)(aligned_shadow + i * n_bytes_per_row),
15695f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryany                     (u8*)shadow_addr, n_bytes_per_row);
15795f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryany  }
15895f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryany  if (flags()->print_legend)
15995f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryany    PrintLegend();
16095f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryany}
16195f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryany
1629873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonovstatic void PrintZoneForPointer(uptr ptr, uptr zone_ptr,
1639873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov                                const char *zone_name) {
1649873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  if (zone_ptr) {
1659873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    if (zone_name) {
166283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany      Printf("malloc_zone_from_ptr(%p) = %p, which is %s\n",
1679873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov                 ptr, zone_ptr, zone_name);
1689873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    } else {
169283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany      Printf("malloc_zone_from_ptr(%p) = %p, which doesn't have a name\n",
1709873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov                 ptr, zone_ptr);
1719873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    }
1729873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  } else {
173283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany    Printf("malloc_zone_from_ptr(%p) = 0\n", ptr);
1749873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  }
1759873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov}
1769873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov
177e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov// ---------------------- Address Descriptions ------------------- {{{1
178e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov
179e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonovstatic bool IsASCII(unsigned char c) {
1809873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  return /*0x00 <= c &&*/ c <= 0x7F;
181e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov}
182e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov
183e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov// Check if the global is a zero-terminated ASCII string. If so, print it.
184e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonovstatic void PrintGlobalNameIfASCII(const __asan_global &g) {
185e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov  for (uptr p = g.beg; p < g.beg + g.size - 1; p++) {
186e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov    if (!IsASCII(*(unsigned char*)p)) return;
187e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov  }
188e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov  if (*(char*)(g.beg + g.size - 1) != 0) return;
189283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Printf("  '%s' is ascii string '%s'\n", g.name, (char*)g.beg);
190e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov}
191e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov
192589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanovbool DescribeAddressRelativeToGlobal(uptr addr, uptr size,
193589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov                                     const __asan_global &g) {
194a3b0e5e4f9f48b2ed0baee10c0236eda7c21c660Kostya Serebryany  static const uptr kMinimalDistanceFromAnotherGlobal = 64;
195a3b0e5e4f9f48b2ed0baee10c0236eda7c21c660Kostya Serebryany  if (addr <= g.beg - kMinimalDistanceFromAnotherGlobal) return false;
196e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov  if (addr >= g.beg + g.size_with_redzone) return false;
19758f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Decorator d;
19858f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.Location());
199e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov  if (addr < g.beg) {
200589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov    Printf("%p is located %zd bytes to the left", (void*)addr, g.beg - addr);
201589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov  } else if (addr + size > g.beg + g.size) {
202589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov    if (addr < g.beg + g.size)
203589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov      addr = g.beg + g.size;
204589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov    Printf("%p is located %zd bytes to the right", (void*)addr,
205589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov           addr - (g.beg + g.size));
206e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov  } else {
207589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov    // Can it happen?
208589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov    Printf("%p is located %zd bytes inside", (void*)addr, addr - g.beg);
209e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov  }
21060c9f441255211f17c4d355ead94392ba1841355Kostya Serebryany  Printf(" of global variable '%s' from '%s' (0x%zx) of size %zu\n",
21160c9f441255211f17c4d355ead94392ba1841355Kostya Serebryany             g.name, g.module_name, g.beg, g.size);
21258f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.EndLocation());
213e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov  PrintGlobalNameIfASCII(g);
214e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov  return true;
215e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov}
216e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov
217e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonovbool DescribeAddressIfShadow(uptr addr) {
218e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  if (AddrIsInMem(addr))
219e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    return false;
220e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  static const char kAddrInShadowReport[] =
221e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov      "Address %p is located in the %s.\n";
222e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  if (AddrIsInShadowGap(addr)) {
223283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany    Printf(kAddrInShadowReport, addr, "shadow gap area");
224e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    return true;
225e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  }
226e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  if (AddrIsInHighShadow(addr)) {
227283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany    Printf(kAddrInShadowReport, addr, "high shadow area");
228e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    return true;
229e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  }
230e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  if (AddrIsInLowShadow(addr)) {
231283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany    Printf(kAddrInShadowReport, addr, "low shadow area");
232e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    return true;
233e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  }
234e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  CHECK(0 && "Address is not in memory and not in shadow?");
235e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  return false;
236e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov}
237e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov
238e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonovbool DescribeAddressIfStack(uptr addr, uptr access_size) {
239def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  AsanThread *t = FindThreadByStackAddress(addr);
240e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  if (!t) return false;
241e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  const sptr kBufSize = 4095;
242e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  char buf[kBufSize];
243e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  uptr offset = 0;
244e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  const char *frame_descr = t->GetFrameNameByAddr(addr, &offset);
245e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  // This string is created by the compiler and has the following form:
246e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  // "FunctioName n alloc_1 alloc_2 ... alloc_n"
247e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  // where alloc_i looks like "offset size len ObjectName ".
248e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  CHECK(frame_descr);
249e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  // Report the function name and the offset.
250e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  const char *name_end = internal_strchr(frame_descr, ' ');
251e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  CHECK(name_end);
252e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  buf[0] = 0;
253e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  internal_strncat(buf, frame_descr,
254e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov                   Min(kBufSize,
255e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov                       static_cast<sptr>(name_end - frame_descr)));
25658f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Decorator d;
25758f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.Location());
258283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Printf("Address %p is located at offset %zu "
259e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov             "in frame <%s> of T%d's stack:\n",
2609c92748b8fa3b833924138a6ae1e653972c9de3bAlexey Samsonov             (void*)addr, offset, Demangle(buf), t->tid());
26158f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.EndLocation());
262e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  // Report the number of stack objects.
263e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  char *p;
264e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  uptr n_objects = internal_simple_strtoll(name_end, &p, 10);
265e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  CHECK(n_objects > 0);
266283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Printf("  This frame has %zu object(s):\n", n_objects);
267e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  // Report all objects in this frame.
268e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  for (uptr i = 0; i < n_objects; i++) {
269e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    uptr beg, size;
270e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    sptr len;
271e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    beg  = internal_simple_strtoll(p, &p, 10);
272e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    size = internal_simple_strtoll(p, &p, 10);
273e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    len  = internal_simple_strtoll(p, &p, 10);
274e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    if (beg <= 0 || size <= 0 || len < 0 || *p != ' ') {
275283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany      Printf("AddressSanitizer can't parse the stack frame "
276e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov                 "descriptor: |%s|\n", frame_descr);
277e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov      break;
278e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    }
279e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    p++;
280e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    buf[0] = 0;
281e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    internal_strncat(buf, p, Min(kBufSize, len));
282e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    p += len;
283283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany    Printf("    [%zu, %zu) '%s'\n", beg, beg + size, buf);
284e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  }
285283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Printf("HINT: this may be a false positive if your program uses "
2860870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov             "some custom stack unwind mechanism or swapcontext\n"
287e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov             "      (longjmp and C++ exceptions *are* supported)\n");
288def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  DescribeThread(t->context());
289e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  return true;
290e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov}
291e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov
2925c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonovstatic void DescribeAccessToHeapChunk(AsanChunkView chunk, uptr addr,
2935c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov                                      uptr access_size) {
294589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov  sptr offset;
29558f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Decorator d;
29658f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.Location());
297589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov  if (chunk.AddrIsAtLeft(addr, access_size, &offset)) {
298589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov    Printf("%p is located %zd bytes to the left of", (void*)addr, offset);
2995c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov  } else if (chunk.AddrIsAtRight(addr, access_size, &offset)) {
300589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov    if (offset < 0) {
301589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov      addr -= offset;
302589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov      offset = 0;
303589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov    }
304589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov    Printf("%p is located %zd bytes to the right of", (void*)addr, offset);
305589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov  } else if (chunk.AddrIsInside(addr, access_size, &offset)) {
306589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov    Printf("%p is located %zd bytes inside of", (void*)addr, offset);
3075c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov  } else {
308589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov    Printf("%p is located somewhere around (this is AddressSanitizer bug!)",
309589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov           (void*)addr);
3105c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov  }
3115c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov  Printf(" %zu-byte region [%p,%p)\n", chunk.UsedSize(),
3125c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov         (void*)(chunk.Beg()), (void*)(chunk.End()));
31358f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.EndLocation());
3145c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov}
3155c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov
316716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany// Return " (thread_name) " or an empty string if the name is empty.
317def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonovconst char *ThreadNameWithParenthesis(AsanThreadContext *t, char buff[],
318716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany                                      uptr buff_len) {
319def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  const char *name = t->name;
320def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  if (name[0] == '\0') return "";
321716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany  buff[0] = 0;
322716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany  internal_strncat(buff, " (", 3);
323716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany  internal_strncat(buff, name, buff_len - 4);
324716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany  internal_strncat(buff, ")", 2);
325716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany  return buff;
326716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany}
327716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany
328716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryanyconst char *ThreadNameWithParenthesis(u32 tid, char buff[],
329716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany                                      uptr buff_len) {
330716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany  if (tid == kInvalidTid) return "";
331def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  asanThreadRegistry().CheckLocked();
332def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  AsanThreadContext *t = GetThreadContextByTidLocked(tid);
333716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany  return ThreadNameWithParenthesis(t, buff, buff_len);
334716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany}
335716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany
3365c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonovvoid DescribeHeapAddress(uptr addr, uptr access_size) {
3375c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov  AsanChunkView chunk = FindHeapChunkByAddress(addr);
3385c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov  if (!chunk.IsValid()) return;
3395c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov  DescribeAccessToHeapChunk(chunk, addr, access_size);
3405c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov  CHECK(chunk.AllocTid() != kInvalidTid);
341def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  asanThreadRegistry().CheckLocked();
342def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  AsanThreadContext *alloc_thread =
343def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov      GetThreadContextByTidLocked(chunk.AllocTid());
3445c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov  StackTrace alloc_stack;
3455c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov  chunk.GetAllocStack(&alloc_stack);
34689c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov  AsanThread *t = GetCurrentThread();
3475c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov  CHECK(t);
348716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany  char tname[128];
34958f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Decorator d;
3505c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov  if (chunk.FreeTid() != kInvalidTid) {
351def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov    AsanThreadContext *free_thread =
352def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov        GetThreadContextByTidLocked(chunk.FreeTid());
35358f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany    Printf("%sfreed by thread T%d%s here:%s\n", d.Allocation(),
354def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov           free_thread->tid,
35558f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany           ThreadNameWithParenthesis(free_thread, tname, sizeof(tname)),
35658f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany           d.EndAllocation());
3575c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov    StackTrace free_stack;
3585c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov    chunk.GetFreeStack(&free_stack);
3595c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov    PrintStack(&free_stack);
36058f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany    Printf("%spreviously allocated by thread T%d%s here:%s\n",
361def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov           d.Allocation(), alloc_thread->tid,
36258f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany           ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)),
36358f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany           d.EndAllocation());
3645c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov    PrintStack(&alloc_stack);
365def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov    DescribeThread(t->context());
3665c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov    DescribeThread(free_thread);
3675c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov    DescribeThread(alloc_thread);
3685c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov  } else {
36958f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany    Printf("%sallocated by thread T%d%s here:%s\n", d.Allocation(),
370def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov           alloc_thread->tid,
37158f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany           ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)),
37258f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany           d.EndAllocation());
3735c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov    PrintStack(&alloc_stack);
374def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov    DescribeThread(t->context());
3755c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov    DescribeThread(alloc_thread);
3765c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov  }
3775c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov}
3785c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov
379e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonovvoid DescribeAddress(uptr addr, uptr access_size) {
380e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  // Check if this is shadow or shadow gap.
381e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  if (DescribeAddressIfShadow(addr))
382e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    return;
383e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  CHECK(AddrIsInMem(addr));
384589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov  if (DescribeAddressIfGlobal(addr, access_size))
385e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    return;
386e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  if (DescribeAddressIfStack(addr, access_size))
387e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    return;
388e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  // Assume it is a heap address.
389e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  DescribeHeapAddress(addr, access_size);
390e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov}
391e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov
39271b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov// ------------------- Thread description -------------------- {{{1
39371b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov
394def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonovvoid DescribeThread(AsanThreadContext *context) {
395def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  CHECK(context);
396def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  asanThreadRegistry().CheckLocked();
39771b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov  // No need to announce the main thread.
398def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  if (context->tid == 0 || context->announced) {
39971b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov    return;
40071b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov  }
401def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  context->announced = true;
402716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany  char tname[128];
403def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  Printf("Thread T%d%s", context->tid,
404def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov         ThreadNameWithParenthesis(context->tid, tname, sizeof(tname)));
405716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany  Printf(" created by T%d%s here:\n",
406def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov         context->parent_tid,
407def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov         ThreadNameWithParenthesis(context->parent_tid,
408716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany                                   tname, sizeof(tname)));
409def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  PrintStack(&context->stack);
41071b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov  // Recursively described parent thread if needed.
41171b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov  if (flags()->print_full_thread_history) {
412def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov    AsanThreadContext *parent_context =
413def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov        GetThreadContextByTidLocked(context->parent_tid);
414def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov    DescribeThread(parent_context);
41571b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov  }
41671b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov}
41771b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov
418e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov// -------------------- Different kinds of reports ----------------- {{{1
419e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov
4209873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov// Use ScopedInErrorReport to run common actions just before and
4219873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov// immediately after printing error report.
4229873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonovclass ScopedInErrorReport {
4239873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov public:
4249873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  ScopedInErrorReport() {
4259873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    static atomic_uint32_t num_calls;
42662e27098b97e5ef74931c536350123a3df9dec6dAlexey Samsonov    static u32 reporting_thread_tid;
4279873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) {
4289873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov      // Do not print more than one report, otherwise they will mix up.
4299873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov      // Error reporting functions shouldn't return at this situation, as
4309873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov      // they are defined as no-return.
431283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany      Report("AddressSanitizer: while reporting a bug found another one."
4329873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov                 "Ignoring.\n");
43389c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov      u32 current_tid = GetCurrentTidOrInvalid();
43462e27098b97e5ef74931c536350123a3df9dec6dAlexey Samsonov      if (current_tid != reporting_thread_tid) {
43562e27098b97e5ef74931c536350123a3df9dec6dAlexey Samsonov        // ASan found two bugs in different threads simultaneously. Sleep
43662e27098b97e5ef74931c536350123a3df9dec6dAlexey Samsonov        // long enough to make sure that the thread which started to print
43762e27098b97e5ef74931c536350123a3df9dec6dAlexey Samsonov        // an error report will finish doing it.
43862e27098b97e5ef74931c536350123a3df9dec6dAlexey Samsonov        SleepForSeconds(Max(100, flags()->sleep_before_dying + 1));
43962e27098b97e5ef74931c536350123a3df9dec6dAlexey Samsonov      }
440f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov      // If we're still not dead for some reason, use raw _exit() instead of
441031633bef8dff03f4e8943a12e34856bd66bbc78Alexey Samsonov      // Die() to bypass any additional checks.
442f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov      internal__exit(flags()->exitcode);
4439873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    }
4446a08d29b2020004b801ca69d8aea5872a7e67d72Alexey Samsonov    ASAN_ON_ERROR();
445def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov    // Make sure the registry is locked while we're printing an error report.
446def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov    // We can lock the registry only here to avoid self-deadlock in case of
447def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov    // recursive reports.
448def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov    asanThreadRegistry().Lock();
44989c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov    reporting_thread_tid = GetCurrentTidOrInvalid();
450283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany    Printf("===================================================="
45162e27098b97e5ef74931c536350123a3df9dec6dAlexey Samsonov           "=============\n");
45262e27098b97e5ef74931c536350123a3df9dec6dAlexey Samsonov    if (reporting_thread_tid != kInvalidTid) {
4539873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov      // We started reporting an error message. Stop using the fake stack
4549873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov      // in case we call an instrumented function from a symbolizer.
45589c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov      AsanThread *curr_thread = GetCurrentThread();
45662e27098b97e5ef74931c536350123a3df9dec6dAlexey Samsonov      CHECK(curr_thread);
4579873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov      curr_thread->fake_stack().StopUsingFakeStack();
4589873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    }
4599873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  }
4609873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  // Destructor is NORETURN, as functions that report errors are.
4619873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  NORETURN ~ScopedInErrorReport() {
4629873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    // Make sure the current thread is announced.
46389c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov    AsanThread *curr_thread = GetCurrentThread();
4649873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    if (curr_thread) {
465def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov      DescribeThread(curr_thread->context());
4669873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    }
4679873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    // Print memory stats.
46895f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryany    if (flags()->print_stats)
46995f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryany      __asan_print_accumulated_stats();
4709873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    if (error_report_callback) {
4719873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov      error_report_callback(error_message_buffer);
4729873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    }
473283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany    Report("ABORTING\n");
4749873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    Die();
4759873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  }
4769873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov};
4779873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov
4782673fd8406197c42f16cede6d287f72169298c2eKostya Serebryanystatic void ReportSummary(const char *error_type, StackTrace *stack) {
4792673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany  if (!stack->size) return;
4802673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany  if (IsSymbolizerAvailable()) {
4812673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany    AddressInfo ai;
4822673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany    // Currently, we include the first stack frame into the report summary.
4832673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany    // Maybe sometimes we need to choose another frame (e.g. skip memcpy/etc).
4842673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany    SymbolizeCode(stack->trace[0], &ai, 1);
4852673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany    ReportErrorSummary(error_type,
4862673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany                       StripPathPrefix(ai.file, flags()->strip_path_prefix),
4872673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany                       ai.line, ai.function);
4882673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany  }
4892673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany  // FIXME: do we need to print anything at all if there is no symbolizer?
4902673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany}
4912673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany
4927354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonovvoid ReportSIGSEGV(uptr pc, uptr sp, uptr bp, uptr addr) {
4939873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  ScopedInErrorReport in_report;
49458f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Decorator d;
49558f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.Warning());
49669d8ede30a0ef32c74af7e4e795eb4b4e7fb1d36Kostya Serebryany  Report("ERROR: AddressSanitizer: SEGV on unknown address %p"
4977354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov             " (pc %p sp %p bp %p T%d)\n",
4987354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov             (void*)addr, (void*)pc, (void*)sp, (void*)bp,
49989c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov             GetCurrentTidOrInvalid());
50058f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.EndWarning());
501283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Printf("AddressSanitizer can not provide additional info.\n");
502a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  GET_STACK_TRACE_FATAL(pc, bp);
503cc347222d55967fdb775429a8a0a3a5d795b8b50Kostya Serebryany  PrintStack(&stack);
5042673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany  ReportSummary("SEGV", &stack);
5057354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov}
5067354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov
507c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryanyvoid ReportDoubleFree(uptr addr, StackTrace *stack) {
5089873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  ScopedInErrorReport in_report;
50958f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Decorator d;
51058f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.Warning());
51169d8ede30a0ef32c74af7e4e795eb4b4e7fb1d36Kostya Serebryany  Report("ERROR: AddressSanitizer: attempting double-free on %p:\n", addr);
51258f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.EndWarning());
513cc347222d55967fdb775429a8a0a3a5d795b8b50Kostya Serebryany  PrintStack(stack);
514f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov  DescribeHeapAddress(addr, 1);
5152673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany  ReportSummary("double-free", stack);
516f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov}
517f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov
518c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryanyvoid ReportFreeNotMalloced(uptr addr, StackTrace *stack) {
5199873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  ScopedInErrorReport in_report;
52058f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Decorator d;
52158f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.Warning());
52269d8ede30a0ef32c74af7e4e795eb4b4e7fb1d36Kostya Serebryany  Report("ERROR: AddressSanitizer: attempting free on address "
523f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov             "which was not malloc()-ed: %p\n", addr);
52458f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.EndWarning());
525cc347222d55967fdb775429a8a0a3a5d795b8b50Kostya Serebryany  PrintStack(stack);
5269873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  DescribeHeapAddress(addr, 1);
5272673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany  ReportSummary("bad-free", stack);
528f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov}
529f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov
530fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryanyvoid ReportAllocTypeMismatch(uptr addr, StackTrace *stack,
531fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany                             AllocType alloc_type,
532fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany                             AllocType dealloc_type) {
533fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany  static const char *alloc_names[] =
534fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany    {"INVALID", "malloc", "operator new", "operator new []"};
535fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany  static const char *dealloc_names[] =
536fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany    {"INVALID", "free", "operator delete", "operator delete []"};
537fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany  CHECK_NE(alloc_type, dealloc_type);
538fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany  ScopedInErrorReport in_report;
539fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany  Decorator d;
540fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany  Printf("%s", d.Warning());
541fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany  Report("ERROR: AddressSanitizer: alloc-dealloc-mismatch (%s vs %s) on %p\n",
542fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany        alloc_names[alloc_type], dealloc_names[dealloc_type], addr);
543fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany  Printf("%s", d.EndWarning());
544fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany  PrintStack(stack);
545fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany  DescribeHeapAddress(addr, 1);
5462673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany  ReportSummary("alloc-dealloc-mismatch", stack);
547fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany  Report("HINT: if you don't care about these warnings you may set "
548fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany         "ASAN_OPTIONS=alloc_dealloc_mismatch=0\n");
549fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany}
550fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany
551c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryanyvoid ReportMallocUsableSizeNotOwned(uptr addr, StackTrace *stack) {
5529873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  ScopedInErrorReport in_report;
55358f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Decorator d;
55458f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.Warning());
55569d8ede30a0ef32c74af7e4e795eb4b4e7fb1d36Kostya Serebryany  Report("ERROR: AddressSanitizer: attempting to call "
556f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov             "malloc_usable_size() for pointer which is "
557f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov             "not owned: %p\n", addr);
55858f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.EndWarning());
559cc347222d55967fdb775429a8a0a3a5d795b8b50Kostya Serebryany  PrintStack(stack);
560f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov  DescribeHeapAddress(addr, 1);
5612673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany  ReportSummary("bad-malloc_usable_size", stack);
562f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov}
563f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov
564c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryanyvoid ReportAsanGetAllocatedSizeNotOwned(uptr addr, StackTrace *stack) {
5659873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  ScopedInErrorReport in_report;
56658f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Decorator d;
56758f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.Warning());
56869d8ede30a0ef32c74af7e4e795eb4b4e7fb1d36Kostya Serebryany  Report("ERROR: AddressSanitizer: attempting to call "
569f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov             "__asan_get_allocated_size() for pointer which is "
570f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov             "not owned: %p\n", addr);
57158f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.EndWarning());
572cc347222d55967fdb775429a8a0a3a5d795b8b50Kostya Serebryany  PrintStack(stack);
573f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov  DescribeHeapAddress(addr, 1);
5742673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany  ReportSummary("bad-__asan_get_allocated_size", stack);
575f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov}
576f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov
577487fee7f6f7497906a00d7d2fe2c75e6d5d4feb1Alexey Samsonovvoid ReportStringFunctionMemoryRangesOverlap(
578487fee7f6f7497906a00d7d2fe2c75e6d5d4feb1Alexey Samsonov    const char *function, const char *offset1, uptr length1,
579c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryany    const char *offset2, uptr length2, StackTrace *stack) {
5809873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  ScopedInErrorReport in_report;
58158f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Decorator d;
5822673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany  char bug_type[100];
5832673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany  internal_snprintf(bug_type, sizeof(bug_type), "%s-param-overlap", function);
58458f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.Warning());
5852673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany  Report("ERROR: AddressSanitizer: %s: "
586487fee7f6f7497906a00d7d2fe2c75e6d5d4feb1Alexey Samsonov             "memory ranges [%p,%p) and [%p, %p) overlap\n", \
5872673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany             bug_type, offset1, offset1 + length1, offset2, offset2 + length2);
58858f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.EndWarning());
589cc347222d55967fdb775429a8a0a3a5d795b8b50Kostya Serebryany  PrintStack(stack);
5909873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  DescribeAddress((uptr)offset1, length1);
5919873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  DescribeAddress((uptr)offset2, length2);
5922673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany  ReportSummary(bug_type, stack);
593487fee7f6f7497906a00d7d2fe2c75e6d5d4feb1Alexey Samsonov}
594f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov
595663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov// ----------------------- Mac-specific reports ----------------- {{{1
596663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov
597663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonovvoid WarnMacFreeUnallocated(
598c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryany    uptr addr, uptr zone_ptr, const char *zone_name, StackTrace *stack) {
5999873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  // Just print a warning here.
600283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Printf("free_common(%p) -- attempting to free unallocated memory.\n"
601663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov             "AddressSanitizer is ignoring this error on Mac OS now.\n",
602663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov             addr);
603663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov  PrintZoneForPointer(addr, zone_ptr, zone_name);
604cc347222d55967fdb775429a8a0a3a5d795b8b50Kostya Serebryany  PrintStack(stack);
6059873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  DescribeHeapAddress(addr, 1);
606663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov}
607663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov
608663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonovvoid ReportMacMzReallocUnknown(
609c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryany    uptr addr, uptr zone_ptr, const char *zone_name, StackTrace *stack) {
6109873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  ScopedInErrorReport in_report;
611283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Printf("mz_realloc(%p) -- attempting to realloc unallocated memory.\n"
612663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov             "This is an unrecoverable problem, exiting now.\n",
613663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov             addr);
614663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov  PrintZoneForPointer(addr, zone_ptr, zone_name);
615cc347222d55967fdb775429a8a0a3a5d795b8b50Kostya Serebryany  PrintStack(stack);
6169873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  DescribeHeapAddress(addr, 1);
617663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov}
618663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov
619663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonovvoid ReportMacCfReallocUnknown(
620c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryany    uptr addr, uptr zone_ptr, const char *zone_name, StackTrace *stack) {
6219873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  ScopedInErrorReport in_report;
622283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Printf("cf_realloc(%p) -- attempting to realloc unallocated memory.\n"
623663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov             "This is an unrecoverable problem, exiting now.\n",
624663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov             addr);
625663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov  PrintZoneForPointer(addr, zone_ptr, zone_name);
626cc347222d55967fdb775429a8a0a3a5d795b8b50Kostya Serebryany  PrintStack(stack);
6279873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  DescribeHeapAddress(addr, 1);
628c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov}
629c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov
630812ff90eaad0e4555554ffb81db0e611ec434e10Alexey Samsonov}  // namespace __asan
631812ff90eaad0e4555554ffb81db0e611ec434e10Alexey Samsonov
632812ff90eaad0e4555554ffb81db0e611ec434e10Alexey Samsonov// --------------------------- Interface --------------------- {{{1
633812ff90eaad0e4555554ffb81db0e611ec434e10Alexey Samsonovusing namespace __asan;  // NOLINT
634812ff90eaad0e4555554ffb81db0e611ec434e10Alexey Samsonov
635812ff90eaad0e4555554ffb81db0e611ec434e10Alexey Samsonovvoid __asan_report_error(uptr pc, uptr bp, uptr sp,
636812ff90eaad0e4555554ffb81db0e611ec434e10Alexey Samsonov                         uptr addr, bool is_write, uptr access_size) {
6379873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  ScopedInErrorReport in_report;
638c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov
6399873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  // Determine the error type.
640c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov  const char *bug_descr = "unknown-crash";
641c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov  if (AddrIsInMem(addr)) {
642c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    u8 *shadow_addr = (u8*)MemToShadow(addr);
643c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    // If we are accessing 16 bytes, look at the second shadow byte.
644c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    if (*shadow_addr == 0 && access_size > SHADOW_GRANULARITY)
645c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov      shadow_addr++;
646c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    // If we are in the partial right redzone, look at the next shadow byte.
647c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    if (*shadow_addr > 0 && *shadow_addr < 128)
648c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov      shadow_addr++;
649c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    switch (*shadow_addr) {
650c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov      case kAsanHeapLeftRedzoneMagic:
651c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov      case kAsanHeapRightRedzoneMagic:
652c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        bug_descr = "heap-buffer-overflow";
653c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        break;
654c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov      case kAsanHeapFreeMagic:
655c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        bug_descr = "heap-use-after-free";
656c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        break;
657c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov      case kAsanStackLeftRedzoneMagic:
658c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        bug_descr = "stack-buffer-underflow";
659c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        break;
6603945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany      case kAsanInitializationOrderMagic:
6613945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany        bug_descr = "initialization-order-fiasco";
6623945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany        break;
663c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov      case kAsanStackMidRedzoneMagic:
664c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov      case kAsanStackRightRedzoneMagic:
665c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov      case kAsanStackPartialRedzoneMagic:
666c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        bug_descr = "stack-buffer-overflow";
667c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        break;
668c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov      case kAsanStackAfterReturnMagic:
669c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        bug_descr = "stack-use-after-return";
670c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        break;
671c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov      case kAsanUserPoisonedMemoryMagic:
672c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        bug_descr = "use-after-poison";
673c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        break;
674d4b5db8cb8a7a13bb5cc1d4ce53e8e088303c854Alexey Samsonov      case kAsanStackUseAfterScopeMagic:
675d4b5db8cb8a7a13bb5cc1d4ce53e8e088303c854Alexey Samsonov        bug_descr = "stack-use-after-scope";
676d4b5db8cb8a7a13bb5cc1d4ce53e8e088303c854Alexey Samsonov        break;
677c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov      case kAsanGlobalRedzoneMagic:
678c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        bug_descr = "global-buffer-overflow";
679c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        break;
680c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    }
681c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov  }
68258f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Decorator d;
68358f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.Warning());
68469d8ede30a0ef32c74af7e4e795eb4b4e7fb1d36Kostya Serebryany  Report("ERROR: AddressSanitizer: %s on address "
685c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov             "%p at pc 0x%zx bp 0x%zx sp 0x%zx\n",
686c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov             bug_descr, (void*)addr, pc, bp, sp);
68758f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.EndWarning());
688c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov
68989c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov  u32 curr_tid = GetCurrentTidOrInvalid();
690716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany  char tname[128];
69158f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s%s of size %zu at %p thread T%d%s%s\n",
69258f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany         d.Access(),
69358f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany         access_size ? (is_write ? "WRITE" : "READ") : "ACCESS",
69458f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany         access_size, (void*)addr, curr_tid,
69558f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany         ThreadNameWithParenthesis(curr_tid, tname, sizeof(tname)),
69658f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany         d.EndAccess());
697c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov
698a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  GET_STACK_TRACE_FATAL(pc, bp);
699cc347222d55967fdb775429a8a0a3a5d795b8b50Kostya Serebryany  PrintStack(&stack);
700c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov
701c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov  DescribeAddress(addr, access_size);
7022673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany  ReportSummary(bug_descr, &stack);
7039873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  PrintShadowMemoryForAddress(addr);
704c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov}
705c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov
706c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonovvoid NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) {
707c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov  error_report_callback = callback;
708c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov  if (callback) {
709c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    error_message_buffer_size = 1 << 16;
710c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    error_message_buffer =
711c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        (char*)MmapOrDie(error_message_buffer_size, __FUNCTION__);
712c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    error_message_buffer_pos = 0;
713c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov  }
714c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov}
715f657a1977b6053c76ca8393f574da7593ea3ea12Alexey Samsonov
71617a7c6763224300f6740b5e7fae274734afec675Kostya Serebryanyvoid __asan_describe_address(uptr addr) {
71717a7c6763224300f6740b5e7fae274734afec675Kostya Serebryany  DescribeAddress(addr, 1);
71817a7c6763224300f6740b5e7fae274734afec675Kostya Serebryany}
71917a7c6763224300f6740b5e7fae274734afec675Kostya Serebryany
7206a08d29b2020004b801ca69d8aea5872a7e67d72Alexey Samsonov#if !SANITIZER_SUPPORTS_WEAK_HOOKS
721866334332ff8c2a1b7f3715224614b6b75a7578cAlexey Samsonov// Provide default implementation of __asan_on_error that does nothing
722866334332ff8c2a1b7f3715224614b6b75a7578cAlexey Samsonov// and may be overriden by user.
723866334332ff8c2a1b7f3715224614b6b75a7578cAlexey SamsonovSANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE NOINLINE
724866334332ff8c2a1b7f3715224614b6b75a7578cAlexey Samsonovvoid __asan_on_error() {}
7256a08d29b2020004b801ca69d8aea5872a7e67d72Alexey Samsonov#endif
726