1 //===-- asan_report.cc ----------------------------------------------------===//
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
8 // This file is a part of AddressSanitizer, an address sanity checker.
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"
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;
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
,
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
{
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
) {
71 case kAsanHeapLeftRedzoneMagic
:
72 case kAsanHeapRightRedzoneMagic
:
73 case kAsanArrayCookieMagic
:
75 case kAsanHeapFreeMagic
:
77 case kAsanStackLeftRedzoneMagic
:
78 case kAsanStackMidRedzoneMagic
:
79 case kAsanStackRightRedzoneMagic
:
80 case kAsanStackPartialRedzoneMagic
:
82 case kAsanStackAfterReturnMagic
:
84 case kAsanInitializationOrderMagic
:
86 case kAsanUserPoisonedMemoryMagic
:
87 case kAsanContiguousContainerOOBMagic
:
89 case kAsanStackUseAfterScopeMagic
:
91 case kAsanGlobalRedzoneMagic
:
93 case kAsanInternalHeapMagic
:
95 case kAsanIntraObjectRedzone
:
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") {
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
) {
125 if (before
) str
->append("%s%p:", before
, bytes
);
126 for (uptr i
= 0; i
< n
; i
++) {
129 p
== guilty
? "[" : (p
- 1 == guilty
&& i
!= 0) ? "" : " ";
130 const char *after
= p
== guilty
? "]" : "";
131 PrintShadowByte(str
, before
, *p
, after
);
136 static void PrintLegend(InternalScopedString
*str
) {
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
, " ");
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()))
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, " ");
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
) {
212 Printf("malloc_zone_from_ptr(%p) = %p, which is %s\n",
213 ptr
, zone_ptr
, zone_name
);
215 Printf("malloc_zone_from_ptr(%p) = %p, which doesn't have a name\n",
219 Printf("malloc_zone_from_ptr(%p) = 0\n", ptr
);
223 static void DescribeThread(AsanThread
*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
),
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.
262 res
= g
.location
->filename
;
267 static void PrintGlobalLocation(InternalScopedString
*str
,
268 const __asan_global
&g
) {
269 str
->append("%s", GlobalFilename(g
));
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);
283 str
.append("%s", d
.Location());
285 str
.append("%p is located %zd bytes to the left", (void *)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
));
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());
306 bool DescribeAddressIfShadow(uptr addr
, AddressDescription
*descr
, bool print
) {
307 if (AddrIsInMem(addr
))
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) {
315 Printf("Address %p is located in the %s area.\n", addr
, area_type
);
318 descr
->region_kind
= area_type
;
322 CHECK(0 && "Address is not in memory and not in shadow?");
326 // Return " (thread_name) " or an empty string if the name is empty.
327 const char *ThreadNameWithParenthesis(AsanThreadContext
*t
, char buff
[],
329 const char *name
= t
->name
;
330 if (name
[0] == '\0') return "";
332 internal_strncat(buff
, " (", 3);
333 internal_strncat(buff
, name
, buff_len
- 4);
334 internal_strncat(buff
, ")", 2);
338 const char *ThreadNameWithParenthesis(u32 tid
, char buff
[],
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
,
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";
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.
373 for (uptr i
= 0; i
< var
.name_len
; ++i
) {
374 str
.append("%c", var
.name_pos
[i
]);
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());
386 Printf("%s", str
.data());
389 bool ParseFrameDescription(const char *frame_descr
,
390 InternalMmapVector
<StackVarDescr
> *vars
) {
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);
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
!= ' ') {
408 StackVarDescr var
= {beg
, size
, p
, len
};
409 vars
->push_back(var
);
416 bool DescribeAddressIfStack(uptr addr
, uptr access_size
) {
417 AsanThread
*t
= FindThreadByStackAddress(addr
);
418 if (!t
) return false;
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());
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
);
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
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");
475 Printf(" (longjmp and C++ exceptions *are* supported)\n");
481 static void DescribeAccessToHeapChunk(AsanChunkView chunk
, uptr addr
,
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
)) {
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
);
498 str
.append("%p is located somewhere around (this is AddressSanitizer bug!)",
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");
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();
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(),
527 ThreadNameWithParenthesis(free_thread
, tname
, sizeof(tname
)),
529 StackTrace free_stack
= chunk
.GetFreeStack();
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
)),
536 Printf("%sallocated by thread T%d%s here:%s\n", d
.Allocation(),
538 ThreadNameWithParenthesis(alloc_thread
, tname
, sizeof(tname
)),
542 DescribeThread(GetCurrentThread());
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
))
552 CHECK(AddrIsInMem(addr
));
553 if (DescribeAddressIfGlobal(addr
, access_size
))
555 if (DescribeAddressIfStack(addr
, access_size
))
557 // Assume it is a heap address.
558 DescribeHeapAddress(addr
, access_size
);
561 // ------------------- Thread description -------------------- {{{1
563 void DescribeThread(AsanThreadContext
*context
) {
565 asanThreadRegistry().CheckLocked();
566 // No need to announce the main thread.
567 if (context
->tid
== 0 || context
->announced
) {
570 context
->announced
= true;
572 InternalScopedString
str(1024);
573 str
.append("Thread T%d%s", context
->tid
,
574 ThreadNameWithParenthesis(context
->tid
, tname
, sizeof(tname
)));
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
{
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. "
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;
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("===================================================="
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");
644 void ReportStackOverflow(uptr pc
, uptr sp
, uptr bp
, void *context
, uptr addr
) {
645 ScopedInErrorReport in_report
;
647 Printf("%s", d
.Warning());
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
);
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
;
663 Printf("%s", d
.Warning());
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
);
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
;
683 Printf("%s", d
.Warning());
685 u32 curr_tid
= GetCurrentTidOrInvalid();
686 Report("ERROR: AddressSanitizer: attempting double-free on %p in "
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
);
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
;
702 Printf("%s", d
.Warning());
704 u32 curr_tid
= GetCurrentTidOrInvalid();
705 Report("ERROR: AddressSanitizer: new-delete-type-mismatch on %p in "
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
);
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
;
725 Printf("%s", d
.Warning());
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
);
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
;
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
);
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
;
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());
771 DescribeHeapAddress(addr
, 1);
772 ReportErrorSummary("bad-malloc_usable_size", stack
);
775 void ReportSanitizerGetAllocatedSizeNotOwned(uptr addr
,
776 BufferedStackTrace
*stack
) {
777 ScopedInErrorReport in_report
;
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());
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
;
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());
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
;
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());
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"
831 beg
, end
, old_mid
, new_mid
);
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
;
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");
853 StackDepotGet(stack_id1
).Print();
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
867 ReportInvalidPointerPair(uptr pc
, uptr bp
, uptr sp
, uptr a1
, uptr a2
) {
868 ScopedInErrorReport in_report
;
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
);
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",
901 PrintZoneForPointer(addr
, zone_ptr
, zone_name
);
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",
912 PrintZoneForPointer(addr
, zone_ptr
, zone_name
);
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",
923 PrintZoneForPointer(addr
, zone_ptr
, zone_name
);
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
,
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
)
942 // If we are in the partial right redzone, look at the next shadow byte.
943 if (*shadow_addr
> 0 && *shadow_addr
< 128)
945 switch (*shadow_addr
) {
946 case kAsanHeapLeftRedzoneMagic
:
947 case kAsanHeapRightRedzoneMagic
:
948 case kAsanArrayCookieMagic
:
949 bug_descr
= "heap-buffer-overflow";
951 case kAsanHeapFreeMagic
:
952 bug_descr
= "heap-use-after-free";
954 case kAsanStackLeftRedzoneMagic
:
955 bug_descr
= "stack-buffer-underflow";
957 case kAsanInitializationOrderMagic
:
958 bug_descr
= "initialization-order-fiasco";
960 case kAsanStackMidRedzoneMagic
:
961 case kAsanStackRightRedzoneMagic
:
962 case kAsanStackPartialRedzoneMagic
:
963 bug_descr
= "stack-buffer-overflow";
965 case kAsanStackAfterReturnMagic
:
966 bug_descr
= "stack-use-after-return";
968 case kAsanUserPoisonedMemoryMagic
:
969 bug_descr
= "use-after-poison";
971 case kAsanContiguousContainerOOBMagic
:
972 bug_descr
= "container-overflow";
974 case kAsanStackUseAfterScopeMagic
:
975 bug_descr
= "stack-use-after-scope";
977 case kAsanGlobalRedzoneMagic
:
978 bug_descr
= "global-buffer-overflow";
980 case kAsanIntraObjectRedzone
:
981 bug_descr
= "intra-object-overflow";
986 ReportData report
= { pc
, sp
, bp
, addr
, (bool)is_write
, access_size
,
988 ScopedInErrorReport
in_report(&report
);
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();
999 Printf("%s%s of size %zu at %p thread T%d%s%s\n",
1001 access_size
? (is_write
? "WRITE" : "READ") : "ACCESS",
1002 access_size
, (void*)addr
, curr_tid
,
1003 ThreadNameWithParenthesis(curr_tid
, tname
, sizeof(tname
)),
1006 GET_STACK_TRACE_FATAL(pc
, bp
);
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
;
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
;
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
);
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() {}