1 //===-- asan_report.cc ----------------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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"
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
,
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
{
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
) {
60 case kAsanHeapLeftRedzoneMagic
:
61 case kAsanHeapRightRedzoneMagic
:
63 case kAsanHeapFreeMagic
:
65 case kAsanStackLeftRedzoneMagic
:
66 case kAsanStackMidRedzoneMagic
:
67 case kAsanStackRightRedzoneMagic
:
68 case kAsanStackPartialRedzoneMagic
:
70 case kAsanStackAfterReturnMagic
:
72 case kAsanInitializationOrderMagic
:
74 case kAsanUserPoisonedMemoryMagic
:
75 case kAsanContiguousContainerOOBMagic
:
77 case kAsanStackUseAfterScopeMagic
:
79 case kAsanGlobalRedzoneMagic
:
81 case kAsanInternalHeapMagic
:
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") {
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
) {
102 if (before
) str
->append("%s%p:", before
, bytes
);
103 for (uptr i
= 0; i
< n
; i
++) {
106 p
== guilty
? "[" : (p
- 1 == guilty
&& i
!= 0) ? "" : " ";
107 const char *after
= p
== guilty
? "]" : "";
108 PrintShadowByte(str
, before
, *p
, after
);
113 static void PrintLegend(InternalScopedString
*str
) {
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
, " ");
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
) {
169 Printf("malloc_zone_from_ptr(%p) = %p, which is %s\n",
170 ptr
, zone_ptr
, zone_name
);
172 Printf("malloc_zone_from_ptr(%p) = %p, which doesn't have a name\n",
176 Printf("malloc_zone_from_ptr(%p) = 0\n", ptr
);
180 static void DescribeThread(AsanThread
*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
)
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
),
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);
218 str
.append("%s", d
.Location());
220 str
.append("%p is located %zd bytes to the left", (void *)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
));
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());
239 bool DescribeAddressIfShadow(uptr addr
) {
240 if (AddrIsInMem(addr
))
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");
248 if (AddrIsInHighShadow(addr
)) {
249 Printf(kAddrInShadowReport
, addr
, "high shadow area");
252 if (AddrIsInLowShadow(addr
)) {
253 Printf(kAddrInShadowReport
, addr
, "low shadow area");
256 CHECK(0 && "Address is not in memory and not in shadow?");
260 // Return " (thread_name) " or an empty string if the name is empty.
261 const char *ThreadNameWithParenthesis(AsanThreadContext
*t
, char buff
[],
263 const char *name
= t
->name
;
264 if (name
[0] == '\0') return "";
266 internal_strncat(buff
, " (", 3);
267 internal_strncat(buff
, name
, buff_len
- 4);
268 internal_strncat(buff
, ")", 2);
272 const char *ThreadNameWithParenthesis(u32 tid
, char buff
[],
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";
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
);
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());
315 Printf("%s", str
.data());
318 struct StackVarDescr
{
321 const char *name_pos
;
325 bool DescribeAddressIfStack(uptr addr
, uptr access_size
) {
326 AsanThread
*t
= FindThreadByStackAddress(addr
);
327 if (!t
) return false;
328 const uptr kBufSize
= 4095;
333 const char *frame_descr
= t
->GetFrameNameByAddr(addr
, &offset
, &frame_pc
);
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
);
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 ".
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",
351 ThreadNameWithParenthesis(t
->tid(), tname
, sizeof(tname
)),
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.
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
++) {
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
);
387 vars
[i
].name_pos
= p
;
388 vars
[i
].name_len
= len
;
391 for (uptr i
= 0; i
< n_objects
; i
++) {
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
,
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");
408 static void DescribeAccessToHeapChunk(AsanChunkView chunk
, uptr addr
,
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
)) {
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
);
425 str
.append("%p is located somewhere around (this is AddressSanitizer bug!)",
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");
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
);
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(),
455 ThreadNameWithParenthesis(free_thread
, tname
, sizeof(tname
)),
457 StackTrace free_stack
;
458 chunk
.GetFreeStack(&free_stack
);
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
)),
465 Printf("%sallocated by thread T%d%s here:%s\n", d
.Allocation(),
467 ThreadNameWithParenthesis(alloc_thread
, tname
, sizeof(tname
)),
471 DescribeThread(GetCurrentThread());
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
))
481 CHECK(AddrIsInMem(addr
));
482 if (DescribeAddressIfGlobal(addr
, access_size
))
484 if (DescribeAddressIfStack(addr
, access_size
))
486 // Assume it is a heap address.
487 DescribeHeapAddress(addr
, access_size
);
490 // ------------------- Thread description -------------------- {{{1
492 void DescribeThread(AsanThreadContext
*context
) {
494 asanThreadRegistry().CheckLocked();
495 // No need to announce the main thread.
496 if (context
->tid
== 0 || context
->announced
) {
499 context
->announced
= true;
501 InternalScopedString
str(1024);
502 str
.append("Thread T%d%s", context
->tid
,
503 ThreadNameWithParenthesis(context
->tid
, tname
, sizeof(tname
)));
505 " created by T%d%s here:\n", context
->parent_tid
,
506 ThreadNameWithParenthesis(context
->parent_tid
, tname
, sizeof(tname
)));
507 Printf("%s", str
.data());
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
{
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."
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
);
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("===================================================="
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");
571 void ReportStackOverflow(uptr pc
, uptr sp
, uptr bp
, void *context
, uptr addr
) {
572 ScopedInErrorReport in_report
;
574 Printf("%s", d
.Warning());
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
);
583 ReportErrorSummary("stack-overflow", &stack
);
586 void ReportSIGSEGV(uptr pc
, uptr sp
, uptr bp
, void *context
, uptr addr
) {
587 ScopedInErrorReport in_report
;
589 Printf("%s", d
.Warning());
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
);
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
;
605 Printf("%s", d
.Warning());
607 u32 curr_tid
= GetCurrentTidOrInvalid();
608 Report("ERROR: AddressSanitizer: attempting double-free on %p in "
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
);
616 DescribeHeapAddress(addr
, 1);
617 ReportErrorSummary("double-free", &stack
);
620 void ReportFreeNotMalloced(uptr addr
, StackTrace
*free_stack
) {
621 ScopedInErrorReport in_report
;
623 Printf("%s", d
.Warning());
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
);
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
;
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
);
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
;
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());
669 DescribeHeapAddress(addr
, 1);
670 ReportErrorSummary("bad-malloc_usable_size", stack
);
673 void ReportAsanGetAllocatedSizeNotOwned(uptr addr
, StackTrace
*stack
) {
674 ScopedInErrorReport in_report
;
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());
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
;
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());
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
,
707 ScopedInErrorReport in_report
;
708 Report("ERROR: AddressSanitizer: bad parameters to "
709 "__sanitizer_annotate_contiguous_container:\n"
714 beg
, end
, old_mid
, new_mid
);
716 ReportErrorSummary("bad-__sanitizer_annotate_contiguous_container", stack
);
719 // ----------------------- CheckForInvalidPointerPair ----------- {{{1
721 ReportInvalidPointerPair(uptr pc
, uptr bp
, uptr sp
, uptr a1
, uptr a2
) {
722 ScopedInErrorReport in_report
;
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
);
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",
755 PrintZoneForPointer(addr
, zone_ptr
, zone_name
);
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",
766 PrintZoneForPointer(addr
, zone_ptr
, zone_name
);
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",
777 PrintZoneForPointer(addr
, zone_ptr
, zone_name
);
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
)
798 // If we are in the partial right redzone, look at the next shadow byte.
799 if (*shadow_addr
> 0 && *shadow_addr
< 128)
801 switch (*shadow_addr
) {
802 case kAsanHeapLeftRedzoneMagic
:
803 case kAsanHeapRightRedzoneMagic
:
804 bug_descr
= "heap-buffer-overflow";
806 case kAsanHeapFreeMagic
:
807 bug_descr
= "heap-use-after-free";
809 case kAsanStackLeftRedzoneMagic
:
810 bug_descr
= "stack-buffer-underflow";
812 case kAsanInitializationOrderMagic
:
813 bug_descr
= "initialization-order-fiasco";
815 case kAsanStackMidRedzoneMagic
:
816 case kAsanStackRightRedzoneMagic
:
817 case kAsanStackPartialRedzoneMagic
:
818 bug_descr
= "stack-buffer-overflow";
820 case kAsanStackAfterReturnMagic
:
821 bug_descr
= "stack-use-after-return";
823 case kAsanUserPoisonedMemoryMagic
:
824 bug_descr
= "use-after-poison";
826 case kAsanContiguousContainerOOBMagic
:
827 bug_descr
= "container-overflow";
829 case kAsanStackUseAfterScopeMagic
:
830 bug_descr
= "stack-use-after-scope";
832 case kAsanGlobalRedzoneMagic
:
833 bug_descr
= "global-buffer-overflow";
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();
846 Printf("%s%s of size %zu at %p thread T%d%s%s\n",
848 access_size
? (is_write
? "WRITE" : "READ") : "ACCESS",
849 access_size
, (void*)addr
, curr_tid
,
850 ThreadNameWithParenthesis(curr_tid
, tname
, sizeof(tname
)),
853 GET_STACK_TRACE_FATAL(pc
, bp
);
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
;
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);
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
);
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() {}