asan_report.cc revision 89c1384464848c1ad041becf8b97936fa10de21b
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"
207354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov#include "asan_thread_registry.h"
2158f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany#include "sanitizer_common/sanitizer_common.h"
2258f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany#include "sanitizer_common/sanitizer_report_decorator.h"
239c92748b8fa3b833924138a6ae1e653972c9de3bAlexey Samsonov#include "sanitizer_common/sanitizer_symbolizer.h"
247354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov
257354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonovnamespace __asan {
267354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov
27f657a1977b6053c76ca8393f574da7593ea3ea12Alexey Samsonov// -------------------- User-specified callbacks ----------------- {{{1
28c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonovstatic void (*error_report_callback)(const char*);
29c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonovstatic char *error_message_buffer = 0;
30c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonovstatic uptr error_message_buffer_pos = 0;
31c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonovstatic uptr error_message_buffer_size = 0;
32c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov
33c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonovvoid AppendToErrorMessageBuffer(const char *buffer) {
34c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov  if (error_message_buffer) {
35c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    uptr length = internal_strlen(buffer);
36c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    CHECK_GE(error_message_buffer_size, error_message_buffer_pos);
37c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    uptr remaining = error_message_buffer_size - error_message_buffer_pos;
38c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    internal_strncpy(error_message_buffer + error_message_buffer_pos,
39c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov                     buffer, remaining);
40c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    error_message_buffer[error_message_buffer_size - 1] = '\0';
41c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    // FIXME: reallocate the buffer instead of truncating the message.
42c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    error_message_buffer_pos += remaining > length ? length : remaining;
43c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov  }
44c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov}
45c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov
4658f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany// ---------------------- Decorator ------------------------------ {{{1
479514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryanybool PrintsToTtyCached() {
489514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  static int cached = 0;
499514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  static bool prints_to_tty;
509514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  if (!cached) {  // Ok wrt threads since we are printing only from one thread.
519514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany    prints_to_tty = PrintsToTty();
529514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany    cached = 1;
539514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  }
549514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  return prints_to_tty;
559514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany}
5658f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryanyclass Decorator: private __sanitizer::AnsiColorDecorator {
5758f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany public:
589514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  Decorator() : __sanitizer::AnsiColorDecorator(PrintsToTtyCached()) { }
5958f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  const char *Warning()    { return Red(); }
6058f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  const char *EndWarning() { return Default(); }
6158f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  const char *Access()     { return Blue(); }
6258f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  const char *EndAccess()  { return Default(); }
6358f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  const char *Location()   { return Green(); }
6458f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  const char *EndLocation() { return Default(); }
6558f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  const char *Allocation()  { return Magenta(); }
6658f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  const char *EndAllocation()  { return Default(); }
679514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany
689514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  const char *ShadowByte(u8 byte) {
699514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany    switch (byte) {
709514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany      case kAsanHeapLeftRedzoneMagic:
719514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany      case kAsanHeapRightRedzoneMagic:
729514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany        return Red();
739514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany      case kAsanHeapFreeMagic:
749514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany        return Magenta();
759514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany      case kAsanStackLeftRedzoneMagic:
769514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany      case kAsanStackMidRedzoneMagic:
779514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany      case kAsanStackRightRedzoneMagic:
789514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany      case kAsanStackPartialRedzoneMagic:
799514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany        return Red();
809514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany      case kAsanStackAfterReturnMagic:
819514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany        return Magenta();
829514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany      case kAsanInitializationOrderMagic:
839514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany        return Cyan();
849514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany      case kAsanUserPoisonedMemoryMagic:
859514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany        return Blue();
869514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany      case kAsanStackUseAfterScopeMagic:
879514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany        return Magenta();
889514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany      case kAsanGlobalRedzoneMagic:
899514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany        return Red();
909514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany      case kAsanInternalHeapMagic:
919514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany        return Yellow();
929514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany      default:
939514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany        return Default();
949514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany    }
959514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  }
969514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  const char *EndShadowByte() { return Default(); }
9758f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany};
9858f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany
999873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov// ---------------------- Helper functions ----------------------- {{{1
1009873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov
1019514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryanystatic void PrintShadowByte(const char *before, u8 byte,
1029514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany                            const char *after = "\n") {
1039514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  Decorator d;
1049514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  Printf("%s%s%x%x%s%s", before,
1059514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany         d.ShadowByte(byte), byte >> 4, byte & 15, d.EndShadowByte(), after);
1069514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany}
1079514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany
1089514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryanystatic void PrintShadowBytes(const char *before, u8 *bytes,
1099514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany                             u8 *guilty, uptr n) {
1109514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  Decorator d;
1119514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  if (before)
1129514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany    Printf("%s%p:", before, bytes);
1139514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  for (uptr i = 0; i < n; i++) {
1149514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany    u8 *p = bytes + i;
1159514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany    const char *before = p == guilty ? "[" :
1169514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany        p - 1 == guilty ? "" : " ";
1179514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany    const char *after = p == guilty ? "]" : "";
1189514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany    PrintShadowByte(before, *p, after);
1199873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  }
120283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Printf("\n");
1219873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov}
1229873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov
12395f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryanystatic void PrintLegend() {
1249514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  Printf("Shadow byte legend (one shadow byte represents %d "
1259514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany         "application bytes):\n", (int)SHADOW_GRANULARITY);
1269514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  PrintShadowByte("  Addressable:           ", 0);
1279514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  Printf("  Partially addressable: ");
1289514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  for (uptr i = 1; i < SHADOW_GRANULARITY; i++)
1299514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany    PrintShadowByte("", i, " ");
1309514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  Printf("\n");
1319514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  PrintShadowByte("  Heap left redzone:     ", kAsanHeapLeftRedzoneMagic);
1329514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  PrintShadowByte("  Heap righ redzone:     ", kAsanHeapRightRedzoneMagic);
1339514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  PrintShadowByte("  Freed Heap region:     ", kAsanHeapFreeMagic);
1349514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  PrintShadowByte("  Stack left redzone:    ", kAsanStackLeftRedzoneMagic);
1359514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  PrintShadowByte("  Stack mid redzone:     ", kAsanStackMidRedzoneMagic);
1369514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  PrintShadowByte("  Stack right redzone:   ", kAsanStackRightRedzoneMagic);
1379514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  PrintShadowByte("  Stack partial redzone: ", kAsanStackPartialRedzoneMagic);
1389514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  PrintShadowByte("  Stack after return:    ", kAsanStackAfterReturnMagic);
1399514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  PrintShadowByte("  Stack use after scope: ", kAsanStackUseAfterScopeMagic);
1409514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  PrintShadowByte("  Global redzone:        ", kAsanGlobalRedzoneMagic);
1419514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  PrintShadowByte("  Global init order:     ", kAsanInitializationOrderMagic);
1429514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  PrintShadowByte("  Poisoned by user:      ", kAsanUserPoisonedMemoryMagic);
1439514a53d7b56be6302c666291b21c0387f7ceca8Kostya Serebryany  PrintShadowByte("  ASan internal:         ", kAsanInternalHeapMagic);
1449873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov}
1459873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov
14695f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryanystatic void PrintShadowMemoryForAddress(uptr addr) {
14795f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryany  if (!AddrIsInMem(addr))
14895f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryany    return;
14995f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryany  uptr shadow_addr = MemToShadow(addr);
15095f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryany  const uptr n_bytes_per_row = 16;
15195f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryany  uptr aligned_shadow = shadow_addr & ~(n_bytes_per_row - 1);
15295f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryany  Printf("Shadow bytes around the buggy address:\n");
15395f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryany  for (int i = -5; i <= 5; i++) {
15495f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryany    const char *prefix = (i == 0) ? "=>" : "  ";
15595f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryany    PrintShadowBytes(prefix,
15695f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryany                     (u8*)(aligned_shadow + i * n_bytes_per_row),
15795f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryany                     (u8*)shadow_addr, n_bytes_per_row);
15895f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryany  }
15995f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryany  if (flags()->print_legend)
16095f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryany    PrintLegend();
16195f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryany}
16295f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryany
1639873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonovstatic void PrintZoneForPointer(uptr ptr, uptr zone_ptr,
1649873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov                                const char *zone_name) {
1659873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  if (zone_ptr) {
1669873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    if (zone_name) {
167283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany      Printf("malloc_zone_from_ptr(%p) = %p, which is %s\n",
1689873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov                 ptr, zone_ptr, zone_name);
1699873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    } else {
170283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany      Printf("malloc_zone_from_ptr(%p) = %p, which doesn't have a name\n",
1719873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov                 ptr, zone_ptr);
1729873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    }
1739873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  } else {
174283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany    Printf("malloc_zone_from_ptr(%p) = 0\n", ptr);
1759873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  }
1769873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov}
1779873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov
178e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov// ---------------------- Address Descriptions ------------------- {{{1
179e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov
180e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonovstatic bool IsASCII(unsigned char c) {
1819873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  return /*0x00 <= c &&*/ c <= 0x7F;
182e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov}
183e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov
184e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov// Check if the global is a zero-terminated ASCII string. If so, print it.
185e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonovstatic void PrintGlobalNameIfASCII(const __asan_global &g) {
186e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov  for (uptr p = g.beg; p < g.beg + g.size - 1; p++) {
187e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov    if (!IsASCII(*(unsigned char*)p)) return;
188e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov  }
189e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov  if (*(char*)(g.beg + g.size - 1) != 0) return;
190283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Printf("  '%s' is ascii string '%s'\n", g.name, (char*)g.beg);
191e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov}
192e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov
193589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanovbool DescribeAddressRelativeToGlobal(uptr addr, uptr size,
194589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov                                     const __asan_global &g) {
195a3b0e5e4f9f48b2ed0baee10c0236eda7c21c660Kostya Serebryany  static const uptr kMinimalDistanceFromAnotherGlobal = 64;
196a3b0e5e4f9f48b2ed0baee10c0236eda7c21c660Kostya Serebryany  if (addr <= g.beg - kMinimalDistanceFromAnotherGlobal) return false;
197e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov  if (addr >= g.beg + g.size_with_redzone) return false;
19858f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Decorator d;
19958f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.Location());
200e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov  if (addr < g.beg) {
201589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov    Printf("%p is located %zd bytes to the left", (void*)addr, g.beg - addr);
202589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov  } else if (addr + size > g.beg + g.size) {
203589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov    if (addr < g.beg + g.size)
204589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov      addr = g.beg + g.size;
205589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov    Printf("%p is located %zd bytes to the right", (void*)addr,
206589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov           addr - (g.beg + g.size));
207e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov  } else {
208589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov    // Can it happen?
209589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov    Printf("%p is located %zd bytes inside", (void*)addr, addr - g.beg);
210e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov  }
21160c9f441255211f17c4d355ead94392ba1841355Kostya Serebryany  Printf(" of global variable '%s' from '%s' (0x%zx) of size %zu\n",
21260c9f441255211f17c4d355ead94392ba1841355Kostya Serebryany             g.name, g.module_name, g.beg, g.size);
21358f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.EndLocation());
214e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov  PrintGlobalNameIfASCII(g);
215e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov  return true;
216e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov}
217e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov
218e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonovbool DescribeAddressIfShadow(uptr addr) {
219e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  if (AddrIsInMem(addr))
220e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    return false;
221e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  static const char kAddrInShadowReport[] =
222e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov      "Address %p is located in the %s.\n";
223e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  if (AddrIsInShadowGap(addr)) {
224283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany    Printf(kAddrInShadowReport, addr, "shadow gap area");
225e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    return true;
226e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  }
227e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  if (AddrIsInHighShadow(addr)) {
228283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany    Printf(kAddrInShadowReport, addr, "high shadow area");
229e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    return true;
230e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  }
231e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  if (AddrIsInLowShadow(addr)) {
232283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany    Printf(kAddrInShadowReport, addr, "low shadow area");
233e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    return true;
234e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  }
235e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  CHECK(0 && "Address is not in memory and not in shadow?");
236e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  return false;
237e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov}
238e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov
239e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonovbool DescribeAddressIfStack(uptr addr, uptr access_size) {
240e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  AsanThread *t = asanThreadRegistry().FindThreadByStackAddress(addr);
241e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  if (!t) return false;
242e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  const sptr kBufSize = 4095;
243e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  char buf[kBufSize];
244e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  uptr offset = 0;
245e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  const char *frame_descr = t->GetFrameNameByAddr(addr, &offset);
246e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  // This string is created by the compiler and has the following form:
247e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  // "FunctioName n alloc_1 alloc_2 ... alloc_n"
248e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  // where alloc_i looks like "offset size len ObjectName ".
249e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  CHECK(frame_descr);
250e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  // Report the function name and the offset.
251e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  const char *name_end = internal_strchr(frame_descr, ' ');
252e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  CHECK(name_end);
253e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  buf[0] = 0;
254e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  internal_strncat(buf, frame_descr,
255e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov                   Min(kBufSize,
256e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov                       static_cast<sptr>(name_end - frame_descr)));
25758f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Decorator d;
25858f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.Location());
259283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Printf("Address %p is located at offset %zu "
260e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov             "in frame <%s> of T%d's stack:\n",
2619c92748b8fa3b833924138a6ae1e653972c9de3bAlexey Samsonov             (void*)addr, offset, Demangle(buf), t->tid());
26258f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.EndLocation());
263e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  // Report the number of stack objects.
264e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  char *p;
265e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  uptr n_objects = internal_simple_strtoll(name_end, &p, 10);
266e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  CHECK(n_objects > 0);
267283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Printf("  This frame has %zu object(s):\n", n_objects);
268e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  // Report all objects in this frame.
269e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  for (uptr i = 0; i < n_objects; i++) {
270e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    uptr beg, size;
271e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    sptr len;
272e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    beg  = internal_simple_strtoll(p, &p, 10);
273e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    size = internal_simple_strtoll(p, &p, 10);
274e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    len  = internal_simple_strtoll(p, &p, 10);
275e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    if (beg <= 0 || size <= 0 || len < 0 || *p != ' ') {
276283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany      Printf("AddressSanitizer can't parse the stack frame "
277e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov                 "descriptor: |%s|\n", frame_descr);
278e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov      break;
279e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    }
280e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    p++;
281e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    buf[0] = 0;
282e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    internal_strncat(buf, p, Min(kBufSize, len));
283e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    p += len;
284283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany    Printf("    [%zu, %zu) '%s'\n", beg, beg + size, buf);
285e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  }
286283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Printf("HINT: this may be a false positive if your program uses "
2870870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov             "some custom stack unwind mechanism or swapcontext\n"
288e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov             "      (longjmp and C++ exceptions *are* supported)\n");
28971b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov  DescribeThread(t->summary());
290e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  return true;
291e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov}
292e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov
2935c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonovstatic void DescribeAccessToHeapChunk(AsanChunkView chunk, uptr addr,
2945c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov                                      uptr access_size) {
295589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov  sptr offset;
29658f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Decorator d;
29758f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.Location());
298589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov  if (chunk.AddrIsAtLeft(addr, access_size, &offset)) {
299589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov    Printf("%p is located %zd bytes to the left of", (void*)addr, offset);
3005c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov  } else if (chunk.AddrIsAtRight(addr, access_size, &offset)) {
301589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov    if (offset < 0) {
302589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov      addr -= offset;
303589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov      offset = 0;
304589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov    }
305589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov    Printf("%p is located %zd bytes to the right of", (void*)addr, offset);
306589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov  } else if (chunk.AddrIsInside(addr, access_size, &offset)) {
307589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov    Printf("%p is located %zd bytes inside of", (void*)addr, offset);
3085c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov  } else {
309589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov    Printf("%p is located somewhere around (this is AddressSanitizer bug!)",
310589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov           (void*)addr);
3115c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov  }
3125c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov  Printf(" %zu-byte region [%p,%p)\n", chunk.UsedSize(),
3135c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov         (void*)(chunk.Beg()), (void*)(chunk.End()));
31458f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.EndLocation());
3155c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov}
3165c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov
317716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany// Return " (thread_name) " or an empty string if the name is empty.
318716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryanyconst char *ThreadNameWithParenthesis(AsanThreadSummary *t, char buff[],
319716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany                                      uptr buff_len) {
320716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany  const char *name = t->name();
321716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany  if (*name == 0) return "";
322716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany  buff[0] = 0;
323716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany  internal_strncat(buff, " (", 3);
324716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany  internal_strncat(buff, name, buff_len - 4);
325716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany  internal_strncat(buff, ")", 2);
326716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany  return buff;
327716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany}
328716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany
329716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryanyconst char *ThreadNameWithParenthesis(u32 tid, char buff[],
330716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany                                      uptr buff_len) {
331716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany  if (tid == kInvalidTid) return "";
332716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany  AsanThreadSummary *t = asanThreadRegistry().FindByTid(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);
3415c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov  AsanThreadSummary *alloc_thread =
3425c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov      asanThreadRegistry().FindByTid(chunk.AllocTid());
3435c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov  StackTrace alloc_stack;
3445c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov  chunk.GetAllocStack(&alloc_stack);
34589c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov  AsanThread *t = GetCurrentThread();
3465c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov  CHECK(t);
347716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany  char tname[128];
34858f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Decorator d;
3495c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov  if (chunk.FreeTid() != kInvalidTid) {
3505c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov    AsanThreadSummary *free_thread =
3515c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov        asanThreadRegistry().FindByTid(chunk.FreeTid());
35258f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany    Printf("%sfreed by thread T%d%s here:%s\n", d.Allocation(),
35358f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany           free_thread->tid(),
35458f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany           ThreadNameWithParenthesis(free_thread, tname, sizeof(tname)),
35558f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany           d.EndAllocation());
3565c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov    StackTrace free_stack;
3575c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov    chunk.GetFreeStack(&free_stack);
3585c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov    PrintStack(&free_stack);
35958f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany    Printf("%spreviously allocated by thread T%d%s here:%s\n",
36058f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany           d.Allocation(), alloc_thread->tid(),
36158f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany           ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)),
36258f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany           d.EndAllocation());
3635c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov    PrintStack(&alloc_stack);
3645c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov    DescribeThread(t->summary());
3655c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov    DescribeThread(free_thread);
3665c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov    DescribeThread(alloc_thread);
3675c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov  } else {
36858f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany    Printf("%sallocated by thread T%d%s here:%s\n", d.Allocation(),
36958f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany           alloc_thread->tid(),
37058f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany           ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)),
37158f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany           d.EndAllocation());
3725c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov    PrintStack(&alloc_stack);
3735c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov    DescribeThread(t->summary());
3745c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov    DescribeThread(alloc_thread);
3755c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov  }
3765c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov}
3775c153faa535f671dd0e8d40ab43397f2d3c6f6f5Alexey Samsonov
378e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonovvoid DescribeAddress(uptr addr, uptr access_size) {
379e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  // Check if this is shadow or shadow gap.
380e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  if (DescribeAddressIfShadow(addr))
381e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    return;
382e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  CHECK(AddrIsInMem(addr));
383589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov  if (DescribeAddressIfGlobal(addr, access_size))
384e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    return;
385e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  if (DescribeAddressIfStack(addr, access_size))
386e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    return;
387e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  // Assume it is a heap address.
388e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  DescribeHeapAddress(addr, access_size);
389e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov}
390e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov
39171b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov// ------------------- Thread description -------------------- {{{1
39271b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov
39371b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonovvoid DescribeThread(AsanThreadSummary *summary) {
39471b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov  CHECK(summary);
39571b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov  // No need to announce the main thread.
39671b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov  if (summary->tid() == 0 || summary->announced()) {
39771b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov    return;
39871b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov  }
39971b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov  summary->set_announced(true);
400716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany  char tname[128];
401716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany  Printf("Thread T%d%s", summary->tid(),
402716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany         ThreadNameWithParenthesis(summary->tid(), tname, sizeof(tname)));
403716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany  Printf(" created by T%d%s here:\n",
404716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany         summary->parent_tid(),
405716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany         ThreadNameWithParenthesis(summary->parent_tid(),
406716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany                                   tname, sizeof(tname)));
40771b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov  PrintStack(summary->stack());
40871b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov  // Recursively described parent thread if needed.
40971b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov  if (flags()->print_full_thread_history) {
41071b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov    AsanThreadSummary *parent_summary =
41171b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov        asanThreadRegistry().FindByTid(summary->parent_tid());
41271b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov    DescribeThread(parent_summary);
41371b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov  }
41471b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov}
41571b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov
416e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov// -------------------- Different kinds of reports ----------------- {{{1
417e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov
4189873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov// Use ScopedInErrorReport to run common actions just before and
4199873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov// immediately after printing error report.
4209873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonovclass ScopedInErrorReport {
4219873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov public:
4229873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  ScopedInErrorReport() {
4239873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    static atomic_uint32_t num_calls;
42462e27098b97e5ef74931c536350123a3df9dec6dAlexey Samsonov    static u32 reporting_thread_tid;
4259873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) {
4269873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov      // Do not print more than one report, otherwise they will mix up.
4279873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov      // Error reporting functions shouldn't return at this situation, as
4289873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov      // they are defined as no-return.
429283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany      Report("AddressSanitizer: while reporting a bug found another one."
4309873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov                 "Ignoring.\n");
43189c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov      u32 current_tid = GetCurrentTidOrInvalid();
43262e27098b97e5ef74931c536350123a3df9dec6dAlexey Samsonov      if (current_tid != reporting_thread_tid) {
43362e27098b97e5ef74931c536350123a3df9dec6dAlexey Samsonov        // ASan found two bugs in different threads simultaneously. Sleep
43462e27098b97e5ef74931c536350123a3df9dec6dAlexey Samsonov        // long enough to make sure that the thread which started to print
43562e27098b97e5ef74931c536350123a3df9dec6dAlexey Samsonov        // an error report will finish doing it.
43662e27098b97e5ef74931c536350123a3df9dec6dAlexey Samsonov        SleepForSeconds(Max(100, flags()->sleep_before_dying + 1));
43762e27098b97e5ef74931c536350123a3df9dec6dAlexey Samsonov      }
438f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov      // If we're still not dead for some reason, use raw _exit() instead of
439031633bef8dff03f4e8943a12e34856bd66bbc78Alexey Samsonov      // Die() to bypass any additional checks.
440f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov      internal__exit(flags()->exitcode);
4419873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    }
4426a08d29b2020004b801ca69d8aea5872a7e67d72Alexey Samsonov    ASAN_ON_ERROR();
44389c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov    reporting_thread_tid = GetCurrentTidOrInvalid();
444283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany    Printf("===================================================="
44562e27098b97e5ef74931c536350123a3df9dec6dAlexey Samsonov           "=============\n");
44662e27098b97e5ef74931c536350123a3df9dec6dAlexey Samsonov    if (reporting_thread_tid != kInvalidTid) {
4479873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov      // We started reporting an error message. Stop using the fake stack
4489873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov      // in case we call an instrumented function from a symbolizer.
44989c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov      AsanThread *curr_thread = GetCurrentThread();
45062e27098b97e5ef74931c536350123a3df9dec6dAlexey Samsonov      CHECK(curr_thread);
4519873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov      curr_thread->fake_stack().StopUsingFakeStack();
4529873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    }
4539873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  }
4549873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  // Destructor is NORETURN, as functions that report errors are.
4559873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  NORETURN ~ScopedInErrorReport() {
4569873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    // Make sure the current thread is announced.
45789c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov    AsanThread *curr_thread = GetCurrentThread();
4589873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    if (curr_thread) {
45971b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov      DescribeThread(curr_thread->summary());
4609873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    }
4619873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    // Print memory stats.
46295f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryany    if (flags()->print_stats)
46395f630ae40cef78fb03b18110eff43bcf8d1c040Kostya Serebryany      __asan_print_accumulated_stats();
4649873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    if (error_report_callback) {
4659873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov      error_report_callback(error_message_buffer);
4669873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    }
467283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany    Report("ABORTING\n");
4689873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    Die();
4699873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  }
4709873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov};
4719873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov
4722673fd8406197c42f16cede6d287f72169298c2eKostya Serebryanystatic void ReportSummary(const char *error_type, StackTrace *stack) {
4732673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany  if (!stack->size) return;
4742673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany  if (IsSymbolizerAvailable()) {
4752673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany    AddressInfo ai;
4762673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany    // Currently, we include the first stack frame into the report summary.
4772673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany    // Maybe sometimes we need to choose another frame (e.g. skip memcpy/etc).
4782673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany    SymbolizeCode(stack->trace[0], &ai, 1);
4792673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany    ReportErrorSummary(error_type,
4802673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany                       StripPathPrefix(ai.file, flags()->strip_path_prefix),
4812673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany                       ai.line, ai.function);
4822673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany  }
4832673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany  // FIXME: do we need to print anything at all if there is no symbolizer?
4842673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany}
4852673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany
4867354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonovvoid ReportSIGSEGV(uptr pc, uptr sp, uptr bp, uptr addr) {
4879873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  ScopedInErrorReport in_report;
48858f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Decorator d;
48958f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.Warning());
49069d8ede30a0ef32c74af7e4e795eb4b4e7fb1d36Kostya Serebryany  Report("ERROR: AddressSanitizer: SEGV on unknown address %p"
4917354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov             " (pc %p sp %p bp %p T%d)\n",
4927354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov             (void*)addr, (void*)pc, (void*)sp, (void*)bp,
49389c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov             GetCurrentTidOrInvalid());
49458f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.EndWarning());
495283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Printf("AddressSanitizer can not provide additional info.\n");
496a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  GET_STACK_TRACE_FATAL(pc, bp);
497cc347222d55967fdb775429a8a0a3a5d795b8b50Kostya Serebryany  PrintStack(&stack);
4982673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany  ReportSummary("SEGV", &stack);
4997354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov}
5007354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov
501c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryanyvoid ReportDoubleFree(uptr addr, StackTrace *stack) {
5029873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  ScopedInErrorReport in_report;
50358f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Decorator d;
50458f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.Warning());
50569d8ede30a0ef32c74af7e4e795eb4b4e7fb1d36Kostya Serebryany  Report("ERROR: AddressSanitizer: attempting double-free on %p:\n", addr);
50658f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.EndWarning());
507cc347222d55967fdb775429a8a0a3a5d795b8b50Kostya Serebryany  PrintStack(stack);
508f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov  DescribeHeapAddress(addr, 1);
5092673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany  ReportSummary("double-free", stack);
510f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov}
511f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov
512c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryanyvoid ReportFreeNotMalloced(uptr addr, StackTrace *stack) {
5139873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  ScopedInErrorReport in_report;
51458f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Decorator d;
51558f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.Warning());
51669d8ede30a0ef32c74af7e4e795eb4b4e7fb1d36Kostya Serebryany  Report("ERROR: AddressSanitizer: attempting free on address "
517f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov             "which was not malloc()-ed: %p\n", addr);
51858f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.EndWarning());
519cc347222d55967fdb775429a8a0a3a5d795b8b50Kostya Serebryany  PrintStack(stack);
5209873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  DescribeHeapAddress(addr, 1);
5212673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany  ReportSummary("bad-free", stack);
522f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov}
523f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov
524fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryanyvoid ReportAllocTypeMismatch(uptr addr, StackTrace *stack,
525fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany                             AllocType alloc_type,
526fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany                             AllocType dealloc_type) {
527fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany  static const char *alloc_names[] =
528fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany    {"INVALID", "malloc", "operator new", "operator new []"};
529fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany  static const char *dealloc_names[] =
530fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany    {"INVALID", "free", "operator delete", "operator delete []"};
531fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany  CHECK_NE(alloc_type, dealloc_type);
532fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany  ScopedInErrorReport in_report;
533fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany  Decorator d;
534fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany  Printf("%s", d.Warning());
535fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany  Report("ERROR: AddressSanitizer: alloc-dealloc-mismatch (%s vs %s) on %p\n",
536fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany        alloc_names[alloc_type], dealloc_names[dealloc_type], addr);
537fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany  Printf("%s", d.EndWarning());
538fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany  PrintStack(stack);
539fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany  DescribeHeapAddress(addr, 1);
5402673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany  ReportSummary("alloc-dealloc-mismatch", stack);
541fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany  Report("HINT: if you don't care about these warnings you may set "
542fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany         "ASAN_OPTIONS=alloc_dealloc_mismatch=0\n");
543fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany}
544fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany
545c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryanyvoid ReportMallocUsableSizeNotOwned(uptr addr, StackTrace *stack) {
5469873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  ScopedInErrorReport in_report;
54758f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Decorator d;
54858f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.Warning());
54969d8ede30a0ef32c74af7e4e795eb4b4e7fb1d36Kostya Serebryany  Report("ERROR: AddressSanitizer: attempting to call "
550f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov             "malloc_usable_size() for pointer which is "
551f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov             "not owned: %p\n", addr);
55258f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.EndWarning());
553cc347222d55967fdb775429a8a0a3a5d795b8b50Kostya Serebryany  PrintStack(stack);
554f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov  DescribeHeapAddress(addr, 1);
5552673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany  ReportSummary("bad-malloc_usable_size", stack);
556f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov}
557f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov
558c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryanyvoid ReportAsanGetAllocatedSizeNotOwned(uptr addr, StackTrace *stack) {
5599873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  ScopedInErrorReport in_report;
56058f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Decorator d;
56158f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.Warning());
56269d8ede30a0ef32c74af7e4e795eb4b4e7fb1d36Kostya Serebryany  Report("ERROR: AddressSanitizer: attempting to call "
563f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov             "__asan_get_allocated_size() for pointer which is "
564f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov             "not owned: %p\n", addr);
56558f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.EndWarning());
566cc347222d55967fdb775429a8a0a3a5d795b8b50Kostya Serebryany  PrintStack(stack);
567f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov  DescribeHeapAddress(addr, 1);
5682673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany  ReportSummary("bad-__asan_get_allocated_size", stack);
569f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov}
570f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov
571487fee7f6f7497906a00d7d2fe2c75e6d5d4feb1Alexey Samsonovvoid ReportStringFunctionMemoryRangesOverlap(
572487fee7f6f7497906a00d7d2fe2c75e6d5d4feb1Alexey Samsonov    const char *function, const char *offset1, uptr length1,
573c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryany    const char *offset2, uptr length2, StackTrace *stack) {
5749873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  ScopedInErrorReport in_report;
57558f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Decorator d;
5762673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany  char bug_type[100];
5772673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany  internal_snprintf(bug_type, sizeof(bug_type), "%s-param-overlap", function);
57858f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.Warning());
5792673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany  Report("ERROR: AddressSanitizer: %s: "
580487fee7f6f7497906a00d7d2fe2c75e6d5d4feb1Alexey Samsonov             "memory ranges [%p,%p) and [%p, %p) overlap\n", \
5812673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany             bug_type, offset1, offset1 + length1, offset2, offset2 + length2);
58258f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.EndWarning());
583cc347222d55967fdb775429a8a0a3a5d795b8b50Kostya Serebryany  PrintStack(stack);
5849873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  DescribeAddress((uptr)offset1, length1);
5859873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  DescribeAddress((uptr)offset2, length2);
5862673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany  ReportSummary(bug_type, stack);
587487fee7f6f7497906a00d7d2fe2c75e6d5d4feb1Alexey Samsonov}
588f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov
589663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov// ----------------------- Mac-specific reports ----------------- {{{1
590663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov
591663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonovvoid WarnMacFreeUnallocated(
592c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryany    uptr addr, uptr zone_ptr, const char *zone_name, StackTrace *stack) {
5939873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  // Just print a warning here.
594283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Printf("free_common(%p) -- attempting to free unallocated memory.\n"
595663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov             "AddressSanitizer is ignoring this error on Mac OS now.\n",
596663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov             addr);
597663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov  PrintZoneForPointer(addr, zone_ptr, zone_name);
598cc347222d55967fdb775429a8a0a3a5d795b8b50Kostya Serebryany  PrintStack(stack);
5999873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  DescribeHeapAddress(addr, 1);
600663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov}
601663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov
602663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonovvoid ReportMacMzReallocUnknown(
603c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryany    uptr addr, uptr zone_ptr, const char *zone_name, StackTrace *stack) {
6049873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  ScopedInErrorReport in_report;
605283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Printf("mz_realloc(%p) -- attempting to realloc unallocated memory.\n"
606663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov             "This is an unrecoverable problem, exiting now.\n",
607663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov             addr);
608663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov  PrintZoneForPointer(addr, zone_ptr, zone_name);
609cc347222d55967fdb775429a8a0a3a5d795b8b50Kostya Serebryany  PrintStack(stack);
6109873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  DescribeHeapAddress(addr, 1);
611663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov}
612663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov
613663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonovvoid ReportMacCfReallocUnknown(
614c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryany    uptr addr, uptr zone_ptr, const char *zone_name, StackTrace *stack) {
6159873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  ScopedInErrorReport in_report;
616283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Printf("cf_realloc(%p) -- attempting to realloc unallocated memory.\n"
617663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov             "This is an unrecoverable problem, exiting now.\n",
618663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov             addr);
619663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov  PrintZoneForPointer(addr, zone_ptr, zone_name);
620cc347222d55967fdb775429a8a0a3a5d795b8b50Kostya Serebryany  PrintStack(stack);
6219873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  DescribeHeapAddress(addr, 1);
622c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov}
623c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov
624812ff90eaad0e4555554ffb81db0e611ec434e10Alexey Samsonov}  // namespace __asan
625812ff90eaad0e4555554ffb81db0e611ec434e10Alexey Samsonov
626812ff90eaad0e4555554ffb81db0e611ec434e10Alexey Samsonov// --------------------------- Interface --------------------- {{{1
627812ff90eaad0e4555554ffb81db0e611ec434e10Alexey Samsonovusing namespace __asan;  // NOLINT
628812ff90eaad0e4555554ffb81db0e611ec434e10Alexey Samsonov
629812ff90eaad0e4555554ffb81db0e611ec434e10Alexey Samsonovvoid __asan_report_error(uptr pc, uptr bp, uptr sp,
630812ff90eaad0e4555554ffb81db0e611ec434e10Alexey Samsonov                         uptr addr, bool is_write, uptr access_size) {
6319873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  ScopedInErrorReport in_report;
632c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov
6339873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  // Determine the error type.
634c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov  const char *bug_descr = "unknown-crash";
635c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov  if (AddrIsInMem(addr)) {
636c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    u8 *shadow_addr = (u8*)MemToShadow(addr);
637c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    // If we are accessing 16 bytes, look at the second shadow byte.
638c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    if (*shadow_addr == 0 && access_size > SHADOW_GRANULARITY)
639c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov      shadow_addr++;
640c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    // If we are in the partial right redzone, look at the next shadow byte.
641c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    if (*shadow_addr > 0 && *shadow_addr < 128)
642c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov      shadow_addr++;
643c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    switch (*shadow_addr) {
644c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov      case kAsanHeapLeftRedzoneMagic:
645c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov      case kAsanHeapRightRedzoneMagic:
646c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        bug_descr = "heap-buffer-overflow";
647c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        break;
648c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov      case kAsanHeapFreeMagic:
649c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        bug_descr = "heap-use-after-free";
650c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        break;
651c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov      case kAsanStackLeftRedzoneMagic:
652c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        bug_descr = "stack-buffer-underflow";
653c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        break;
6543945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany      case kAsanInitializationOrderMagic:
6553945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany        bug_descr = "initialization-order-fiasco";
6563945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany        break;
657c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov      case kAsanStackMidRedzoneMagic:
658c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov      case kAsanStackRightRedzoneMagic:
659c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov      case kAsanStackPartialRedzoneMagic:
660c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        bug_descr = "stack-buffer-overflow";
661c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        break;
662c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov      case kAsanStackAfterReturnMagic:
663c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        bug_descr = "stack-use-after-return";
664c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        break;
665c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov      case kAsanUserPoisonedMemoryMagic:
666c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        bug_descr = "use-after-poison";
667c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        break;
668d4b5db8cb8a7a13bb5cc1d4ce53e8e088303c854Alexey Samsonov      case kAsanStackUseAfterScopeMagic:
669d4b5db8cb8a7a13bb5cc1d4ce53e8e088303c854Alexey Samsonov        bug_descr = "stack-use-after-scope";
670d4b5db8cb8a7a13bb5cc1d4ce53e8e088303c854Alexey Samsonov        break;
671c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov      case kAsanGlobalRedzoneMagic:
672c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        bug_descr = "global-buffer-overflow";
673c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        break;
674c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    }
675c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov  }
67658f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Decorator d;
67758f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.Warning());
67869d8ede30a0ef32c74af7e4e795eb4b4e7fb1d36Kostya Serebryany  Report("ERROR: AddressSanitizer: %s on address "
679c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov             "%p at pc 0x%zx bp 0x%zx sp 0x%zx\n",
680c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov             bug_descr, (void*)addr, pc, bp, sp);
68158f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s", d.EndWarning());
682c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov
68389c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov  u32 curr_tid = GetCurrentTidOrInvalid();
684716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany  char tname[128];
68558f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany  Printf("%s%s of size %zu at %p thread T%d%s%s\n",
68658f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany         d.Access(),
68758f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany         access_size ? (is_write ? "WRITE" : "READ") : "ACCESS",
68858f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany         access_size, (void*)addr, curr_tid,
68958f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany         ThreadNameWithParenthesis(curr_tid, tname, sizeof(tname)),
69058f54555c2528f863e211a0679c2c423cfa55fb2Kostya Serebryany         d.EndAccess());
691c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov
692a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  GET_STACK_TRACE_FATAL(pc, bp);
693cc347222d55967fdb775429a8a0a3a5d795b8b50Kostya Serebryany  PrintStack(&stack);
694c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov
695c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov  DescribeAddress(addr, access_size);
6962673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany  ReportSummary(bug_descr, &stack);
6979873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  PrintShadowMemoryForAddress(addr);
698c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov}
699c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov
700c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonovvoid NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) {
701c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov  error_report_callback = callback;
702c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov  if (callback) {
703c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    error_message_buffer_size = 1 << 16;
704c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    error_message_buffer =
705c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        (char*)MmapOrDie(error_message_buffer_size, __FUNCTION__);
706c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    error_message_buffer_pos = 0;
707c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov  }
708c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov}
709f657a1977b6053c76ca8393f574da7593ea3ea12Alexey Samsonov
71017a7c6763224300f6740b5e7fae274734afec675Kostya Serebryanyvoid __asan_describe_address(uptr addr) {
71117a7c6763224300f6740b5e7fae274734afec675Kostya Serebryany  DescribeAddress(addr, 1);
71217a7c6763224300f6740b5e7fae274734afec675Kostya Serebryany}
71317a7c6763224300f6740b5e7fae274734afec675Kostya Serebryany
7146a08d29b2020004b801ca69d8aea5872a7e67d72Alexey Samsonov#if !SANITIZER_SUPPORTS_WEAK_HOOKS
715866334332ff8c2a1b7f3715224614b6b75a7578cAlexey Samsonov// Provide default implementation of __asan_on_error that does nothing
716866334332ff8c2a1b7f3715224614b6b75a7578cAlexey Samsonov// and may be overriden by user.
717866334332ff8c2a1b7f3715224614b6b75a7578cAlexey SamsonovSANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE NOINLINE
718866334332ff8c2a1b7f3715224614b6b75a7578cAlexey Samsonovvoid __asan_on_error() {}
7196a08d29b2020004b801ca69d8aea5872a7e67d72Alexey Samsonov#endif
720