PR target/37072
[official-gcc.git] / libsanitizer / asan / asan_report.cc
blobfcccb70ff8b32166614697874842bce279bd31ee
1 //===-- asan_report.cc ----------------------------------------------------===//
2 //
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // This file is a part of AddressSanitizer, an address sanity checker.
9 //
10 // This file contains error reporting code.
11 //===----------------------------------------------------------------------===//
12 #include "asan_flags.h"
13 #include "asan_internal.h"
14 #include "asan_mapping.h"
15 #include "asan_report.h"
16 #include "asan_stack.h"
17 #include "asan_thread.h"
18 #include "sanitizer_common/sanitizer_common.h"
19 #include "sanitizer_common/sanitizer_flags.h"
20 #include "sanitizer_common/sanitizer_report_decorator.h"
21 #include "sanitizer_common/sanitizer_stackdepot.h"
22 #include "sanitizer_common/sanitizer_symbolizer.h"
24 namespace __asan {
26 // -------------------- User-specified callbacks ----------------- {{{1
27 static void (*error_report_callback)(const char*);
28 static char *error_message_buffer = 0;
29 static uptr error_message_buffer_pos = 0;
30 static uptr error_message_buffer_size = 0;
32 struct ReportData {
33 uptr pc;
34 uptr sp;
35 uptr bp;
36 uptr addr;
37 bool is_write;
38 uptr access_size;
39 const char *description;
42 static bool report_happened = false;
43 static ReportData report_data = {};
45 void AppendToErrorMessageBuffer(const char *buffer) {
46 if (error_message_buffer) {
47 uptr length = internal_strlen(buffer);
48 CHECK_GE(error_message_buffer_size, error_message_buffer_pos);
49 uptr remaining = error_message_buffer_size - error_message_buffer_pos;
50 internal_strncpy(error_message_buffer + error_message_buffer_pos,
51 buffer, remaining);
52 error_message_buffer[error_message_buffer_size - 1] = '\0';
53 // FIXME: reallocate the buffer instead of truncating the message.
54 error_message_buffer_pos += remaining > length ? length : remaining;
58 // ---------------------- Decorator ------------------------------ {{{1
59 class Decorator: public __sanitizer::SanitizerCommonDecorator {
60 public:
61 Decorator() : SanitizerCommonDecorator() { }
62 const char *Access() { return Blue(); }
63 const char *EndAccess() { return Default(); }
64 const char *Location() { return Green(); }
65 const char *EndLocation() { return Default(); }
66 const char *Allocation() { return Magenta(); }
67 const char *EndAllocation() { return Default(); }
69 const char *ShadowByte(u8 byte) {
70 switch (byte) {
71 case kAsanHeapLeftRedzoneMagic:
72 case kAsanHeapRightRedzoneMagic:
73 case kAsanArrayCookieMagic:
74 return Red();
75 case kAsanHeapFreeMagic:
76 return Magenta();
77 case kAsanStackLeftRedzoneMagic:
78 case kAsanStackMidRedzoneMagic:
79 case kAsanStackRightRedzoneMagic:
80 case kAsanStackPartialRedzoneMagic:
81 return Red();
82 case kAsanStackAfterReturnMagic:
83 return Magenta();
84 case kAsanInitializationOrderMagic:
85 return Cyan();
86 case kAsanUserPoisonedMemoryMagic:
87 case kAsanContiguousContainerOOBMagic:
88 return Blue();
89 case kAsanStackUseAfterScopeMagic:
90 return Magenta();
91 case kAsanGlobalRedzoneMagic:
92 return Red();
93 case kAsanInternalHeapMagic:
94 return Yellow();
95 case kAsanIntraObjectRedzone:
96 return Yellow();
97 default:
98 return Default();
101 const char *EndShadowByte() { return Default(); }
102 const char *MemoryByte() { return Magenta(); }
103 const char *EndMemoryByte() { return Default(); }
106 // ---------------------- Helper functions ----------------------- {{{1
108 static void PrintMemoryByte(InternalScopedString *str, const char *before,
109 u8 byte, bool in_shadow, const char *after = "\n") {
110 Decorator d;
111 str->append("%s%s%x%x%s%s", before,
112 in_shadow ? d.ShadowByte(byte) : d.MemoryByte(),
113 byte >> 4, byte & 15,
114 in_shadow ? d.EndShadowByte() : d.EndMemoryByte(), after);
117 static void PrintShadowByte(InternalScopedString *str, const char *before,
118 u8 byte, const char *after = "\n") {
119 PrintMemoryByte(str, before, byte, /*in_shadow*/true, after);
122 static void PrintShadowBytes(InternalScopedString *str, const char *before,
123 u8 *bytes, u8 *guilty, uptr n) {
124 Decorator d;
125 if (before) str->append("%s%p:", before, bytes);
126 for (uptr i = 0; i < n; i++) {
127 u8 *p = bytes + i;
128 const char *before =
129 p == guilty ? "[" : (p - 1 == guilty && i != 0) ? "" : " ";
130 const char *after = p == guilty ? "]" : "";
131 PrintShadowByte(str, before, *p, after);
133 str->append("\n");
136 static void PrintLegend(InternalScopedString *str) {
137 str->append(
138 "Shadow byte legend (one shadow byte represents %d "
139 "application bytes):\n",
140 (int)SHADOW_GRANULARITY);
141 PrintShadowByte(str, " Addressable: ", 0);
142 str->append(" Partially addressable: ");
143 for (u8 i = 1; i < SHADOW_GRANULARITY; i++) PrintShadowByte(str, "", i, " ");
144 str->append("\n");
145 PrintShadowByte(str, " Heap left redzone: ",
146 kAsanHeapLeftRedzoneMagic);
147 PrintShadowByte(str, " Heap right redzone: ",
148 kAsanHeapRightRedzoneMagic);
149 PrintShadowByte(str, " Freed heap region: ", kAsanHeapFreeMagic);
150 PrintShadowByte(str, " Stack left redzone: ",
151 kAsanStackLeftRedzoneMagic);
152 PrintShadowByte(str, " Stack mid redzone: ",
153 kAsanStackMidRedzoneMagic);
154 PrintShadowByte(str, " Stack right redzone: ",
155 kAsanStackRightRedzoneMagic);
156 PrintShadowByte(str, " Stack partial redzone: ",
157 kAsanStackPartialRedzoneMagic);
158 PrintShadowByte(str, " Stack after return: ",
159 kAsanStackAfterReturnMagic);
160 PrintShadowByte(str, " Stack use after scope: ",
161 kAsanStackUseAfterScopeMagic);
162 PrintShadowByte(str, " Global redzone: ", kAsanGlobalRedzoneMagic);
163 PrintShadowByte(str, " Global init order: ",
164 kAsanInitializationOrderMagic);
165 PrintShadowByte(str, " Poisoned by user: ",
166 kAsanUserPoisonedMemoryMagic);
167 PrintShadowByte(str, " Container overflow: ",
168 kAsanContiguousContainerOOBMagic);
169 PrintShadowByte(str, " Array cookie: ",
170 kAsanArrayCookieMagic);
171 PrintShadowByte(str, " Intra object redzone: ",
172 kAsanIntraObjectRedzone);
173 PrintShadowByte(str, " ASan internal: ", kAsanInternalHeapMagic);
176 void MaybeDumpInstructionBytes(uptr pc) {
177 if (!flags()->dump_instruction_bytes || (pc < GetPageSizeCached()))
178 return;
179 InternalScopedString str(1024);
180 str.append("First 16 instruction bytes at pc: ");
181 if (IsAccessibleMemoryRange(pc, 16)) {
182 for (int i = 0; i < 16; ++i) {
183 PrintMemoryByte(&str, "", ((u8 *)pc)[i], /*in_shadow*/false, " ");
185 str.append("\n");
186 } else {
187 str.append("unaccessible\n");
189 Report("%s", str.data());
192 static void PrintShadowMemoryForAddress(uptr addr) {
193 if (!AddrIsInMem(addr)) return;
194 uptr shadow_addr = MemToShadow(addr);
195 const uptr n_bytes_per_row = 16;
196 uptr aligned_shadow = shadow_addr & ~(n_bytes_per_row - 1);
197 InternalScopedString str(4096 * 8);
198 str.append("Shadow bytes around the buggy address:\n");
199 for (int i = -5; i <= 5; i++) {
200 const char *prefix = (i == 0) ? "=>" : " ";
201 PrintShadowBytes(&str, prefix, (u8 *)(aligned_shadow + i * n_bytes_per_row),
202 (u8 *)shadow_addr, n_bytes_per_row);
204 if (flags()->print_legend) PrintLegend(&str);
205 Printf("%s", str.data());
208 static void PrintZoneForPointer(uptr ptr, uptr zone_ptr,
209 const char *zone_name) {
210 if (zone_ptr) {
211 if (zone_name) {
212 Printf("malloc_zone_from_ptr(%p) = %p, which is %s\n",
213 ptr, zone_ptr, zone_name);
214 } else {
215 Printf("malloc_zone_from_ptr(%p) = %p, which doesn't have a name\n",
216 ptr, zone_ptr);
218 } else {
219 Printf("malloc_zone_from_ptr(%p) = 0\n", ptr);
223 static void DescribeThread(AsanThread *t) {
224 if (t)
225 DescribeThread(t->context());
228 // ---------------------- Address Descriptions ------------------- {{{1
230 static bool IsASCII(unsigned char c) {
231 return /*0x00 <= c &&*/ c <= 0x7F;
234 static const char *MaybeDemangleGlobalName(const char *name) {
235 // We can spoil names of globals with C linkage, so use an heuristic
236 // approach to check if the name should be demangled.
237 bool should_demangle = false;
238 if (name[0] == '_' && name[1] == 'Z')
239 should_demangle = true;
240 else if (SANITIZER_WINDOWS && name[0] == '\01' && name[1] == '?')
241 should_demangle = true;
243 return should_demangle ? Symbolizer::GetOrInit()->Demangle(name) : name;
246 // Check if the global is a zero-terminated ASCII string. If so, print it.
247 static void PrintGlobalNameIfASCII(InternalScopedString *str,
248 const __asan_global &g) {
249 for (uptr p = g.beg; p < g.beg + g.size - 1; p++) {
250 unsigned char c = *(unsigned char*)p;
251 if (c == '\0' || !IsASCII(c)) return;
253 if (*(char*)(g.beg + g.size - 1) != '\0') return;
254 str->append(" '%s' is ascii string '%s'\n", MaybeDemangleGlobalName(g.name),
255 (char *)g.beg);
258 static const char *GlobalFilename(const __asan_global &g) {
259 const char *res = g.module_name;
260 // Prefer the filename from source location, if is available.
261 if (g.location)
262 res = g.location->filename;
263 CHECK(res);
264 return res;
267 static void PrintGlobalLocation(InternalScopedString *str,
268 const __asan_global &g) {
269 str->append("%s", GlobalFilename(g));
270 if (!g.location)
271 return;
272 if (g.location->line_no)
273 str->append(":%d", g.location->line_no);
274 if (g.location->column_no)
275 str->append(":%d", g.location->column_no);
278 bool DescribeAddressRelativeToGlobal(uptr addr, uptr size,
279 const __asan_global &g) {
280 if (!IsAddressNearGlobal(addr, g)) return false;
281 InternalScopedString str(4096);
282 Decorator d;
283 str.append("%s", d.Location());
284 if (addr < g.beg) {
285 str.append("%p is located %zd bytes to the left", (void *)addr,
286 g.beg - addr);
287 } else if (addr + size > g.beg + g.size) {
288 if (addr < g.beg + g.size)
289 addr = g.beg + g.size;
290 str.append("%p is located %zd bytes to the right", (void *)addr,
291 addr - (g.beg + g.size));
292 } else {
293 // Can it happen?
294 str.append("%p is located %zd bytes inside", (void *)addr, addr - g.beg);
296 str.append(" of global variable '%s' defined in '",
297 MaybeDemangleGlobalName(g.name));
298 PrintGlobalLocation(&str, g);
299 str.append("' (0x%zx) of size %zu\n", g.beg, g.size);
300 str.append("%s", d.EndLocation());
301 PrintGlobalNameIfASCII(&str, g);
302 Printf("%s", str.data());
303 return true;
306 bool DescribeAddressIfShadow(uptr addr, AddressDescription *descr, bool print) {
307 if (AddrIsInMem(addr))
308 return false;
309 const char *area_type = nullptr;
310 if (AddrIsInShadowGap(addr)) area_type = "shadow gap";
311 else if (AddrIsInHighShadow(addr)) area_type = "high shadow";
312 else if (AddrIsInLowShadow(addr)) area_type = "low shadow";
313 if (area_type != nullptr) {
314 if (print) {
315 Printf("Address %p is located in the %s area.\n", addr, area_type);
316 } else {
317 CHECK(descr);
318 descr->region_kind = area_type;
320 return true;
322 CHECK(0 && "Address is not in memory and not in shadow?");
323 return false;
326 // Return " (thread_name) " or an empty string if the name is empty.
327 const char *ThreadNameWithParenthesis(AsanThreadContext *t, char buff[],
328 uptr buff_len) {
329 const char *name = t->name;
330 if (name[0] == '\0') return "";
331 buff[0] = 0;
332 internal_strncat(buff, " (", 3);
333 internal_strncat(buff, name, buff_len - 4);
334 internal_strncat(buff, ")", 2);
335 return buff;
338 const char *ThreadNameWithParenthesis(u32 tid, char buff[],
339 uptr buff_len) {
340 if (tid == kInvalidTid) return "";
341 asanThreadRegistry().CheckLocked();
342 AsanThreadContext *t = GetThreadContextByTidLocked(tid);
343 return ThreadNameWithParenthesis(t, buff, buff_len);
346 static void PrintAccessAndVarIntersection(const StackVarDescr &var, uptr addr,
347 uptr access_size, uptr prev_var_end,
348 uptr next_var_beg) {
349 uptr var_end = var.beg + var.size;
350 uptr addr_end = addr + access_size;
351 const char *pos_descr = 0;
352 // If the variable [var.beg, var_end) is the nearest variable to the
353 // current memory access, indicate it in the log.
354 if (addr >= var.beg) {
355 if (addr_end <= var_end)
356 pos_descr = "is inside"; // May happen if this is a use-after-return.
357 else if (addr < var_end)
358 pos_descr = "partially overflows";
359 else if (addr_end <= next_var_beg &&
360 next_var_beg - addr_end >= addr - var_end)
361 pos_descr = "overflows";
362 } else {
363 if (addr_end > var.beg)
364 pos_descr = "partially underflows";
365 else if (addr >= prev_var_end &&
366 addr - prev_var_end >= var.beg - addr_end)
367 pos_descr = "underflows";
369 InternalScopedString str(1024);
370 str.append(" [%zd, %zd)", var.beg, var_end);
371 // Render variable name.
372 str.append(" '");
373 for (uptr i = 0; i < var.name_len; ++i) {
374 str.append("%c", var.name_pos[i]);
376 str.append("'");
377 if (pos_descr) {
378 Decorator d;
379 // FIXME: we may want to also print the size of the access here,
380 // but in case of accesses generated by memset it may be confusing.
381 str.append("%s <== Memory access at offset %zd %s this variable%s\n",
382 d.Location(), addr, pos_descr, d.EndLocation());
383 } else {
384 str.append("\n");
386 Printf("%s", str.data());
389 bool ParseFrameDescription(const char *frame_descr,
390 InternalMmapVector<StackVarDescr> *vars) {
391 CHECK(frame_descr);
392 char *p;
393 // This string is created by the compiler and has the following form:
394 // "n alloc_1 alloc_2 ... alloc_n"
395 // where alloc_i looks like "offset size len ObjectName".
396 uptr n_objects = (uptr)internal_simple_strtoll(frame_descr, &p, 10);
397 if (n_objects == 0)
398 return false;
400 for (uptr i = 0; i < n_objects; i++) {
401 uptr beg = (uptr)internal_simple_strtoll(p, &p, 10);
402 uptr size = (uptr)internal_simple_strtoll(p, &p, 10);
403 uptr len = (uptr)internal_simple_strtoll(p, &p, 10);
404 if (beg == 0 || size == 0 || *p != ' ') {
405 return false;
407 p++;
408 StackVarDescr var = {beg, size, p, len};
409 vars->push_back(var);
410 p += len;
413 return true;
416 bool DescribeAddressIfStack(uptr addr, uptr access_size) {
417 AsanThread *t = FindThreadByStackAddress(addr);
418 if (!t) return false;
420 Decorator d;
421 char tname[128];
422 Printf("%s", d.Location());
423 Printf("Address %p is located in stack of thread T%d%s", addr, t->tid(),
424 ThreadNameWithParenthesis(t->tid(), tname, sizeof(tname)));
426 // Try to fetch precise stack frame for this access.
427 AsanThread::StackFrameAccess access;
428 if (!t->GetStackFrameAccessByAddr(addr, &access)) {
429 Printf("%s\n", d.EndLocation());
430 return true;
432 Printf(" at offset %zu in frame%s\n", access.offset, d.EndLocation());
434 // Now we print the frame where the alloca has happened.
435 // We print this frame as a stack trace with one element.
436 // The symbolizer may print more than one frame if inlining was involved.
437 // The frame numbers may be different than those in the stack trace printed
438 // previously. That's unfortunate, but I have no better solution,
439 // especially given that the alloca may be from entirely different place
440 // (e.g. use-after-scope, or different thread's stack).
441 #if defined(__powerpc64__) && defined(__BIG_ENDIAN__)
442 // On PowerPC64 ELFv1, the address of a function actually points to a
443 // three-doubleword data structure with the first field containing
444 // the address of the function's code.
445 access.frame_pc = *reinterpret_cast<uptr *>(access.frame_pc);
446 #endif
447 access.frame_pc += 16;
448 Printf("%s", d.EndLocation());
449 StackTrace alloca_stack(&access.frame_pc, 1);
450 alloca_stack.Print();
452 InternalMmapVector<StackVarDescr> vars(16);
453 if (!ParseFrameDescription(access.frame_descr, &vars)) {
454 Printf("AddressSanitizer can't parse the stack frame "
455 "descriptor: |%s|\n", access.frame_descr);
456 // 'addr' is a stack address, so return true even if we can't parse frame
457 return true;
459 uptr n_objects = vars.size();
460 // Report the number of stack objects.
461 Printf(" This frame has %zu object(s):\n", n_objects);
463 // Report all objects in this frame.
464 for (uptr i = 0; i < n_objects; i++) {
465 uptr prev_var_end = i ? vars[i - 1].beg + vars[i - 1].size : 0;
466 uptr next_var_beg = i + 1 < n_objects ? vars[i + 1].beg : ~(0UL);
467 PrintAccessAndVarIntersection(vars[i], access.offset, access_size,
468 prev_var_end, next_var_beg);
470 Printf("HINT: this may be a false positive if your program uses "
471 "some custom stack unwind mechanism or swapcontext\n");
472 if (SANITIZER_WINDOWS)
473 Printf(" (longjmp, SEH and C++ exceptions *are* supported)\n");
474 else
475 Printf(" (longjmp and C++ exceptions *are* supported)\n");
477 DescribeThread(t);
478 return true;
481 static void DescribeAccessToHeapChunk(AsanChunkView chunk, uptr addr,
482 uptr access_size) {
483 sptr offset;
484 Decorator d;
485 InternalScopedString str(4096);
486 str.append("%s", d.Location());
487 if (chunk.AddrIsAtLeft(addr, access_size, &offset)) {
488 str.append("%p is located %zd bytes to the left of", (void *)addr, offset);
489 } else if (chunk.AddrIsAtRight(addr, access_size, &offset)) {
490 if (offset < 0) {
491 addr -= offset;
492 offset = 0;
494 str.append("%p is located %zd bytes to the right of", (void *)addr, offset);
495 } else if (chunk.AddrIsInside(addr, access_size, &offset)) {
496 str.append("%p is located %zd bytes inside of", (void*)addr, offset);
497 } else {
498 str.append("%p is located somewhere around (this is AddressSanitizer bug!)",
499 (void *)addr);
501 str.append(" %zu-byte region [%p,%p)\n", chunk.UsedSize(),
502 (void *)(chunk.Beg()), (void *)(chunk.End()));
503 str.append("%s", d.EndLocation());
504 Printf("%s", str.data());
507 void DescribeHeapAddress(uptr addr, uptr access_size) {
508 AsanChunkView chunk = FindHeapChunkByAddress(addr);
509 if (!chunk.IsValid()) {
510 Printf("AddressSanitizer can not describe address in more detail "
511 "(wild memory access suspected).\n");
512 return;
514 DescribeAccessToHeapChunk(chunk, addr, access_size);
515 CHECK(chunk.AllocTid() != kInvalidTid);
516 asanThreadRegistry().CheckLocked();
517 AsanThreadContext *alloc_thread =
518 GetThreadContextByTidLocked(chunk.AllocTid());
519 StackTrace alloc_stack = chunk.GetAllocStack();
520 char tname[128];
521 Decorator d;
522 AsanThreadContext *free_thread = 0;
523 if (chunk.FreeTid() != kInvalidTid) {
524 free_thread = GetThreadContextByTidLocked(chunk.FreeTid());
525 Printf("%sfreed by thread T%d%s here:%s\n", d.Allocation(),
526 free_thread->tid,
527 ThreadNameWithParenthesis(free_thread, tname, sizeof(tname)),
528 d.EndAllocation());
529 StackTrace free_stack = chunk.GetFreeStack();
530 free_stack.Print();
531 Printf("%spreviously allocated by thread T%d%s here:%s\n",
532 d.Allocation(), alloc_thread->tid,
533 ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)),
534 d.EndAllocation());
535 } else {
536 Printf("%sallocated by thread T%d%s here:%s\n", d.Allocation(),
537 alloc_thread->tid,
538 ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)),
539 d.EndAllocation());
541 alloc_stack.Print();
542 DescribeThread(GetCurrentThread());
543 if (free_thread)
544 DescribeThread(free_thread);
545 DescribeThread(alloc_thread);
548 void DescribeAddress(uptr addr, uptr access_size) {
549 // Check if this is shadow or shadow gap.
550 if (DescribeAddressIfShadow(addr))
551 return;
552 CHECK(AddrIsInMem(addr));
553 if (DescribeAddressIfGlobal(addr, access_size))
554 return;
555 if (DescribeAddressIfStack(addr, access_size))
556 return;
557 // Assume it is a heap address.
558 DescribeHeapAddress(addr, access_size);
561 // ------------------- Thread description -------------------- {{{1
563 void DescribeThread(AsanThreadContext *context) {
564 CHECK(context);
565 asanThreadRegistry().CheckLocked();
566 // No need to announce the main thread.
567 if (context->tid == 0 || context->announced) {
568 return;
570 context->announced = true;
571 char tname[128];
572 InternalScopedString str(1024);
573 str.append("Thread T%d%s", context->tid,
574 ThreadNameWithParenthesis(context->tid, tname, sizeof(tname)));
575 str.append(
576 " created by T%d%s here:\n", context->parent_tid,
577 ThreadNameWithParenthesis(context->parent_tid, tname, sizeof(tname)));
578 Printf("%s", str.data());
579 StackDepotGet(context->stack_id).Print();
580 // Recursively described parent thread if needed.
581 if (flags()->print_full_thread_history) {
582 AsanThreadContext *parent_context =
583 GetThreadContextByTidLocked(context->parent_tid);
584 DescribeThread(parent_context);
588 // -------------------- Different kinds of reports ----------------- {{{1
590 // Use ScopedInErrorReport to run common actions just before and
591 // immediately after printing error report.
592 class ScopedInErrorReport {
593 public:
594 explicit ScopedInErrorReport(ReportData *report = nullptr) {
595 static atomic_uint32_t num_calls;
596 static u32 reporting_thread_tid;
597 if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) {
598 // Do not print more than one report, otherwise they will mix up.
599 // Error reporting functions shouldn't return at this situation, as
600 // they are defined as no-return.
601 Report("AddressSanitizer: while reporting a bug found another one. "
602 "Ignoring.\n");
603 u32 current_tid = GetCurrentTidOrInvalid();
604 if (current_tid != reporting_thread_tid) {
605 // ASan found two bugs in different threads simultaneously. Sleep
606 // long enough to make sure that the thread which started to print
607 // an error report will finish doing it.
608 SleepForSeconds(Max(100, flags()->sleep_before_dying + 1));
610 // If we're still not dead for some reason, use raw _exit() instead of
611 // Die() to bypass any additional checks.
612 internal__exit(flags()->exitcode);
614 if (report) report_data = *report;
615 report_happened = true;
616 ASAN_ON_ERROR();
617 // Make sure the registry and sanitizer report mutexes are locked while
618 // we're printing an error report.
619 // We can lock them only here to avoid self-deadlock in case of
620 // recursive reports.
621 asanThreadRegistry().Lock();
622 CommonSanitizerReportMutex.Lock();
623 reporting_thread_tid = GetCurrentTidOrInvalid();
624 Printf("===================================================="
625 "=============\n");
627 // Destructor is NORETURN, as functions that report errors are.
628 NORETURN ~ScopedInErrorReport() {
629 // Make sure the current thread is announced.
630 DescribeThread(GetCurrentThread());
631 // We may want to grab this lock again when printing stats.
632 asanThreadRegistry().Unlock();
633 // Print memory stats.
634 if (flags()->print_stats)
635 __asan_print_accumulated_stats();
636 if (error_report_callback) {
637 error_report_callback(error_message_buffer);
639 Report("ABORTING\n");
640 Die();
644 void ReportStackOverflow(uptr pc, uptr sp, uptr bp, void *context, uptr addr) {
645 ScopedInErrorReport in_report;
646 Decorator d;
647 Printf("%s", d.Warning());
648 Report(
649 "ERROR: AddressSanitizer: stack-overflow on address %p"
650 " (pc %p bp %p sp %p T%d)\n",
651 (void *)addr, (void *)pc, (void *)bp, (void *)sp,
652 GetCurrentTidOrInvalid());
653 Printf("%s", d.EndWarning());
654 GET_STACK_TRACE_SIGNAL(pc, bp, context);
655 stack.Print();
656 ReportErrorSummary("stack-overflow", &stack);
659 void ReportSIGSEGV(const char *description, uptr pc, uptr sp, uptr bp,
660 void *context, uptr addr) {
661 ScopedInErrorReport in_report;
662 Decorator d;
663 Printf("%s", d.Warning());
664 Report(
665 "ERROR: AddressSanitizer: %s on unknown address %p"
666 " (pc %p bp %p sp %p T%d)\n",
667 description, (void *)addr, (void *)pc, (void *)bp, (void *)sp,
668 GetCurrentTidOrInvalid());
669 if (pc < GetPageSizeCached()) {
670 Report("Hint: pc points to the zero page.\n");
672 Printf("%s", d.EndWarning());
673 GET_STACK_TRACE_SIGNAL(pc, bp, context);
674 stack.Print();
675 MaybeDumpInstructionBytes(pc);
676 Printf("AddressSanitizer can not provide additional info.\n");
677 ReportErrorSummary("SEGV", &stack);
680 void ReportDoubleFree(uptr addr, BufferedStackTrace *free_stack) {
681 ScopedInErrorReport in_report;
682 Decorator d;
683 Printf("%s", d.Warning());
684 char tname[128];
685 u32 curr_tid = GetCurrentTidOrInvalid();
686 Report("ERROR: AddressSanitizer: attempting double-free on %p in "
687 "thread T%d%s:\n",
688 addr, curr_tid,
689 ThreadNameWithParenthesis(curr_tid, tname, sizeof(tname)));
690 Printf("%s", d.EndWarning());
691 CHECK_GT(free_stack->size, 0);
692 GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp);
693 stack.Print();
694 DescribeHeapAddress(addr, 1);
695 ReportErrorSummary("double-free", &stack);
698 void ReportNewDeleteSizeMismatch(uptr addr, uptr delete_size,
699 BufferedStackTrace *free_stack) {
700 ScopedInErrorReport in_report;
701 Decorator d;
702 Printf("%s", d.Warning());
703 char tname[128];
704 u32 curr_tid = GetCurrentTidOrInvalid();
705 Report("ERROR: AddressSanitizer: new-delete-type-mismatch on %p in "
706 "thread T%d%s:\n",
707 addr, curr_tid,
708 ThreadNameWithParenthesis(curr_tid, tname, sizeof(tname)));
709 Printf("%s object passed to delete has wrong type:\n", d.EndWarning());
710 Printf(" size of the allocated type: %zd bytes;\n"
711 " size of the deallocated type: %zd bytes.\n",
712 asan_mz_size(reinterpret_cast<void*>(addr)), delete_size);
713 CHECK_GT(free_stack->size, 0);
714 GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp);
715 stack.Print();
716 DescribeHeapAddress(addr, 1);
717 ReportErrorSummary("new-delete-type-mismatch", &stack);
718 Report("HINT: if you don't care about these warnings you may set "
719 "ASAN_OPTIONS=new_delete_type_mismatch=0\n");
722 void ReportFreeNotMalloced(uptr addr, BufferedStackTrace *free_stack) {
723 ScopedInErrorReport in_report;
724 Decorator d;
725 Printf("%s", d.Warning());
726 char tname[128];
727 u32 curr_tid = GetCurrentTidOrInvalid();
728 Report("ERROR: AddressSanitizer: attempting free on address "
729 "which was not malloc()-ed: %p in thread T%d%s\n", addr,
730 curr_tid, ThreadNameWithParenthesis(curr_tid, tname, sizeof(tname)));
731 Printf("%s", d.EndWarning());
732 CHECK_GT(free_stack->size, 0);
733 GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp);
734 stack.Print();
735 DescribeHeapAddress(addr, 1);
736 ReportErrorSummary("bad-free", &stack);
739 void ReportAllocTypeMismatch(uptr addr, BufferedStackTrace *free_stack,
740 AllocType alloc_type,
741 AllocType dealloc_type) {
742 static const char *alloc_names[] =
743 {"INVALID", "malloc", "operator new", "operator new []"};
744 static const char *dealloc_names[] =
745 {"INVALID", "free", "operator delete", "operator delete []"};
746 CHECK_NE(alloc_type, dealloc_type);
747 ScopedInErrorReport in_report;
748 Decorator d;
749 Printf("%s", d.Warning());
750 Report("ERROR: AddressSanitizer: alloc-dealloc-mismatch (%s vs %s) on %p\n",
751 alloc_names[alloc_type], dealloc_names[dealloc_type], addr);
752 Printf("%s", d.EndWarning());
753 CHECK_GT(free_stack->size, 0);
754 GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp);
755 stack.Print();
756 DescribeHeapAddress(addr, 1);
757 ReportErrorSummary("alloc-dealloc-mismatch", &stack);
758 Report("HINT: if you don't care about these warnings you may set "
759 "ASAN_OPTIONS=alloc_dealloc_mismatch=0\n");
762 void ReportMallocUsableSizeNotOwned(uptr addr, BufferedStackTrace *stack) {
763 ScopedInErrorReport in_report;
764 Decorator d;
765 Printf("%s", d.Warning());
766 Report("ERROR: AddressSanitizer: attempting to call "
767 "malloc_usable_size() for pointer which is "
768 "not owned: %p\n", addr);
769 Printf("%s", d.EndWarning());
770 stack->Print();
771 DescribeHeapAddress(addr, 1);
772 ReportErrorSummary("bad-malloc_usable_size", stack);
775 void ReportSanitizerGetAllocatedSizeNotOwned(uptr addr,
776 BufferedStackTrace *stack) {
777 ScopedInErrorReport in_report;
778 Decorator d;
779 Printf("%s", d.Warning());
780 Report("ERROR: AddressSanitizer: attempting to call "
781 "__sanitizer_get_allocated_size() for pointer which is "
782 "not owned: %p\n", addr);
783 Printf("%s", d.EndWarning());
784 stack->Print();
785 DescribeHeapAddress(addr, 1);
786 ReportErrorSummary("bad-__sanitizer_get_allocated_size", stack);
789 void ReportStringFunctionMemoryRangesOverlap(const char *function,
790 const char *offset1, uptr length1,
791 const char *offset2, uptr length2,
792 BufferedStackTrace *stack) {
793 ScopedInErrorReport in_report;
794 Decorator d;
795 char bug_type[100];
796 internal_snprintf(bug_type, sizeof(bug_type), "%s-param-overlap", function);
797 Printf("%s", d.Warning());
798 Report("ERROR: AddressSanitizer: %s: "
799 "memory ranges [%p,%p) and [%p, %p) overlap\n", \
800 bug_type, offset1, offset1 + length1, offset2, offset2 + length2);
801 Printf("%s", d.EndWarning());
802 stack->Print();
803 DescribeAddress((uptr)offset1, length1);
804 DescribeAddress((uptr)offset2, length2);
805 ReportErrorSummary(bug_type, stack);
808 void ReportStringFunctionSizeOverflow(uptr offset, uptr size,
809 BufferedStackTrace *stack) {
810 ScopedInErrorReport in_report;
811 Decorator d;
812 const char *bug_type = "negative-size-param";
813 Printf("%s", d.Warning());
814 Report("ERROR: AddressSanitizer: %s: (size=%zd)\n", bug_type, size);
815 Printf("%s", d.EndWarning());
816 stack->Print();
817 DescribeAddress(offset, size);
818 ReportErrorSummary(bug_type, stack);
821 void ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end,
822 uptr old_mid, uptr new_mid,
823 BufferedStackTrace *stack) {
824 ScopedInErrorReport in_report;
825 Report("ERROR: AddressSanitizer: bad parameters to "
826 "__sanitizer_annotate_contiguous_container:\n"
827 " beg : %p\n"
828 " end : %p\n"
829 " old_mid : %p\n"
830 " new_mid : %p\n",
831 beg, end, old_mid, new_mid);
832 stack->Print();
833 ReportErrorSummary("bad-__sanitizer_annotate_contiguous_container", stack);
836 void ReportODRViolation(const __asan_global *g1, u32 stack_id1,
837 const __asan_global *g2, u32 stack_id2) {
838 ScopedInErrorReport in_report;
839 Decorator d;
840 Printf("%s", d.Warning());
841 Report("ERROR: AddressSanitizer: odr-violation (%p):\n", g1->beg);
842 Printf("%s", d.EndWarning());
843 InternalScopedString g1_loc(256), g2_loc(256);
844 PrintGlobalLocation(&g1_loc, *g1);
845 PrintGlobalLocation(&g2_loc, *g2);
846 Printf(" [1] size=%zd '%s' %s\n", g1->size,
847 MaybeDemangleGlobalName(g1->name), g1_loc.data());
848 Printf(" [2] size=%zd '%s' %s\n", g2->size,
849 MaybeDemangleGlobalName(g2->name), g2_loc.data());
850 if (stack_id1 && stack_id2) {
851 Printf("These globals were registered at these points:\n");
852 Printf(" [1]:\n");
853 StackDepotGet(stack_id1).Print();
854 Printf(" [2]:\n");
855 StackDepotGet(stack_id2).Print();
857 Report("HINT: if you don't care about these warnings you may set "
858 "ASAN_OPTIONS=detect_odr_violation=0\n");
859 InternalScopedString error_msg(256);
860 error_msg.append("odr-violation: global '%s' at %s",
861 MaybeDemangleGlobalName(g1->name), g1_loc.data());
862 ReportErrorSummary(error_msg.data());
865 // ----------------------- CheckForInvalidPointerPair ----------- {{{1
866 static NOINLINE void
867 ReportInvalidPointerPair(uptr pc, uptr bp, uptr sp, uptr a1, uptr a2) {
868 ScopedInErrorReport in_report;
869 Decorator d;
870 Printf("%s", d.Warning());
871 Report("ERROR: AddressSanitizer: invalid-pointer-pair: %p %p\n", a1, a2);
872 Printf("%s", d.EndWarning());
873 GET_STACK_TRACE_FATAL(pc, bp);
874 stack.Print();
875 DescribeAddress(a1, 1);
876 DescribeAddress(a2, 1);
877 ReportErrorSummary("invalid-pointer-pair", &stack);
880 static INLINE void CheckForInvalidPointerPair(void *p1, void *p2) {
881 if (!flags()->detect_invalid_pointer_pairs) return;
882 uptr a1 = reinterpret_cast<uptr>(p1);
883 uptr a2 = reinterpret_cast<uptr>(p2);
884 AsanChunkView chunk1 = FindHeapChunkByAddress(a1);
885 AsanChunkView chunk2 = FindHeapChunkByAddress(a2);
886 bool valid1 = chunk1.IsValid();
887 bool valid2 = chunk2.IsValid();
888 if ((valid1 != valid2) || (valid1 && valid2 && !chunk1.Eq(chunk2))) {
889 GET_CALLER_PC_BP_SP; \
890 return ReportInvalidPointerPair(pc, bp, sp, a1, a2);
893 // ----------------------- Mac-specific reports ----------------- {{{1
895 void WarnMacFreeUnallocated(uptr addr, uptr zone_ptr, const char *zone_name,
896 BufferedStackTrace *stack) {
897 // Just print a warning here.
898 Printf("free_common(%p) -- attempting to free unallocated memory.\n"
899 "AddressSanitizer is ignoring this error on Mac OS now.\n",
900 addr);
901 PrintZoneForPointer(addr, zone_ptr, zone_name);
902 stack->Print();
903 DescribeHeapAddress(addr, 1);
906 void ReportMacMzReallocUnknown(uptr addr, uptr zone_ptr, const char *zone_name,
907 BufferedStackTrace *stack) {
908 ScopedInErrorReport in_report;
909 Printf("mz_realloc(%p) -- attempting to realloc unallocated memory.\n"
910 "This is an unrecoverable problem, exiting now.\n",
911 addr);
912 PrintZoneForPointer(addr, zone_ptr, zone_name);
913 stack->Print();
914 DescribeHeapAddress(addr, 1);
917 void ReportMacCfReallocUnknown(uptr addr, uptr zone_ptr, const char *zone_name,
918 BufferedStackTrace *stack) {
919 ScopedInErrorReport in_report;
920 Printf("cf_realloc(%p) -- attempting to realloc unallocated memory.\n"
921 "This is an unrecoverable problem, exiting now.\n",
922 addr);
923 PrintZoneForPointer(addr, zone_ptr, zone_name);
924 stack->Print();
925 DescribeHeapAddress(addr, 1);
928 } // namespace __asan
930 // --------------------------- Interface --------------------- {{{1
931 using namespace __asan; // NOLINT
933 void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write,
934 uptr access_size) {
935 // Determine the error type.
936 const char *bug_descr = "unknown-crash";
937 if (AddrIsInMem(addr)) {
938 u8 *shadow_addr = (u8*)MemToShadow(addr);
939 // If we are accessing 16 bytes, look at the second shadow byte.
940 if (*shadow_addr == 0 && access_size > SHADOW_GRANULARITY)
941 shadow_addr++;
942 // If we are in the partial right redzone, look at the next shadow byte.
943 if (*shadow_addr > 0 && *shadow_addr < 128)
944 shadow_addr++;
945 switch (*shadow_addr) {
946 case kAsanHeapLeftRedzoneMagic:
947 case kAsanHeapRightRedzoneMagic:
948 case kAsanArrayCookieMagic:
949 bug_descr = "heap-buffer-overflow";
950 break;
951 case kAsanHeapFreeMagic:
952 bug_descr = "heap-use-after-free";
953 break;
954 case kAsanStackLeftRedzoneMagic:
955 bug_descr = "stack-buffer-underflow";
956 break;
957 case kAsanInitializationOrderMagic:
958 bug_descr = "initialization-order-fiasco";
959 break;
960 case kAsanStackMidRedzoneMagic:
961 case kAsanStackRightRedzoneMagic:
962 case kAsanStackPartialRedzoneMagic:
963 bug_descr = "stack-buffer-overflow";
964 break;
965 case kAsanStackAfterReturnMagic:
966 bug_descr = "stack-use-after-return";
967 break;
968 case kAsanUserPoisonedMemoryMagic:
969 bug_descr = "use-after-poison";
970 break;
971 case kAsanContiguousContainerOOBMagic:
972 bug_descr = "container-overflow";
973 break;
974 case kAsanStackUseAfterScopeMagic:
975 bug_descr = "stack-use-after-scope";
976 break;
977 case kAsanGlobalRedzoneMagic:
978 bug_descr = "global-buffer-overflow";
979 break;
980 case kAsanIntraObjectRedzone:
981 bug_descr = "intra-object-overflow";
982 break;
986 ReportData report = { pc, sp, bp, addr, (bool)is_write, access_size,
987 bug_descr };
988 ScopedInErrorReport in_report(&report);
990 Decorator d;
991 Printf("%s", d.Warning());
992 Report("ERROR: AddressSanitizer: %s on address "
993 "%p at pc %p bp %p sp %p\n",
994 bug_descr, (void*)addr, pc, bp, sp);
995 Printf("%s", d.EndWarning());
997 u32 curr_tid = GetCurrentTidOrInvalid();
998 char tname[128];
999 Printf("%s%s of size %zu at %p thread T%d%s%s\n",
1000 d.Access(),
1001 access_size ? (is_write ? "WRITE" : "READ") : "ACCESS",
1002 access_size, (void*)addr, curr_tid,
1003 ThreadNameWithParenthesis(curr_tid, tname, sizeof(tname)),
1004 d.EndAccess());
1006 GET_STACK_TRACE_FATAL(pc, bp);
1007 stack.Print();
1009 DescribeAddress(addr, access_size);
1010 ReportErrorSummary(bug_descr, &stack);
1011 PrintShadowMemoryForAddress(addr);
1014 void NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) {
1015 error_report_callback = callback;
1016 if (callback) {
1017 error_message_buffer_size = 1 << 16;
1018 error_message_buffer =
1019 (char*)MmapOrDie(error_message_buffer_size, __func__);
1020 error_message_buffer_pos = 0;
1024 void __asan_describe_address(uptr addr) {
1025 // Thread registry must be locked while we're describing an address.
1026 asanThreadRegistry().Lock();
1027 DescribeAddress(addr, 1);
1028 asanThreadRegistry().Unlock();
1031 int __asan_report_present() {
1032 return report_happened ? 1 : 0;
1035 uptr __asan_get_report_pc() {
1036 return report_data.pc;
1039 uptr __asan_get_report_bp() {
1040 return report_data.bp;
1043 uptr __asan_get_report_sp() {
1044 return report_data.sp;
1047 uptr __asan_get_report_address() {
1048 return report_data.addr;
1051 int __asan_get_report_access_type() {
1052 return report_data.is_write ? 1 : 0;
1055 uptr __asan_get_report_access_size() {
1056 return report_data.access_size;
1059 const char *__asan_get_report_description() {
1060 return report_data.description;
1063 extern "C" {
1064 SANITIZER_INTERFACE_ATTRIBUTE
1065 void __sanitizer_ptr_sub(void *a, void *b) {
1066 CheckForInvalidPointerPair(a, b);
1068 SANITIZER_INTERFACE_ATTRIBUTE
1069 void __sanitizer_ptr_cmp(void *a, void *b) {
1070 CheckForInvalidPointerPair(a, b);
1072 } // extern "C"
1074 #if !SANITIZER_SUPPORTS_WEAK_HOOKS
1075 // Provide default implementation of __asan_on_error that does nothing
1076 // and may be overriden by user.
1077 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE NOINLINE
1078 void __asan_on_error() {}
1079 #endif