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"
217354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov
227354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonovnamespace __asan {
237354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov
24f657a1977b6053c76ca8393f574da7593ea3ea12Alexey Samsonov// -------------------- User-specified callbacks ----------------- {{{1
25c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonovstatic void (*error_report_callback)(const char*);
26c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonovstatic char *error_message_buffer = 0;
27c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonovstatic uptr error_message_buffer_pos = 0;
28c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonovstatic uptr error_message_buffer_size = 0;
29c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov
30c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonovvoid AppendToErrorMessageBuffer(const char *buffer) {
31c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov  if (error_message_buffer) {
32c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    uptr length = internal_strlen(buffer);
33c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    CHECK_GE(error_message_buffer_size, error_message_buffer_pos);
34c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    uptr remaining = error_message_buffer_size - error_message_buffer_pos;
35c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    internal_strncpy(error_message_buffer + error_message_buffer_pos,
36c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov                     buffer, remaining);
37c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    error_message_buffer[error_message_buffer_size - 1] = '\0';
38c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    // FIXME: reallocate the buffer instead of truncating the message.
39c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    error_message_buffer_pos += remaining > length ? length : remaining;
40c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov  }
41c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov}
42c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov
43f657a1977b6053c76ca8393f574da7593ea3ea12Alexey Samsonovstatic void (*on_error_callback)(void);
44f657a1977b6053c76ca8393f574da7593ea3ea12Alexey Samsonov
459873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov// ---------------------- Helper functions ----------------------- {{{1
469873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov
479873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonovstatic void PrintBytes(const char *before, uptr *a) {
489873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  u8 *bytes = (u8*)a;
499873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  uptr byte_num = (__WORDSIZE) / 8;
50283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Printf("%s%p:", before, (void*)a);
519873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  for (uptr i = 0; i < byte_num; i++) {
52283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany    Printf(" %x%x", bytes[i] >> 4, bytes[i] & 15);
539873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  }
54283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Printf("\n");
559873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov}
569873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov
579873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonovstatic void PrintShadowMemoryForAddress(uptr addr) {
589873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  if (!AddrIsInMem(addr))
599873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    return;
609873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  uptr shadow_addr = MemToShadow(addr);
61283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Printf("Shadow byte and word:\n");
62283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Printf("  %p: %x\n", (void*)shadow_addr, *(unsigned char*)shadow_addr);
639873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  uptr aligned_shadow = shadow_addr & ~(kWordSize - 1);
649873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  PrintBytes("  ", (uptr*)(aligned_shadow));
65283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Printf("More shadow bytes:\n");
669873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  for (int i = -4; i <= 4; i++) {
679873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    const char *prefix = (i == 0) ? "=>" : "  ";
689873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    PrintBytes(prefix, (uptr*)(aligned_shadow + i * kWordSize));
699873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  }
709873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov}
719873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov
729873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonovstatic void PrintZoneForPointer(uptr ptr, uptr zone_ptr,
739873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov                                const char *zone_name) {
749873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  if (zone_ptr) {
759873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    if (zone_name) {
76283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany      Printf("malloc_zone_from_ptr(%p) = %p, which is %s\n",
779873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov                 ptr, zone_ptr, zone_name);
789873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    } else {
79283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany      Printf("malloc_zone_from_ptr(%p) = %p, which doesn't have a name\n",
809873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov                 ptr, zone_ptr);
819873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    }
829873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  } else {
83283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany    Printf("malloc_zone_from_ptr(%p) = 0\n", ptr);
849873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  }
859873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov}
869873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov
87e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov// ---------------------- Address Descriptions ------------------- {{{1
88e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov
89e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonovstatic bool IsASCII(unsigned char c) {
909873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  return /*0x00 <= c &&*/ c <= 0x7F;
91e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov}
92e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov
93e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov// Check if the global is a zero-terminated ASCII string. If so, print it.
94e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonovstatic void PrintGlobalNameIfASCII(const __asan_global &g) {
95e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov  for (uptr p = g.beg; p < g.beg + g.size - 1; p++) {
96e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov    if (!IsASCII(*(unsigned char*)p)) return;
97e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov  }
98e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov  if (*(char*)(g.beg + g.size - 1) != 0) return;
99283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Printf("  '%s' is ascii string '%s'\n", g.name, (char*)g.beg);
100e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov}
101e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov
102e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonovbool DescribeAddressRelativeToGlobal(uptr addr, const __asan_global &g) {
103e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov  if (addr < g.beg - kGlobalAndStackRedzone) return false;
104e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov  if (addr >= g.beg + g.size_with_redzone) return false;
105283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Printf("%p is located ", (void*)addr);
106e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov  if (addr < g.beg) {
107283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany    Printf("%zd bytes to the left", g.beg - addr);
108e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov  } else if (addr >= g.beg + g.size) {
109283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany    Printf("%zd bytes to the right", addr - (g.beg + g.size));
110e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov  } else {
111283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany    Printf("%zd bytes inside", addr - g.beg);  // Can it happen?
112e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov  }
113283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Printf(" of global variable '%s' (0x%zx) of size %zu\n",
114e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov             g.name, g.beg, g.size);
115e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov  PrintGlobalNameIfASCII(g);
116e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov  return true;
117e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov}
118e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov
119e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonovbool DescribeAddressIfShadow(uptr addr) {
120e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  if (AddrIsInMem(addr))
121e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    return false;
122e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  static const char kAddrInShadowReport[] =
123e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov      "Address %p is located in the %s.\n";
124e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  if (AddrIsInShadowGap(addr)) {
125283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany    Printf(kAddrInShadowReport, addr, "shadow gap area");
126e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    return true;
127e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  }
128e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  if (AddrIsInHighShadow(addr)) {
129283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany    Printf(kAddrInShadowReport, addr, "high shadow area");
130e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    return true;
131e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  }
132e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  if (AddrIsInLowShadow(addr)) {
133283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany    Printf(kAddrInShadowReport, addr, "low shadow area");
134e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    return true;
135e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  }
136e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  CHECK(0 && "Address is not in memory and not in shadow?");
137e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  return false;
138e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov}
139e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov
140e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonovbool DescribeAddressIfStack(uptr addr, uptr access_size) {
141e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  AsanThread *t = asanThreadRegistry().FindThreadByStackAddress(addr);
142e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  if (!t) return false;
143e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  const sptr kBufSize = 4095;
144e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  char buf[kBufSize];
145e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  uptr offset = 0;
146e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  const char *frame_descr = t->GetFrameNameByAddr(addr, &offset);
147e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  // This string is created by the compiler and has the following form:
148e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  // "FunctioName n alloc_1 alloc_2 ... alloc_n"
149e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  // where alloc_i looks like "offset size len ObjectName ".
150e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  CHECK(frame_descr);
151e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  // Report the function name and the offset.
152e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  const char *name_end = internal_strchr(frame_descr, ' ');
153e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  CHECK(name_end);
154e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  buf[0] = 0;
155e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  internal_strncat(buf, frame_descr,
156e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov                   Min(kBufSize,
157e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov                       static_cast<sptr>(name_end - frame_descr)));
158283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Printf("Address %p is located at offset %zu "
159e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov             "in frame <%s> of T%d's stack:\n",
160e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov             (void*)addr, offset, buf, t->tid());
161e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  // Report the number of stack objects.
162e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  char *p;
163e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  uptr n_objects = internal_simple_strtoll(name_end, &p, 10);
164e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  CHECK(n_objects > 0);
165283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Printf("  This frame has %zu object(s):\n", n_objects);
166e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  // Report all objects in this frame.
167e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  for (uptr i = 0; i < n_objects; i++) {
168e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    uptr beg, size;
169e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    sptr len;
170e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    beg  = internal_simple_strtoll(p, &p, 10);
171e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    size = internal_simple_strtoll(p, &p, 10);
172e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    len  = internal_simple_strtoll(p, &p, 10);
173e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    if (beg <= 0 || size <= 0 || len < 0 || *p != ' ') {
174283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany      Printf("AddressSanitizer can't parse the stack frame "
175e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov                 "descriptor: |%s|\n", frame_descr);
176e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov      break;
177e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    }
178e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    p++;
179e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    buf[0] = 0;
180e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    internal_strncat(buf, p, Min(kBufSize, len));
181e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    p += len;
182283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany    Printf("    [%zu, %zu) '%s'\n", beg, beg + size, buf);
183e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  }
184283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Printf("HINT: this may be a false positive if your program uses "
185e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov             "some custom stack unwind mechanism\n"
186e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov             "      (longjmp and C++ exceptions *are* supported)\n");
18771b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov  DescribeThread(t->summary());
188e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  return true;
189e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov}
190e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov
191e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonovvoid DescribeAddress(uptr addr, uptr access_size) {
192e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  // Check if this is shadow or shadow gap.
193e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  if (DescribeAddressIfShadow(addr))
194e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    return;
195e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  CHECK(AddrIsInMem(addr));
196e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  if (DescribeAddressIfGlobal(addr))
197e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    return;
198e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  if (DescribeAddressIfStack(addr, access_size))
199e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov    return;
200e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  // Assume it is a heap address.
201e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov  DescribeHeapAddress(addr, access_size);
202e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov}
203e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov
20471b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov// ------------------- Thread description -------------------- {{{1
20571b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov
20671b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonovvoid DescribeThread(AsanThreadSummary *summary) {
20771b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov  CHECK(summary);
20871b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov  // No need to announce the main thread.
20971b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov  if (summary->tid() == 0 || summary->announced()) {
21071b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov    return;
21171b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov  }
21271b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov  summary->set_announced(true);
21371b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov  Printf("Thread T%d created by T%d here:\n",
21471b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov         summary->tid(), summary->parent_tid());
21571b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov  PrintStack(summary->stack());
21671b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov  // Recursively described parent thread if needed.
21771b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov  if (flags()->print_full_thread_history) {
21871b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov    AsanThreadSummary *parent_summary =
21971b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov        asanThreadRegistry().FindByTid(summary->parent_tid());
22071b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov    DescribeThread(parent_summary);
22171b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov  }
22271b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov}
22371b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov
224e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov// -------------------- Different kinds of reports ----------------- {{{1
225e218beb2d14b663bd277158f386a86d0e62fef74Alexey Samsonov
2269873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov// Use ScopedInErrorReport to run common actions just before and
2279873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov// immediately after printing error report.
2289873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonovclass ScopedInErrorReport {
2299873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov public:
2309873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  ScopedInErrorReport() {
2319873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    static atomic_uint32_t num_calls;
2329873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) {
2339873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov      // Do not print more than one report, otherwise they will mix up.
2349873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov      // Error reporting functions shouldn't return at this situation, as
2359873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov      // they are defined as no-return.
236283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany      Report("AddressSanitizer: while reporting a bug found another one."
2379873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov                 "Ignoring.\n");
238be98caf9fe5e7b94b2009616cf31f0d87cf98d67Alexey Samsonov      // We can't use infinite busy loop here, as ASan may try to report an
239be98caf9fe5e7b94b2009616cf31f0d87cf98d67Alexey Samsonov      // error while another error report is being printed (e.g. if the code
240be98caf9fe5e7b94b2009616cf31f0d87cf98d67Alexey Samsonov      // that prints error report for buffer overflow results in SEGV).
2419873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov      SleepForSeconds(Max(5, flags()->sleep_before_dying + 1));
242be98caf9fe5e7b94b2009616cf31f0d87cf98d67Alexey Samsonov      Die();
2439873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    }
244f657a1977b6053c76ca8393f574da7593ea3ea12Alexey Samsonov    if (on_error_callback) {
245f657a1977b6053c76ca8393f574da7593ea3ea12Alexey Samsonov      on_error_callback();
246f657a1977b6053c76ca8393f574da7593ea3ea12Alexey Samsonov    }
247283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany    Printf("===================================================="
2489873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov               "=============\n");
2499873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    AsanThread *curr_thread = asanThreadRegistry().GetCurrent();
2509873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    if (curr_thread) {
2519873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov      // We started reporting an error message. Stop using the fake stack
2529873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov      // in case we call an instrumented function from a symbolizer.
2539873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov      curr_thread->fake_stack().StopUsingFakeStack();
2549873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    }
2559873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  }
2569873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  // Destructor is NORETURN, as functions that report errors are.
2579873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  NORETURN ~ScopedInErrorReport() {
2589873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    // Make sure the current thread is announced.
2599873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    AsanThread *curr_thread = asanThreadRegistry().GetCurrent();
2609873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    if (curr_thread) {
26171b42c9740e6f73da607aaa539affb5c4807231cAlexey Samsonov      DescribeThread(curr_thread->summary());
2629873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    }
2639873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    // Print memory stats.
2649873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    __asan_print_accumulated_stats();
2659873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    if (error_report_callback) {
2669873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov      error_report_callback(error_message_buffer);
2679873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    }
268283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany    Report("ABORTING\n");
2699873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov    Die();
2709873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  }
2719873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov};
2729873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov
273f4e21fb6369497a271373ef4530e33a40e607542Daniel Dunbar#pragma clang diagnostic push
274f4e21fb6369497a271373ef4530e33a40e607542Daniel Dunbar#pragma clang diagnostic ignored "-Winvalid-noreturn"
275f4e21fb6369497a271373ef4530e33a40e607542Daniel Dunbar
2767354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonovvoid ReportSIGSEGV(uptr pc, uptr sp, uptr bp, uptr addr) {
2779873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  ScopedInErrorReport in_report;
278283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Report("ERROR: AddressSanitizer crashed on unknown address %p"
2797354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov             " (pc %p sp %p bp %p T%d)\n",
2807354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov             (void*)addr, (void*)pc, (void*)sp, (void*)bp,
2817354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov             asanThreadRegistry().GetCurrentTidOrInvalid());
282283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Printf("AddressSanitizer can not provide additional info.\n");
2837354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov  GET_STACK_TRACE_WITH_PC_AND_BP(kStackTraceMax, pc, bp);
284cc347222d55967fdb775429a8a0a3a5d795b8b50Kostya Serebryany  PrintStack(&stack);
2857354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov}
2867354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov
287c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryanyvoid ReportDoubleFree(uptr addr, StackTrace *stack) {
2889873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  ScopedInErrorReport in_report;
289283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Report("ERROR: AddressSanitizer attempting double-free on %p:\n", addr);
290cc347222d55967fdb775429a8a0a3a5d795b8b50Kostya Serebryany  PrintStack(stack);
291f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov  DescribeHeapAddress(addr, 1);
292f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov}
293f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov
294c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryanyvoid ReportFreeNotMalloced(uptr addr, StackTrace *stack) {
2959873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  ScopedInErrorReport in_report;
296283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Report("ERROR: AddressSanitizer attempting free on address "
297f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov             "which was not malloc()-ed: %p\n", addr);
298cc347222d55967fdb775429a8a0a3a5d795b8b50Kostya Serebryany  PrintStack(stack);
2999873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  DescribeHeapAddress(addr, 1);
300f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov}
301f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov
302c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryanyvoid ReportMallocUsableSizeNotOwned(uptr addr, StackTrace *stack) {
3039873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  ScopedInErrorReport in_report;
304283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Report("ERROR: AddressSanitizer attempting to call "
305f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov             "malloc_usable_size() for pointer which is "
306f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov             "not owned: %p\n", addr);
307cc347222d55967fdb775429a8a0a3a5d795b8b50Kostya Serebryany  PrintStack(stack);
308f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov  DescribeHeapAddress(addr, 1);
309f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov}
310f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov
311c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryanyvoid ReportAsanGetAllocatedSizeNotOwned(uptr addr, StackTrace *stack) {
3129873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  ScopedInErrorReport in_report;
313283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Report("ERROR: AddressSanitizer attempting to call "
314f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov             "__asan_get_allocated_size() for pointer which is "
315f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov             "not owned: %p\n", addr);
316cc347222d55967fdb775429a8a0a3a5d795b8b50Kostya Serebryany  PrintStack(stack);
317f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov  DescribeHeapAddress(addr, 1);
318f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov}
319f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov
320487fee7f6f7497906a00d7d2fe2c75e6d5d4feb1Alexey Samsonovvoid ReportStringFunctionMemoryRangesOverlap(
321487fee7f6f7497906a00d7d2fe2c75e6d5d4feb1Alexey Samsonov    const char *function, const char *offset1, uptr length1,
322c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryany    const char *offset2, uptr length2, StackTrace *stack) {
3239873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  ScopedInErrorReport in_report;
324283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Report("ERROR: AddressSanitizer %s-param-overlap: "
325487fee7f6f7497906a00d7d2fe2c75e6d5d4feb1Alexey Samsonov             "memory ranges [%p,%p) and [%p, %p) overlap\n", \
326487fee7f6f7497906a00d7d2fe2c75e6d5d4feb1Alexey Samsonov             function, offset1, offset1 + length1, offset2, offset2 + length2);
327cc347222d55967fdb775429a8a0a3a5d795b8b50Kostya Serebryany  PrintStack(stack);
3289873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  DescribeAddress((uptr)offset1, length1);
3299873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  DescribeAddress((uptr)offset2, length2);
330487fee7f6f7497906a00d7d2fe2c75e6d5d4feb1Alexey Samsonov}
331f7c1d18183d2dfbd02864cf47b3239d6a5d717c0Alexey Samsonov
332f4e21fb6369497a271373ef4530e33a40e607542Daniel Dunbar#pragma clang diagnostic pop
333f4e21fb6369497a271373ef4530e33a40e607542Daniel Dunbar
334663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov// ----------------------- Mac-specific reports ----------------- {{{1
335663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov
336663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonovvoid WarnMacFreeUnallocated(
337c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryany    uptr addr, uptr zone_ptr, const char *zone_name, StackTrace *stack) {
3389873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  // Just print a warning here.
339283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Printf("free_common(%p) -- attempting to free unallocated memory.\n"
340663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov             "AddressSanitizer is ignoring this error on Mac OS now.\n",
341663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov             addr);
342663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov  PrintZoneForPointer(addr, zone_ptr, zone_name);
343cc347222d55967fdb775429a8a0a3a5d795b8b50Kostya Serebryany  PrintStack(stack);
3449873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  DescribeHeapAddress(addr, 1);
345663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov}
346663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov
347f4e21fb6369497a271373ef4530e33a40e607542Daniel Dunbar#pragma clang diagnostic push
348f4e21fb6369497a271373ef4530e33a40e607542Daniel Dunbar#pragma clang diagnostic ignored "-Winvalid-noreturn"
349f4e21fb6369497a271373ef4530e33a40e607542Daniel Dunbar
350663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonovvoid ReportMacMzReallocUnknown(
351c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryany    uptr addr, uptr zone_ptr, const char *zone_name, StackTrace *stack) {
3529873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  ScopedInErrorReport in_report;
353283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Printf("mz_realloc(%p) -- attempting to realloc unallocated memory.\n"
354663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov             "This is an unrecoverable problem, exiting now.\n",
355663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov             addr);
356663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov  PrintZoneForPointer(addr, zone_ptr, zone_name);
357cc347222d55967fdb775429a8a0a3a5d795b8b50Kostya Serebryany  PrintStack(stack);
3589873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  DescribeHeapAddress(addr, 1);
359663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov}
360663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov
361663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonovvoid ReportMacCfReallocUnknown(
362c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryany    uptr addr, uptr zone_ptr, const char *zone_name, StackTrace *stack) {
3639873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  ScopedInErrorReport in_report;
364283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Printf("cf_realloc(%p) -- attempting to realloc unallocated memory.\n"
365663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov             "This is an unrecoverable problem, exiting now.\n",
366663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov             addr);
367663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov  PrintZoneForPointer(addr, zone_ptr, zone_name);
368cc347222d55967fdb775429a8a0a3a5d795b8b50Kostya Serebryany  PrintStack(stack);
3699873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  DescribeHeapAddress(addr, 1);
370c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov}
371c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov
372f4e21fb6369497a271373ef4530e33a40e607542Daniel Dunbar#pragma clang diagnostic pop
373f4e21fb6369497a271373ef4530e33a40e607542Daniel Dunbar
374812ff90eaad0e4555554ffb81db0e611ec434e10Alexey Samsonov}  // namespace __asan
375812ff90eaad0e4555554ffb81db0e611ec434e10Alexey Samsonov
376812ff90eaad0e4555554ffb81db0e611ec434e10Alexey Samsonov// --------------------------- Interface --------------------- {{{1
377812ff90eaad0e4555554ffb81db0e611ec434e10Alexey Samsonovusing namespace __asan;  // NOLINT
378812ff90eaad0e4555554ffb81db0e611ec434e10Alexey Samsonov
379812ff90eaad0e4555554ffb81db0e611ec434e10Alexey Samsonovvoid __asan_report_error(uptr pc, uptr bp, uptr sp,
380812ff90eaad0e4555554ffb81db0e611ec434e10Alexey Samsonov                         uptr addr, bool is_write, uptr access_size) {
3819873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  ScopedInErrorReport in_report;
382c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov
3839873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  // Determine the error type.
384c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov  const char *bug_descr = "unknown-crash";
385c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov  if (AddrIsInMem(addr)) {
386c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    u8 *shadow_addr = (u8*)MemToShadow(addr);
387c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    // If we are accessing 16 bytes, look at the second shadow byte.
388c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    if (*shadow_addr == 0 && access_size > SHADOW_GRANULARITY)
389c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov      shadow_addr++;
390c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    // If we are in the partial right redzone, look at the next shadow byte.
391c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    if (*shadow_addr > 0 && *shadow_addr < 128)
392c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov      shadow_addr++;
393c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    switch (*shadow_addr) {
394c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov      case kAsanHeapLeftRedzoneMagic:
395c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov      case kAsanHeapRightRedzoneMagic:
396c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        bug_descr = "heap-buffer-overflow";
397c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        break;
398c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov      case kAsanHeapFreeMagic:
399c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        bug_descr = "heap-use-after-free";
400c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        break;
401c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov      case kAsanStackLeftRedzoneMagic:
402c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        bug_descr = "stack-buffer-underflow";
403c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        break;
4043945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany      case kAsanInitializationOrderMagic:
4053945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany        bug_descr = "initialization-order-fiasco";
4063945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany        break;
407c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov      case kAsanStackMidRedzoneMagic:
408c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov      case kAsanStackRightRedzoneMagic:
409c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov      case kAsanStackPartialRedzoneMagic:
410c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        bug_descr = "stack-buffer-overflow";
411c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        break;
412c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov      case kAsanStackAfterReturnMagic:
413c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        bug_descr = "stack-use-after-return";
414c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        break;
415c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov      case kAsanUserPoisonedMemoryMagic:
416c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        bug_descr = "use-after-poison";
417c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        break;
418c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov      case kAsanGlobalRedzoneMagic:
419c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        bug_descr = "global-buffer-overflow";
420c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        break;
421c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    }
422c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov  }
423c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov
424283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Report("ERROR: AddressSanitizer %s on address "
425c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov             "%p at pc 0x%zx bp 0x%zx sp 0x%zx\n",
426c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov             bug_descr, (void*)addr, pc, bp, sp);
427c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov
4289873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  u32 curr_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
429283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany  Printf("%s of size %zu at %p thread T%d\n",
430c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov             access_size ? (is_write ? "WRITE" : "READ") : "ACCESS",
431c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov             access_size, (void*)addr, curr_tid);
432c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov
433c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov  GET_STACK_TRACE_WITH_PC_AND_BP(kStackTraceMax, pc, bp);
434cc347222d55967fdb775429a8a0a3a5d795b8b50Kostya Serebryany  PrintStack(&stack);
435c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov
436c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov  DescribeAddress(addr, access_size);
437c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov
4389873792adb79e9daa1594564cbe5b2d680c5ed13Alexey Samsonov  PrintShadowMemoryForAddress(addr);
439c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov}
440c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov
441c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonovvoid NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) {
442c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov  error_report_callback = callback;
443c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov  if (callback) {
444c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    error_message_buffer_size = 1 << 16;
445c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    error_message_buffer =
446c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov        (char*)MmapOrDie(error_message_buffer_size, __FUNCTION__);
447c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov    error_message_buffer_pos = 0;
448c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov  }
449c98570beff64ec0a513dcc11a4662ffba70e43ddAlexey Samsonov}
450f657a1977b6053c76ca8393f574da7593ea3ea12Alexey Samsonov
451f657a1977b6053c76ca8393f574da7593ea3ea12Alexey Samsonovvoid NOINLINE __asan_set_on_error_callback(void (*callback)(void)) {
452f657a1977b6053c76ca8393f574da7593ea3ea12Alexey Samsonov  on_error_callback = callback;
453f657a1977b6053c76ca8393f574da7593ea3ea12Alexey Samsonov}
454