[CMake] Respect CMAKE_CXX_FLAGS in custom clang_compile commands
[blocksruntime.git] / lib / asan / asan_report.cc
blob2a6de8ecfd23770acca9e02e1e9991aff8bd26c1
1 //===-- asan_report.cc ----------------------------------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file is a part of AddressSanitizer, an address sanity checker.
12 // This file contains error reporting code.
13 //===----------------------------------------------------------------------===//
14 #include "asan_flags.h"
15 #include "asan_internal.h"
16 #include "asan_mapping.h"
17 #include "asan_report.h"
18 #include "asan_stack.h"
19 #include "asan_thread.h"
20 #include "sanitizer_common/sanitizer_common.h"
21 #include "sanitizer_common/sanitizer_flags.h"
22 #include "sanitizer_common/sanitizer_report_decorator.h"
23 #include "sanitizer_common/sanitizer_stackdepot.h"
24 #include "sanitizer_common/sanitizer_symbolizer.h"
26 namespace __asan {
28 // -------------------- User-specified callbacks ----------------- {{{1
29 static void (*error_report_callback)(const char*);
30 static char *error_message_buffer = 0;
31 static uptr error_message_buffer_pos = 0;
32 static uptr error_message_buffer_size = 0;
34 void AppendToErrorMessageBuffer(const char *buffer) {
35 if (error_message_buffer) {
36 uptr length = internal_strlen(buffer);
37 CHECK_GE(error_message_buffer_size, error_message_buffer_pos);
38 uptr remaining = error_message_buffer_size - error_message_buffer_pos;
39 internal_strncpy(error_message_buffer + error_message_buffer_pos,
40 buffer, remaining);
41 error_message_buffer[error_message_buffer_size - 1] = '\0';
42 // FIXME: reallocate the buffer instead of truncating the message.
43 error_message_buffer_pos += remaining > length ? length : remaining;
47 // ---------------------- Decorator ------------------------------ {{{1
48 class Decorator: public __sanitizer::SanitizerCommonDecorator {
49 public:
50 Decorator() : SanitizerCommonDecorator() { }
51 const char *Access() { return Blue(); }
52 const char *EndAccess() { return Default(); }
53 const char *Location() { return Green(); }
54 const char *EndLocation() { return Default(); }
55 const char *Allocation() { return Magenta(); }
56 const char *EndAllocation() { return Default(); }
58 const char *ShadowByte(u8 byte) {
59 switch (byte) {
60 case kAsanHeapLeftRedzoneMagic:
61 case kAsanHeapRightRedzoneMagic:
62 return Red();
63 case kAsanHeapFreeMagic:
64 return Magenta();
65 case kAsanStackLeftRedzoneMagic:
66 case kAsanStackMidRedzoneMagic:
67 case kAsanStackRightRedzoneMagic:
68 case kAsanStackPartialRedzoneMagic:
69 return Red();
70 case kAsanStackAfterReturnMagic:
71 return Magenta();
72 case kAsanInitializationOrderMagic:
73 return Cyan();
74 case kAsanUserPoisonedMemoryMagic:
75 case kAsanContiguousContainerOOBMagic:
76 return Blue();
77 case kAsanStackUseAfterScopeMagic:
78 return Magenta();
79 case kAsanGlobalRedzoneMagic:
80 return Red();
81 case kAsanInternalHeapMagic:
82 return Yellow();
83 default:
84 return Default();
87 const char *EndShadowByte() { return Default(); }
90 // ---------------------- Helper functions ----------------------- {{{1
92 static void PrintShadowByte(InternalScopedString *str, const char *before,
93 u8 byte, const char *after = "\n") {
94 Decorator d;
95 str->append("%s%s%x%x%s%s", before, d.ShadowByte(byte), byte >> 4, byte & 15,
96 d.EndShadowByte(), after);
99 static void PrintShadowBytes(InternalScopedString *str, const char *before,
100 u8 *bytes, u8 *guilty, uptr n) {
101 Decorator d;
102 if (before) str->append("%s%p:", before, bytes);
103 for (uptr i = 0; i < n; i++) {
104 u8 *p = bytes + i;
105 const char *before =
106 p == guilty ? "[" : (p - 1 == guilty && i != 0) ? "" : " ";
107 const char *after = p == guilty ? "]" : "";
108 PrintShadowByte(str, before, *p, after);
110 str->append("\n");
113 static void PrintLegend(InternalScopedString *str) {
114 str->append(
115 "Shadow byte legend (one shadow byte represents %d "
116 "application bytes):\n",
117 (int)SHADOW_GRANULARITY);
118 PrintShadowByte(str, " Addressable: ", 0);
119 str->append(" Partially addressable: ");
120 for (u8 i = 1; i < SHADOW_GRANULARITY; i++) PrintShadowByte(str, "", i, " ");
121 str->append("\n");
122 PrintShadowByte(str, " Heap left redzone: ",
123 kAsanHeapLeftRedzoneMagic);
124 PrintShadowByte(str, " Heap right redzone: ",
125 kAsanHeapRightRedzoneMagic);
126 PrintShadowByte(str, " Freed heap region: ", kAsanHeapFreeMagic);
127 PrintShadowByte(str, " Stack left redzone: ",
128 kAsanStackLeftRedzoneMagic);
129 PrintShadowByte(str, " Stack mid redzone: ",
130 kAsanStackMidRedzoneMagic);
131 PrintShadowByte(str, " Stack right redzone: ",
132 kAsanStackRightRedzoneMagic);
133 PrintShadowByte(str, " Stack partial redzone: ",
134 kAsanStackPartialRedzoneMagic);
135 PrintShadowByte(str, " Stack after return: ",
136 kAsanStackAfterReturnMagic);
137 PrintShadowByte(str, " Stack use after scope: ",
138 kAsanStackUseAfterScopeMagic);
139 PrintShadowByte(str, " Global redzone: ", kAsanGlobalRedzoneMagic);
140 PrintShadowByte(str, " Global init order: ",
141 kAsanInitializationOrderMagic);
142 PrintShadowByte(str, " Poisoned by user: ",
143 kAsanUserPoisonedMemoryMagic);
144 PrintShadowByte(str, " Contiguous container OOB:",
145 kAsanContiguousContainerOOBMagic);
146 PrintShadowByte(str, " ASan internal: ", kAsanInternalHeapMagic);
149 static void PrintShadowMemoryForAddress(uptr addr) {
150 if (!AddrIsInMem(addr)) return;
151 uptr shadow_addr = MemToShadow(addr);
152 const uptr n_bytes_per_row = 16;
153 uptr aligned_shadow = shadow_addr & ~(n_bytes_per_row - 1);
154 InternalScopedString str(4096 * 8);
155 str.append("Shadow bytes around the buggy address:\n");
156 for (int i = -5; i <= 5; i++) {
157 const char *prefix = (i == 0) ? "=>" : " ";
158 PrintShadowBytes(&str, prefix, (u8 *)(aligned_shadow + i * n_bytes_per_row),
159 (u8 *)shadow_addr, n_bytes_per_row);
161 if (flags()->print_legend) PrintLegend(&str);
162 Printf("%s", str.data());
165 static void PrintZoneForPointer(uptr ptr, uptr zone_ptr,
166 const char *zone_name) {
167 if (zone_ptr) {
168 if (zone_name) {
169 Printf("malloc_zone_from_ptr(%p) = %p, which is %s\n",
170 ptr, zone_ptr, zone_name);
171 } else {
172 Printf("malloc_zone_from_ptr(%p) = %p, which doesn't have a name\n",
173 ptr, zone_ptr);
175 } else {
176 Printf("malloc_zone_from_ptr(%p) = 0\n", ptr);
180 static void DescribeThread(AsanThread *t) {
181 if (t)
182 DescribeThread(t->context());
185 // ---------------------- Address Descriptions ------------------- {{{1
187 static bool IsASCII(unsigned char c) {
188 return /*0x00 <= c &&*/ c <= 0x7F;
191 static const char *MaybeDemangleGlobalName(const char *name) {
192 // We can spoil names of globals with C linkage, so use an heuristic
193 // approach to check if the name should be demangled.
194 return (name[0] == '_' && name[1] == 'Z')
195 ? Symbolizer::Get()->Demangle(name)
196 : name;
199 // Check if the global is a zero-terminated ASCII string. If so, print it.
200 static void PrintGlobalNameIfASCII(InternalScopedString *str,
201 const __asan_global &g) {
202 for (uptr p = g.beg; p < g.beg + g.size - 1; p++) {
203 unsigned char c = *(unsigned char*)p;
204 if (c == '\0' || !IsASCII(c)) return;
206 if (*(char*)(g.beg + g.size - 1) != '\0') return;
207 str->append(" '%s' is ascii string '%s'\n", MaybeDemangleGlobalName(g.name),
208 (char *)g.beg);
211 bool DescribeAddressRelativeToGlobal(uptr addr, uptr size,
212 const __asan_global &g) {
213 static const uptr kMinimalDistanceFromAnotherGlobal = 64;
214 if (addr <= g.beg - kMinimalDistanceFromAnotherGlobal) return false;
215 if (addr >= g.beg + g.size_with_redzone) return false;
216 InternalScopedString str(4096);
217 Decorator d;
218 str.append("%s", d.Location());
219 if (addr < g.beg) {
220 str.append("%p is located %zd bytes to the left", (void *)addr,
221 g.beg - addr);
222 } else if (addr + size > g.beg + g.size) {
223 if (addr < g.beg + g.size)
224 addr = g.beg + g.size;
225 str.append("%p is located %zd bytes to the right", (void *)addr,
226 addr - (g.beg + g.size));
227 } else {
228 // Can it happen?
229 str.append("%p is located %zd bytes inside", (void *)addr, addr - g.beg);
231 str.append(" of global variable '%s' from '%s' (0x%zx) of size %zu\n",
232 MaybeDemangleGlobalName(g.name), g.module_name, g.beg, g.size);
233 str.append("%s", d.EndLocation());
234 PrintGlobalNameIfASCII(&str, g);
235 Printf("%s", str.data());
236 return true;
239 bool DescribeAddressIfShadow(uptr addr) {
240 if (AddrIsInMem(addr))
241 return false;
242 static const char kAddrInShadowReport[] =
243 "Address %p is located in the %s.\n";
244 if (AddrIsInShadowGap(addr)) {
245 Printf(kAddrInShadowReport, addr, "shadow gap area");
246 return true;
248 if (AddrIsInHighShadow(addr)) {
249 Printf(kAddrInShadowReport, addr, "high shadow area");
250 return true;
252 if (AddrIsInLowShadow(addr)) {
253 Printf(kAddrInShadowReport, addr, "low shadow area");
254 return true;
256 CHECK(0 && "Address is not in memory and not in shadow?");
257 return false;
260 // Return " (thread_name) " or an empty string if the name is empty.
261 const char *ThreadNameWithParenthesis(AsanThreadContext *t, char buff[],
262 uptr buff_len) {
263 const char *name = t->name;
264 if (name[0] == '\0') return "";
265 buff[0] = 0;
266 internal_strncat(buff, " (", 3);
267 internal_strncat(buff, name, buff_len - 4);
268 internal_strncat(buff, ")", 2);
269 return buff;
272 const char *ThreadNameWithParenthesis(u32 tid, char buff[],
273 uptr buff_len) {
274 if (tid == kInvalidTid) return "";
275 asanThreadRegistry().CheckLocked();
276 AsanThreadContext *t = GetThreadContextByTidLocked(tid);
277 return ThreadNameWithParenthesis(t, buff, buff_len);
280 void PrintAccessAndVarIntersection(const char *var_name,
281 uptr var_beg, uptr var_size,
282 uptr addr, uptr access_size,
283 uptr prev_var_end, uptr next_var_beg) {
284 uptr var_end = var_beg + var_size;
285 uptr addr_end = addr + access_size;
286 const char *pos_descr = 0;
287 // If the variable [var_beg, var_end) is the nearest variable to the
288 // current memory access, indicate it in the log.
289 if (addr >= var_beg) {
290 if (addr_end <= var_end)
291 pos_descr = "is inside"; // May happen if this is a use-after-return.
292 else if (addr < var_end)
293 pos_descr = "partially overflows";
294 else if (addr_end <= next_var_beg &&
295 next_var_beg - addr_end >= addr - var_end)
296 pos_descr = "overflows";
297 } else {
298 if (addr_end > var_beg)
299 pos_descr = "partially underflows";
300 else if (addr >= prev_var_end &&
301 addr - prev_var_end >= var_beg - addr_end)
302 pos_descr = "underflows";
304 InternalScopedString str(1024);
305 str.append(" [%zd, %zd) '%s'", var_beg, var_beg + var_size, var_name);
306 if (pos_descr) {
307 Decorator d;
308 // FIXME: we may want to also print the size of the access here,
309 // but in case of accesses generated by memset it may be confusing.
310 str.append("%s <== Memory access at offset %zd %s this variable%s\n",
311 d.Location(), addr, pos_descr, d.EndLocation());
312 } else {
313 str.append("\n");
315 Printf("%s", str.data());
318 struct StackVarDescr {
319 uptr beg;
320 uptr size;
321 const char *name_pos;
322 uptr name_len;
325 bool DescribeAddressIfStack(uptr addr, uptr access_size) {
326 AsanThread *t = FindThreadByStackAddress(addr);
327 if (!t) return false;
328 const uptr kBufSize = 4095;
329 char buf[kBufSize];
330 uptr offset = 0;
331 uptr frame_pc = 0;
332 char tname[128];
333 const char *frame_descr = t->GetFrameNameByAddr(addr, &offset, &frame_pc);
335 #ifdef __powerpc64__
336 // On PowerPC64, the address of a function actually points to a
337 // three-doubleword data structure with the first field containing
338 // the address of the function's code.
339 frame_pc = *reinterpret_cast<uptr *>(frame_pc);
340 #endif
342 // This string is created by the compiler and has the following form:
343 // "n alloc_1 alloc_2 ... alloc_n"
344 // where alloc_i looks like "offset size len ObjectName ".
345 CHECK(frame_descr);
346 Decorator d;
347 Printf("%s", d.Location());
348 Printf("Address %p is located in stack of thread T%d%s "
349 "at offset %zu in frame\n",
350 addr, t->tid(),
351 ThreadNameWithParenthesis(t->tid(), tname, sizeof(tname)),
352 offset);
353 // Now we print the frame where the alloca has happened.
354 // We print this frame as a stack trace with one element.
355 // The symbolizer may print more than one frame if inlining was involved.
356 // The frame numbers may be different than those in the stack trace printed
357 // previously. That's unfortunate, but I have no better solution,
358 // especially given that the alloca may be from entirely different place
359 // (e.g. use-after-scope, or different thread's stack).
360 StackTrace alloca_stack;
361 alloca_stack.trace[0] = frame_pc + 16;
362 alloca_stack.size = 1;
363 Printf("%s", d.EndLocation());
364 alloca_stack.Print();
365 // Report the number of stack objects.
366 char *p;
367 uptr n_objects = (uptr)internal_simple_strtoll(frame_descr, &p, 10);
368 CHECK_GT(n_objects, 0);
369 Printf(" This frame has %zu object(s):\n", n_objects);
371 // Report all objects in this frame.
372 InternalScopedBuffer<StackVarDescr> vars(n_objects);
373 for (uptr i = 0; i < n_objects; i++) {
374 uptr beg, size;
375 uptr len;
376 beg = (uptr)internal_simple_strtoll(p, &p, 10);
377 size = (uptr)internal_simple_strtoll(p, &p, 10);
378 len = (uptr)internal_simple_strtoll(p, &p, 10);
379 if (beg == 0 || size == 0 || *p != ' ') {
380 Printf("AddressSanitizer can't parse the stack frame "
381 "descriptor: |%s|\n", frame_descr);
382 break;
384 p++;
385 vars[i].beg = beg;
386 vars[i].size = size;
387 vars[i].name_pos = p;
388 vars[i].name_len = len;
389 p += len;
391 for (uptr i = 0; i < n_objects; i++) {
392 buf[0] = 0;
393 internal_strncat(buf, vars[i].name_pos,
394 static_cast<uptr>(Min(kBufSize, vars[i].name_len)));
395 uptr prev_var_end = i ? vars[i - 1].beg + vars[i - 1].size : 0;
396 uptr next_var_beg = i + 1 < n_objects ? vars[i + 1].beg : ~(0UL);
397 PrintAccessAndVarIntersection(buf, vars[i].beg, vars[i].size,
398 offset, access_size,
399 prev_var_end, next_var_beg);
401 Printf("HINT: this may be a false positive if your program uses "
402 "some custom stack unwind mechanism or swapcontext\n"
403 " (longjmp and C++ exceptions *are* supported)\n");
404 DescribeThread(t);
405 return true;
408 static void DescribeAccessToHeapChunk(AsanChunkView chunk, uptr addr,
409 uptr access_size) {
410 sptr offset;
411 Decorator d;
412 InternalScopedString str(4096);
413 str.append("%s", d.Location());
414 if (chunk.AddrIsAtLeft(addr, access_size, &offset)) {
415 str.append("%p is located %zd bytes to the left of", (void *)addr, offset);
416 } else if (chunk.AddrIsAtRight(addr, access_size, &offset)) {
417 if (offset < 0) {
418 addr -= offset;
419 offset = 0;
421 str.append("%p is located %zd bytes to the right of", (void *)addr, offset);
422 } else if (chunk.AddrIsInside(addr, access_size, &offset)) {
423 str.append("%p is located %zd bytes inside of", (void*)addr, offset);
424 } else {
425 str.append("%p is located somewhere around (this is AddressSanitizer bug!)",
426 (void *)addr);
428 str.append(" %zu-byte region [%p,%p)\n", chunk.UsedSize(),
429 (void *)(chunk.Beg()), (void *)(chunk.End()));
430 str.append("%s", d.EndLocation());
431 Printf("%s", str.data());
434 void DescribeHeapAddress(uptr addr, uptr access_size) {
435 AsanChunkView chunk = FindHeapChunkByAddress(addr);
436 if (!chunk.IsValid()) {
437 Printf("AddressSanitizer can not describe address in more detail "
438 "(wild memory access suspected).\n");
439 return;
441 DescribeAccessToHeapChunk(chunk, addr, access_size);
442 CHECK(chunk.AllocTid() != kInvalidTid);
443 asanThreadRegistry().CheckLocked();
444 AsanThreadContext *alloc_thread =
445 GetThreadContextByTidLocked(chunk.AllocTid());
446 StackTrace alloc_stack;
447 chunk.GetAllocStack(&alloc_stack);
448 char tname[128];
449 Decorator d;
450 AsanThreadContext *free_thread = 0;
451 if (chunk.FreeTid() != kInvalidTid) {
452 free_thread = GetThreadContextByTidLocked(chunk.FreeTid());
453 Printf("%sfreed by thread T%d%s here:%s\n", d.Allocation(),
454 free_thread->tid,
455 ThreadNameWithParenthesis(free_thread, tname, sizeof(tname)),
456 d.EndAllocation());
457 StackTrace free_stack;
458 chunk.GetFreeStack(&free_stack);
459 free_stack.Print();
460 Printf("%spreviously allocated by thread T%d%s here:%s\n",
461 d.Allocation(), alloc_thread->tid,
462 ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)),
463 d.EndAllocation());
464 } else {
465 Printf("%sallocated by thread T%d%s here:%s\n", d.Allocation(),
466 alloc_thread->tid,
467 ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)),
468 d.EndAllocation());
470 alloc_stack.Print();
471 DescribeThread(GetCurrentThread());
472 if (free_thread)
473 DescribeThread(free_thread);
474 DescribeThread(alloc_thread);
477 void DescribeAddress(uptr addr, uptr access_size) {
478 // Check if this is shadow or shadow gap.
479 if (DescribeAddressIfShadow(addr))
480 return;
481 CHECK(AddrIsInMem(addr));
482 if (DescribeAddressIfGlobal(addr, access_size))
483 return;
484 if (DescribeAddressIfStack(addr, access_size))
485 return;
486 // Assume it is a heap address.
487 DescribeHeapAddress(addr, access_size);
490 // ------------------- Thread description -------------------- {{{1
492 void DescribeThread(AsanThreadContext *context) {
493 CHECK(context);
494 asanThreadRegistry().CheckLocked();
495 // No need to announce the main thread.
496 if (context->tid == 0 || context->announced) {
497 return;
499 context->announced = true;
500 char tname[128];
501 InternalScopedString str(1024);
502 str.append("Thread T%d%s", context->tid,
503 ThreadNameWithParenthesis(context->tid, tname, sizeof(tname)));
504 str.append(
505 " created by T%d%s here:\n", context->parent_tid,
506 ThreadNameWithParenthesis(context->parent_tid, tname, sizeof(tname)));
507 Printf("%s", str.data());
508 uptr stack_size;
509 const uptr *stack_trace = StackDepotGet(context->stack_id, &stack_size);
510 StackTrace::PrintStack(stack_trace, stack_size);
511 // Recursively described parent thread if needed.
512 if (flags()->print_full_thread_history) {
513 AsanThreadContext *parent_context =
514 GetThreadContextByTidLocked(context->parent_tid);
515 DescribeThread(parent_context);
519 // -------------------- Different kinds of reports ----------------- {{{1
521 // Use ScopedInErrorReport to run common actions just before and
522 // immediately after printing error report.
523 class ScopedInErrorReport {
524 public:
525 ScopedInErrorReport() {
526 static atomic_uint32_t num_calls;
527 static u32 reporting_thread_tid;
528 if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) {
529 // Do not print more than one report, otherwise they will mix up.
530 // Error reporting functions shouldn't return at this situation, as
531 // they are defined as no-return.
532 Report("AddressSanitizer: while reporting a bug found another one."
533 "Ignoring.\n");
534 u32 current_tid = GetCurrentTidOrInvalid();
535 if (current_tid != reporting_thread_tid) {
536 // ASan found two bugs in different threads simultaneously. Sleep
537 // long enough to make sure that the thread which started to print
538 // an error report will finish doing it.
539 SleepForSeconds(Max(100, flags()->sleep_before_dying + 1));
541 // If we're still not dead for some reason, use raw _exit() instead of
542 // Die() to bypass any additional checks.
543 internal__exit(flags()->exitcode);
545 ASAN_ON_ERROR();
546 // Make sure the registry and sanitizer report mutexes are locked while
547 // we're printing an error report.
548 // We can lock them only here to avoid self-deadlock in case of
549 // recursive reports.
550 asanThreadRegistry().Lock();
551 CommonSanitizerReportMutex.Lock();
552 reporting_thread_tid = GetCurrentTidOrInvalid();
553 Printf("===================================================="
554 "=============\n");
556 // Destructor is NORETURN, as functions that report errors are.
557 NORETURN ~ScopedInErrorReport() {
558 // Make sure the current thread is announced.
559 DescribeThread(GetCurrentThread());
560 // Print memory stats.
561 if (flags()->print_stats)
562 __asan_print_accumulated_stats();
563 if (error_report_callback) {
564 error_report_callback(error_message_buffer);
566 Report("ABORTING\n");
567 Die();
571 void ReportStackOverflow(uptr pc, uptr sp, uptr bp, void *context, uptr addr) {
572 ScopedInErrorReport in_report;
573 Decorator d;
574 Printf("%s", d.Warning());
575 Report(
576 "ERROR: AddressSanitizer: stack-overflow on address %p"
577 " (pc %p sp %p bp %p T%d)\n",
578 (void *)addr, (void *)pc, (void *)sp, (void *)bp,
579 GetCurrentTidOrInvalid());
580 Printf("%s", d.EndWarning());
581 GET_STACK_TRACE_SIGNAL(pc, bp, context);
582 stack.Print();
583 ReportErrorSummary("stack-overflow", &stack);
586 void ReportSIGSEGV(uptr pc, uptr sp, uptr bp, void *context, uptr addr) {
587 ScopedInErrorReport in_report;
588 Decorator d;
589 Printf("%s", d.Warning());
590 Report(
591 "ERROR: AddressSanitizer: SEGV on unknown address %p"
592 " (pc %p sp %p bp %p T%d)\n",
593 (void *)addr, (void *)pc, (void *)sp, (void *)bp,
594 GetCurrentTidOrInvalid());
595 Printf("%s", d.EndWarning());
596 GET_STACK_TRACE_SIGNAL(pc, bp, context);
597 stack.Print();
598 Printf("AddressSanitizer can not provide additional info.\n");
599 ReportErrorSummary("SEGV", &stack);
602 void ReportDoubleFree(uptr addr, StackTrace *free_stack) {
603 ScopedInErrorReport in_report;
604 Decorator d;
605 Printf("%s", d.Warning());
606 char tname[128];
607 u32 curr_tid = GetCurrentTidOrInvalid();
608 Report("ERROR: AddressSanitizer: attempting double-free on %p in "
609 "thread T%d%s:\n",
610 addr, curr_tid,
611 ThreadNameWithParenthesis(curr_tid, tname, sizeof(tname)));
612 Printf("%s", d.EndWarning());
613 CHECK_GT(free_stack->size, 0);
614 GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp);
615 stack.Print();
616 DescribeHeapAddress(addr, 1);
617 ReportErrorSummary("double-free", &stack);
620 void ReportFreeNotMalloced(uptr addr, StackTrace *free_stack) {
621 ScopedInErrorReport in_report;
622 Decorator d;
623 Printf("%s", d.Warning());
624 char tname[128];
625 u32 curr_tid = GetCurrentTidOrInvalid();
626 Report("ERROR: AddressSanitizer: attempting free on address "
627 "which was not malloc()-ed: %p in thread T%d%s\n", addr,
628 curr_tid, ThreadNameWithParenthesis(curr_tid, tname, sizeof(tname)));
629 Printf("%s", d.EndWarning());
630 CHECK_GT(free_stack->size, 0);
631 GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp);
632 stack.Print();
633 DescribeHeapAddress(addr, 1);
634 ReportErrorSummary("bad-free", &stack);
637 void ReportAllocTypeMismatch(uptr addr, StackTrace *free_stack,
638 AllocType alloc_type,
639 AllocType dealloc_type) {
640 static const char *alloc_names[] =
641 {"INVALID", "malloc", "operator new", "operator new []"};
642 static const char *dealloc_names[] =
643 {"INVALID", "free", "operator delete", "operator delete []"};
644 CHECK_NE(alloc_type, dealloc_type);
645 ScopedInErrorReport in_report;
646 Decorator d;
647 Printf("%s", d.Warning());
648 Report("ERROR: AddressSanitizer: alloc-dealloc-mismatch (%s vs %s) on %p\n",
649 alloc_names[alloc_type], dealloc_names[dealloc_type], addr);
650 Printf("%s", d.EndWarning());
651 CHECK_GT(free_stack->size, 0);
652 GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp);
653 stack.Print();
654 DescribeHeapAddress(addr, 1);
655 ReportErrorSummary("alloc-dealloc-mismatch", &stack);
656 Report("HINT: if you don't care about these warnings you may set "
657 "ASAN_OPTIONS=alloc_dealloc_mismatch=0\n");
660 void ReportMallocUsableSizeNotOwned(uptr addr, StackTrace *stack) {
661 ScopedInErrorReport in_report;
662 Decorator d;
663 Printf("%s", d.Warning());
664 Report("ERROR: AddressSanitizer: attempting to call "
665 "malloc_usable_size() for pointer which is "
666 "not owned: %p\n", addr);
667 Printf("%s", d.EndWarning());
668 stack->Print();
669 DescribeHeapAddress(addr, 1);
670 ReportErrorSummary("bad-malloc_usable_size", stack);
673 void ReportAsanGetAllocatedSizeNotOwned(uptr addr, StackTrace *stack) {
674 ScopedInErrorReport in_report;
675 Decorator d;
676 Printf("%s", d.Warning());
677 Report("ERROR: AddressSanitizer: attempting to call "
678 "__asan_get_allocated_size() for pointer which is "
679 "not owned: %p\n", addr);
680 Printf("%s", d.EndWarning());
681 stack->Print();
682 DescribeHeapAddress(addr, 1);
683 ReportErrorSummary("bad-__asan_get_allocated_size", stack);
686 void ReportStringFunctionMemoryRangesOverlap(
687 const char *function, const char *offset1, uptr length1,
688 const char *offset2, uptr length2, StackTrace *stack) {
689 ScopedInErrorReport in_report;
690 Decorator d;
691 char bug_type[100];
692 internal_snprintf(bug_type, sizeof(bug_type), "%s-param-overlap", function);
693 Printf("%s", d.Warning());
694 Report("ERROR: AddressSanitizer: %s: "
695 "memory ranges [%p,%p) and [%p, %p) overlap\n", \
696 bug_type, offset1, offset1 + length1, offset2, offset2 + length2);
697 Printf("%s", d.EndWarning());
698 stack->Print();
699 DescribeAddress((uptr)offset1, length1);
700 DescribeAddress((uptr)offset2, length2);
701 ReportErrorSummary(bug_type, stack);
704 void ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end,
705 uptr old_mid, uptr new_mid,
706 StackTrace *stack) {
707 ScopedInErrorReport in_report;
708 Report("ERROR: AddressSanitizer: bad parameters to "
709 "__sanitizer_annotate_contiguous_container:\n"
710 " beg : %p\n"
711 " end : %p\n"
712 " old_mid : %p\n"
713 " new_mid : %p\n",
714 beg, end, old_mid, new_mid);
715 stack->Print();
716 ReportErrorSummary("bad-__sanitizer_annotate_contiguous_container", stack);
719 // ----------------------- CheckForInvalidPointerPair ----------- {{{1
720 static NOINLINE void
721 ReportInvalidPointerPair(uptr pc, uptr bp, uptr sp, uptr a1, uptr a2) {
722 ScopedInErrorReport in_report;
723 Decorator d;
724 Printf("%s", d.Warning());
725 Report("ERROR: AddressSanitizer: invalid-pointer-pair: %p %p\n", a1, a2);
726 Printf("%s", d.EndWarning());
727 GET_STACK_TRACE_FATAL(pc, bp);
728 stack.Print();
729 DescribeAddress(a1, 1);
730 DescribeAddress(a2, 1);
731 ReportErrorSummary("invalid-pointer-pair", &stack);
734 static INLINE void CheckForInvalidPointerPair(void *p1, void *p2) {
735 if (!flags()->detect_invalid_pointer_pairs) return;
736 uptr a1 = reinterpret_cast<uptr>(p1);
737 uptr a2 = reinterpret_cast<uptr>(p2);
738 AsanChunkView chunk1 = FindHeapChunkByAddress(a1);
739 AsanChunkView chunk2 = FindHeapChunkByAddress(a2);
740 bool valid1 = chunk1.IsValid();
741 bool valid2 = chunk2.IsValid();
742 if ((valid1 != valid2) || (valid1 && valid2 && !chunk1.Eq(chunk2))) {
743 GET_CALLER_PC_BP_SP; \
744 return ReportInvalidPointerPair(pc, bp, sp, a1, a2);
747 // ----------------------- Mac-specific reports ----------------- {{{1
749 void WarnMacFreeUnallocated(
750 uptr addr, uptr zone_ptr, const char *zone_name, StackTrace *stack) {
751 // Just print a warning here.
752 Printf("free_common(%p) -- attempting to free unallocated memory.\n"
753 "AddressSanitizer is ignoring this error on Mac OS now.\n",
754 addr);
755 PrintZoneForPointer(addr, zone_ptr, zone_name);
756 stack->Print();
757 DescribeHeapAddress(addr, 1);
760 void ReportMacMzReallocUnknown(
761 uptr addr, uptr zone_ptr, const char *zone_name, StackTrace *stack) {
762 ScopedInErrorReport in_report;
763 Printf("mz_realloc(%p) -- attempting to realloc unallocated memory.\n"
764 "This is an unrecoverable problem, exiting now.\n",
765 addr);
766 PrintZoneForPointer(addr, zone_ptr, zone_name);
767 stack->Print();
768 DescribeHeapAddress(addr, 1);
771 void ReportMacCfReallocUnknown(
772 uptr addr, uptr zone_ptr, const char *zone_name, StackTrace *stack) {
773 ScopedInErrorReport in_report;
774 Printf("cf_realloc(%p) -- attempting to realloc unallocated memory.\n"
775 "This is an unrecoverable problem, exiting now.\n",
776 addr);
777 PrintZoneForPointer(addr, zone_ptr, zone_name);
778 stack->Print();
779 DescribeHeapAddress(addr, 1);
782 } // namespace __asan
784 // --------------------------- Interface --------------------- {{{1
785 using namespace __asan; // NOLINT
787 void __asan_report_error(uptr pc, uptr bp, uptr sp,
788 uptr addr, bool is_write, uptr access_size) {
789 ScopedInErrorReport in_report;
791 // Determine the error type.
792 const char *bug_descr = "unknown-crash";
793 if (AddrIsInMem(addr)) {
794 u8 *shadow_addr = (u8*)MemToShadow(addr);
795 // If we are accessing 16 bytes, look at the second shadow byte.
796 if (*shadow_addr == 0 && access_size > SHADOW_GRANULARITY)
797 shadow_addr++;
798 // If we are in the partial right redzone, look at the next shadow byte.
799 if (*shadow_addr > 0 && *shadow_addr < 128)
800 shadow_addr++;
801 switch (*shadow_addr) {
802 case kAsanHeapLeftRedzoneMagic:
803 case kAsanHeapRightRedzoneMagic:
804 bug_descr = "heap-buffer-overflow";
805 break;
806 case kAsanHeapFreeMagic:
807 bug_descr = "heap-use-after-free";
808 break;
809 case kAsanStackLeftRedzoneMagic:
810 bug_descr = "stack-buffer-underflow";
811 break;
812 case kAsanInitializationOrderMagic:
813 bug_descr = "initialization-order-fiasco";
814 break;
815 case kAsanStackMidRedzoneMagic:
816 case kAsanStackRightRedzoneMagic:
817 case kAsanStackPartialRedzoneMagic:
818 bug_descr = "stack-buffer-overflow";
819 break;
820 case kAsanStackAfterReturnMagic:
821 bug_descr = "stack-use-after-return";
822 break;
823 case kAsanUserPoisonedMemoryMagic:
824 bug_descr = "use-after-poison";
825 break;
826 case kAsanContiguousContainerOOBMagic:
827 bug_descr = "container-overflow";
828 break;
829 case kAsanStackUseAfterScopeMagic:
830 bug_descr = "stack-use-after-scope";
831 break;
832 case kAsanGlobalRedzoneMagic:
833 bug_descr = "global-buffer-overflow";
834 break;
837 Decorator d;
838 Printf("%s", d.Warning());
839 Report("ERROR: AddressSanitizer: %s on address "
840 "%p at pc 0x%zx bp 0x%zx sp 0x%zx\n",
841 bug_descr, (void*)addr, pc, bp, sp);
842 Printf("%s", d.EndWarning());
844 u32 curr_tid = GetCurrentTidOrInvalid();
845 char tname[128];
846 Printf("%s%s of size %zu at %p thread T%d%s%s\n",
847 d.Access(),
848 access_size ? (is_write ? "WRITE" : "READ") : "ACCESS",
849 access_size, (void*)addr, curr_tid,
850 ThreadNameWithParenthesis(curr_tid, tname, sizeof(tname)),
851 d.EndAccess());
853 GET_STACK_TRACE_FATAL(pc, bp);
854 stack.Print();
856 DescribeAddress(addr, access_size);
857 ReportErrorSummary(bug_descr, &stack);
858 PrintShadowMemoryForAddress(addr);
861 void NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) {
862 error_report_callback = callback;
863 if (callback) {
864 error_message_buffer_size = 1 << 16;
865 error_message_buffer =
866 (char*)MmapOrDie(error_message_buffer_size, __func__);
867 error_message_buffer_pos = 0;
871 void __asan_describe_address(uptr addr) {
872 DescribeAddress(addr, 1);
875 extern "C" {
876 SANITIZER_INTERFACE_ATTRIBUTE
877 void __sanitizer_ptr_sub(void *a, void *b) {
878 CheckForInvalidPointerPair(a, b);
880 SANITIZER_INTERFACE_ATTRIBUTE
881 void __sanitizer_ptr_cmp(void *a, void *b) {
882 CheckForInvalidPointerPair(a, b);
884 } // extern "C"
886 #if !SANITIZER_SUPPORTS_WEAK_HOOKS
887 // Provide default implementation of __asan_on_error that does nothing
888 // and may be overriden by user.
889 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE NOINLINE
890 void __asan_on_error() {}
891 #endif