1 //===-- asan_errors.cpp -----------------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file is a part of AddressSanitizer, an address sanity checker.
11 // ASan implementation for error structures.
12 //===----------------------------------------------------------------------===//
14 #include "asan_errors.h"
15 #include "asan_descriptions.h"
16 #include "asan_mapping.h"
17 #include "asan_report.h"
18 #include "asan_stack.h"
19 #include "sanitizer_common/sanitizer_stackdepot.h"
23 static void OnStackUnwind(const SignalContext
&sig
,
24 const void *callback_context
,
25 BufferedStackTrace
*stack
) {
26 bool fast
= common_flags()->fast_unwind_on_fatal
;
27 #if SANITIZER_FREEBSD || SANITIZER_NETBSD
28 // On FreeBSD the slow unwinding that leverages _Unwind_Backtrace()
29 // yields the call stack of the signal's handler and not of the code
30 // that raised the signal (as it does on Linux).
33 // Tests and maybe some users expect that scariness is going to be printed
34 // just before the stack. As only asan has scariness score we have no
35 // corresponding code in the sanitizer_common and we use this callback to
37 static_cast<const ScarinessScoreBase
*>(callback_context
)->Print();
38 stack
->Unwind(sig
.pc
, sig
.bp
, sig
.context
, fast
);
41 void ErrorDeadlySignal::Print() {
42 ReportDeadlySignal(signal
, tid
, &OnStackUnwind
, &scariness
);
45 void ErrorDoubleFree::Print() {
47 Printf("%s", d
.Error());
49 "ERROR: AddressSanitizer: attempting %s on %p in thread %s:\n",
50 scariness
.GetDescription(), addr_description
.addr
,
51 AsanThreadIdAndName(tid
).c_str());
52 Printf("%s", d
.Default());
54 GET_STACK_TRACE_FATAL(second_free_stack
->trace
[0],
55 second_free_stack
->top_frame_bp
);
57 addr_description
.Print();
58 ReportErrorSummary(scariness
.GetDescription(), &stack
);
61 void ErrorNewDeleteTypeMismatch::Print() {
63 Printf("%s", d
.Error());
65 "ERROR: AddressSanitizer: %s on %p in thread %s:\n",
66 scariness
.GetDescription(), addr_description
.addr
,
67 AsanThreadIdAndName(tid
).c_str());
68 Printf("%s object passed to delete has wrong type:\n", d
.Default());
69 if (delete_size
!= 0) {
71 " size of the allocated type: %zd bytes;\n"
72 " size of the deallocated type: %zd bytes.\n",
73 addr_description
.chunk_access
.chunk_size
, delete_size
);
75 const uptr user_alignment
=
76 addr_description
.chunk_access
.user_requested_alignment
;
77 if (delete_alignment
!= user_alignment
) {
78 char user_alignment_str
[32];
79 char delete_alignment_str
[32];
80 internal_snprintf(user_alignment_str
, sizeof(user_alignment_str
),
81 "%zd bytes", user_alignment
);
82 internal_snprintf(delete_alignment_str
, sizeof(delete_alignment_str
),
83 "%zd bytes", delete_alignment
);
84 static const char *kDefaultAlignment
= "default-aligned";
86 " alignment of the allocated type: %s;\n"
87 " alignment of the deallocated type: %s.\n",
88 user_alignment
> 0 ? user_alignment_str
: kDefaultAlignment
,
89 delete_alignment
> 0 ? delete_alignment_str
: kDefaultAlignment
);
91 CHECK_GT(free_stack
->size
, 0);
93 GET_STACK_TRACE_FATAL(free_stack
->trace
[0], free_stack
->top_frame_bp
);
95 addr_description
.Print();
96 ReportErrorSummary(scariness
.GetDescription(), &stack
);
98 "HINT: if you don't care about these errors you may set "
99 "ASAN_OPTIONS=new_delete_type_mismatch=0\n");
102 void ErrorFreeNotMalloced::Print() {
104 Printf("%s", d
.Error());
106 "ERROR: AddressSanitizer: attempting free on address "
107 "which was not malloc()-ed: %p in thread %s\n",
108 addr_description
.Address(), AsanThreadIdAndName(tid
).c_str());
109 Printf("%s", d
.Default());
110 CHECK_GT(free_stack
->size
, 0);
112 GET_STACK_TRACE_FATAL(free_stack
->trace
[0], free_stack
->top_frame_bp
);
114 addr_description
.Print();
115 ReportErrorSummary(scariness
.GetDescription(), &stack
);
118 void ErrorAllocTypeMismatch::Print() {
119 static const char *alloc_names
[] = {"INVALID", "malloc", "operator new",
121 static const char *dealloc_names
[] = {"INVALID", "free", "operator delete",
122 "operator delete []"};
123 CHECK_NE(alloc_type
, dealloc_type
);
125 Printf("%s", d
.Error());
126 Report("ERROR: AddressSanitizer: %s (%s vs %s) on %p\n",
127 scariness
.GetDescription(), alloc_names
[alloc_type
],
128 dealloc_names
[dealloc_type
], addr_description
.Address());
129 Printf("%s", d
.Default());
130 CHECK_GT(dealloc_stack
->size
, 0);
132 GET_STACK_TRACE_FATAL(dealloc_stack
->trace
[0], dealloc_stack
->top_frame_bp
);
134 addr_description
.Print();
135 ReportErrorSummary(scariness
.GetDescription(), &stack
);
137 "HINT: if you don't care about these errors you may set "
138 "ASAN_OPTIONS=alloc_dealloc_mismatch=0\n");
141 void ErrorMallocUsableSizeNotOwned::Print() {
143 Printf("%s", d
.Error());
145 "ERROR: AddressSanitizer: attempting to call malloc_usable_size() for "
146 "pointer which is not owned: %p\n",
147 addr_description
.Address());
148 Printf("%s", d
.Default());
150 addr_description
.Print();
151 ReportErrorSummary(scariness
.GetDescription(), stack
);
154 void ErrorSanitizerGetAllocatedSizeNotOwned::Print() {
156 Printf("%s", d
.Error());
158 "ERROR: AddressSanitizer: attempting to call "
159 "__sanitizer_get_allocated_size() for pointer which is not owned: %p\n",
160 addr_description
.Address());
161 Printf("%s", d
.Default());
163 addr_description
.Print();
164 ReportErrorSummary(scariness
.GetDescription(), stack
);
167 void ErrorCallocOverflow::Print() {
169 Printf("%s", d
.Error());
171 "ERROR: AddressSanitizer: calloc parameters overflow: count * size "
172 "(%zd * %zd) cannot be represented in type size_t (thread %s)\n",
173 count
, size
, AsanThreadIdAndName(tid
).c_str());
174 Printf("%s", d
.Default());
176 PrintHintAllocatorCannotReturnNull();
177 ReportErrorSummary(scariness
.GetDescription(), stack
);
180 void ErrorReallocArrayOverflow::Print() {
182 Printf("%s", d
.Error());
184 "ERROR: AddressSanitizer: reallocarray parameters overflow: count * size "
185 "(%zd * %zd) cannot be represented in type size_t (thread %s)\n",
186 count
, size
, AsanThreadIdAndName(tid
).c_str());
187 Printf("%s", d
.Default());
189 PrintHintAllocatorCannotReturnNull();
190 ReportErrorSummary(scariness
.GetDescription(), stack
);
193 void ErrorPvallocOverflow::Print() {
195 Printf("%s", d
.Error());
197 "ERROR: AddressSanitizer: pvalloc parameters overflow: size 0x%zx "
198 "rounded up to system page size 0x%zx cannot be represented in type "
199 "size_t (thread %s)\n",
200 size
, GetPageSizeCached(), AsanThreadIdAndName(tid
).c_str());
201 Printf("%s", d
.Default());
203 PrintHintAllocatorCannotReturnNull();
204 ReportErrorSummary(scariness
.GetDescription(), stack
);
207 void ErrorInvalidAllocationAlignment::Print() {
209 Printf("%s", d
.Error());
211 "ERROR: AddressSanitizer: invalid allocation alignment: %zd, "
212 "alignment must be a power of two (thread %s)\n",
213 alignment
, AsanThreadIdAndName(tid
).c_str());
214 Printf("%s", d
.Default());
216 PrintHintAllocatorCannotReturnNull();
217 ReportErrorSummary(scariness
.GetDescription(), stack
);
220 void ErrorInvalidAlignedAllocAlignment::Print() {
222 Printf("%s", d
.Error());
224 Report("ERROR: AddressSanitizer: invalid alignment requested in "
225 "aligned_alloc: %zd, alignment must be a power of two and the "
226 "requested size 0x%zx must be a multiple of alignment "
227 "(thread %s)\n", alignment
, size
, AsanThreadIdAndName(tid
).c_str());
229 Report("ERROR: AddressSanitizer: invalid alignment requested in "
230 "aligned_alloc: %zd, the requested size 0x%zx must be a multiple of "
231 "alignment (thread %s)\n", alignment
, size
,
232 AsanThreadIdAndName(tid
).c_str());
234 Printf("%s", d
.Default());
236 PrintHintAllocatorCannotReturnNull();
237 ReportErrorSummary(scariness
.GetDescription(), stack
);
240 void ErrorInvalidPosixMemalignAlignment::Print() {
242 Printf("%s", d
.Error());
244 "ERROR: AddressSanitizer: invalid alignment requested in posix_memalign: "
245 "%zd, alignment must be a power of two and a multiple of sizeof(void*) "
246 "== %zd (thread %s)\n",
247 alignment
, sizeof(void*), AsanThreadIdAndName(tid
).c_str()); // NOLINT
248 Printf("%s", d
.Default());
250 PrintHintAllocatorCannotReturnNull();
251 ReportErrorSummary(scariness
.GetDescription(), stack
);
254 void ErrorAllocationSizeTooBig::Print() {
256 Printf("%s", d
.Error());
258 "ERROR: AddressSanitizer: requested allocation size 0x%zx (0x%zx after "
259 "adjustments for alignment, red zones etc.) exceeds maximum supported "
260 "size of 0x%zx (thread %s)\n",
261 user_size
, total_size
, max_size
, AsanThreadIdAndName(tid
).c_str());
262 Printf("%s", d
.Default());
264 PrintHintAllocatorCannotReturnNull();
265 ReportErrorSummary(scariness
.GetDescription(), stack
);
268 void ErrorRssLimitExceeded::Print() {
270 Printf("%s", d
.Error());
272 "ERROR: AddressSanitizer: specified RSS limit exceeded, currently set to "
273 "soft_rss_limit_mb=%zd\n", common_flags()->soft_rss_limit_mb
);
274 Printf("%s", d
.Default());
276 PrintHintAllocatorCannotReturnNull();
277 ReportErrorSummary(scariness
.GetDescription(), stack
);
280 void ErrorOutOfMemory::Print() {
282 Printf("%s", d
.Error());
284 "ERROR: AddressSanitizer: allocator is out of memory trying to allocate "
285 "0x%zx bytes\n", requested_size
);
286 Printf("%s", d
.Default());
288 PrintHintAllocatorCannotReturnNull();
289 ReportErrorSummary(scariness
.GetDescription(), stack
);
292 void ErrorStringFunctionMemoryRangesOverlap::Print() {
295 internal_snprintf(bug_type
, sizeof(bug_type
), "%s-param-overlap", function
);
296 Printf("%s", d
.Error());
298 "ERROR: AddressSanitizer: %s: memory ranges [%p,%p) and [%p, %p) "
300 bug_type
, addr1_description
.Address(),
301 addr1_description
.Address() + length1
, addr2_description
.Address(),
302 addr2_description
.Address() + length2
);
303 Printf("%s", d
.Default());
306 addr1_description
.Print();
307 addr2_description
.Print();
308 ReportErrorSummary(bug_type
, stack
);
311 void ErrorStringFunctionSizeOverflow::Print() {
313 Printf("%s", d
.Error());
314 Report("ERROR: AddressSanitizer: %s: (size=%zd)\n",
315 scariness
.GetDescription(), size
);
316 Printf("%s", d
.Default());
319 addr_description
.Print();
320 ReportErrorSummary(scariness
.GetDescription(), stack
);
323 void ErrorBadParamsToAnnotateContiguousContainer::Print() {
325 "ERROR: AddressSanitizer: bad parameters to "
326 "__sanitizer_annotate_contiguous_container:\n"
331 beg
, end
, old_mid
, new_mid
);
332 uptr granularity
= SHADOW_GRANULARITY
;
333 if (!IsAligned(beg
, granularity
))
334 Report("ERROR: beg is not aligned by %d\n", granularity
);
336 ReportErrorSummary(scariness
.GetDescription(), stack
);
339 void ErrorODRViolation::Print() {
341 Printf("%s", d
.Error());
342 Report("ERROR: AddressSanitizer: %s (%p):\n", scariness
.GetDescription(),
344 Printf("%s", d
.Default());
345 InternalScopedString
g1_loc(256), g2_loc(256);
346 PrintGlobalLocation(&g1_loc
, global1
);
347 PrintGlobalLocation(&g2_loc
, global2
);
348 Printf(" [1] size=%zd '%s' %s\n", global1
.size
,
349 MaybeDemangleGlobalName(global1
.name
), g1_loc
.data());
350 Printf(" [2] size=%zd '%s' %s\n", global2
.size
,
351 MaybeDemangleGlobalName(global2
.name
), g2_loc
.data());
352 if (stack_id1
&& stack_id2
) {
353 Printf("These globals were registered at these points:\n");
355 StackDepotGet(stack_id1
).Print();
357 StackDepotGet(stack_id2
).Print();
360 "HINT: if you don't care about these errors you may set "
361 "ASAN_OPTIONS=detect_odr_violation=0\n");
362 InternalScopedString
error_msg(256);
363 error_msg
.append("%s: global '%s' at %s", scariness
.GetDescription(),
364 MaybeDemangleGlobalName(global1
.name
), g1_loc
.data());
365 ReportErrorSummary(error_msg
.data());
368 void ErrorInvalidPointerPair::Print() {
370 Printf("%s", d
.Error());
371 Report("ERROR: AddressSanitizer: %s: %p %p\n", scariness
.GetDescription(),
372 addr1_description
.Address(), addr2_description
.Address());
373 Printf("%s", d
.Default());
374 GET_STACK_TRACE_FATAL(pc
, bp
);
376 addr1_description
.Print();
377 addr2_description
.Print();
378 ReportErrorSummary(scariness
.GetDescription(), &stack
);
381 static bool AdjacentShadowValuesAreFullyPoisoned(u8
*s
) {
382 return s
[-1] > 127 && s
[1] > 127;
385 ErrorGeneric::ErrorGeneric(u32 tid
, uptr pc_
, uptr bp_
, uptr sp_
, uptr addr
,
386 bool is_write_
, uptr access_size_
)
388 addr_description(addr
, access_size_
, /*shouldLockThreadRegistry=*/false),
392 access_size(access_size_
),
397 if (access_size
<= 9) {
398 char desr
[] = "?-byte";
399 desr
[0] = '0' + access_size
;
400 scariness
.Scare(access_size
+ access_size
/ 2, desr
);
401 } else if (access_size
>= 10) {
402 scariness
.Scare(15, "multi-byte");
404 is_write
? scariness
.Scare(20, "write") : scariness
.Scare(1, "read");
406 // Determine the error type.
407 bug_descr
= "unknown-crash";
408 if (AddrIsInMem(addr
)) {
409 u8
*shadow_addr
= (u8
*)MemToShadow(addr
);
410 // If we are accessing 16 bytes, look at the second shadow byte.
411 if (*shadow_addr
== 0 && access_size
> SHADOW_GRANULARITY
) shadow_addr
++;
412 // If we are in the partial right redzone, look at the next shadow byte.
413 if (*shadow_addr
> 0 && *shadow_addr
< 128) shadow_addr
++;
414 bool far_from_bounds
= false;
415 shadow_val
= *shadow_addr
;
416 int bug_type_score
= 0;
417 // For use-after-frees reads are almost as bad as writes.
418 int read_after_free_bonus
= 0;
419 switch (shadow_val
) {
420 case kAsanHeapLeftRedzoneMagic
:
421 case kAsanArrayCookieMagic
:
422 bug_descr
= "heap-buffer-overflow";
424 far_from_bounds
= AdjacentShadowValuesAreFullyPoisoned(shadow_addr
);
426 case kAsanHeapFreeMagic
:
427 bug_descr
= "heap-use-after-free";
429 if (!is_write
) read_after_free_bonus
= 18;
431 case kAsanStackLeftRedzoneMagic
:
432 bug_descr
= "stack-buffer-underflow";
434 far_from_bounds
= AdjacentShadowValuesAreFullyPoisoned(shadow_addr
);
436 case kAsanInitializationOrderMagic
:
437 bug_descr
= "initialization-order-fiasco";
440 case kAsanStackMidRedzoneMagic
:
441 case kAsanStackRightRedzoneMagic
:
442 bug_descr
= "stack-buffer-overflow";
444 far_from_bounds
= AdjacentShadowValuesAreFullyPoisoned(shadow_addr
);
446 case kAsanStackAfterReturnMagic
:
447 bug_descr
= "stack-use-after-return";
449 if (!is_write
) read_after_free_bonus
= 18;
451 case kAsanUserPoisonedMemoryMagic
:
452 bug_descr
= "use-after-poison";
455 case kAsanContiguousContainerOOBMagic
:
456 bug_descr
= "container-overflow";
459 case kAsanStackUseAfterScopeMagic
:
460 bug_descr
= "stack-use-after-scope";
463 case kAsanGlobalRedzoneMagic
:
464 bug_descr
= "global-buffer-overflow";
466 far_from_bounds
= AdjacentShadowValuesAreFullyPoisoned(shadow_addr
);
468 case kAsanIntraObjectRedzone
:
469 bug_descr
= "intra-object-overflow";
472 case kAsanAllocaLeftMagic
:
473 case kAsanAllocaRightMagic
:
474 bug_descr
= "dynamic-stack-buffer-overflow";
476 far_from_bounds
= AdjacentShadowValuesAreFullyPoisoned(shadow_addr
);
479 scariness
.Scare(bug_type_score
+ read_after_free_bonus
, bug_descr
);
480 if (far_from_bounds
) scariness
.Scare(10, "far-from-bounds");
485 static void PrintContainerOverflowHint() {
486 Printf("HINT: if you don't care about these errors you may set "
487 "ASAN_OPTIONS=detect_container_overflow=0.\n"
488 "If you suspect a false positive see also: "
489 "https://github.com/google/sanitizers/wiki/"
490 "AddressSanitizerContainerOverflow.\n");
493 static void PrintShadowByte(InternalScopedString
*str
, const char *before
,
494 u8 byte
, const char *after
= "\n") {
495 PrintMemoryByte(str
, before
, byte
, /*in_shadow*/true, after
);
498 static void PrintLegend(InternalScopedString
*str
) {
500 "Shadow byte legend (one shadow byte represents %d "
501 "application bytes):\n",
502 (int)SHADOW_GRANULARITY
);
503 PrintShadowByte(str
, " Addressable: ", 0);
504 str
->append(" Partially addressable: ");
505 for (u8 i
= 1; i
< SHADOW_GRANULARITY
; i
++) PrintShadowByte(str
, "", i
, " ");
507 PrintShadowByte(str
, " Heap left redzone: ",
508 kAsanHeapLeftRedzoneMagic
);
509 PrintShadowByte(str
, " Freed heap region: ", kAsanHeapFreeMagic
);
510 PrintShadowByte(str
, " Stack left redzone: ",
511 kAsanStackLeftRedzoneMagic
);
512 PrintShadowByte(str
, " Stack mid redzone: ",
513 kAsanStackMidRedzoneMagic
);
514 PrintShadowByte(str
, " Stack right redzone: ",
515 kAsanStackRightRedzoneMagic
);
516 PrintShadowByte(str
, " Stack after return: ",
517 kAsanStackAfterReturnMagic
);
518 PrintShadowByte(str
, " Stack use after scope: ",
519 kAsanStackUseAfterScopeMagic
);
520 PrintShadowByte(str
, " Global redzone: ", kAsanGlobalRedzoneMagic
);
521 PrintShadowByte(str
, " Global init order: ",
522 kAsanInitializationOrderMagic
);
523 PrintShadowByte(str
, " Poisoned by user: ",
524 kAsanUserPoisonedMemoryMagic
);
525 PrintShadowByte(str
, " Container overflow: ",
526 kAsanContiguousContainerOOBMagic
);
527 PrintShadowByte(str
, " Array cookie: ",
528 kAsanArrayCookieMagic
);
529 PrintShadowByte(str
, " Intra object redzone: ",
530 kAsanIntraObjectRedzone
);
531 PrintShadowByte(str
, " ASan internal: ", kAsanInternalHeapMagic
);
532 PrintShadowByte(str
, " Left alloca redzone: ", kAsanAllocaLeftMagic
);
533 PrintShadowByte(str
, " Right alloca redzone: ", kAsanAllocaRightMagic
);
534 PrintShadowByte(str
, " Shadow gap: ", kAsanShadowGap
);
537 static void PrintShadowBytes(InternalScopedString
*str
, const char *before
,
538 u8
*bytes
, u8
*guilty
, uptr n
) {
540 if (before
) str
->append("%s%p:", before
, bytes
);
541 for (uptr i
= 0; i
< n
; i
++) {
544 p
== guilty
? "[" : (p
- 1 == guilty
&& i
!= 0) ? "" : " ";
545 const char *after
= p
== guilty
? "]" : "";
546 PrintShadowByte(str
, before
, *p
, after
);
551 static void PrintShadowMemoryForAddress(uptr addr
) {
552 if (!AddrIsInMem(addr
)) return;
553 uptr shadow_addr
= MemToShadow(addr
);
554 const uptr n_bytes_per_row
= 16;
555 uptr aligned_shadow
= shadow_addr
& ~(n_bytes_per_row
- 1);
556 InternalScopedString
str(4096 * 8);
557 str
.append("Shadow bytes around the buggy address:\n");
558 for (int i
= -5; i
<= 5; i
++) {
559 uptr row_shadow_addr
= aligned_shadow
+ i
* n_bytes_per_row
;
560 // Skip rows that would be outside the shadow range. This can happen when
561 // the user address is near the bottom, top, or shadow gap of the address
563 if (!AddrIsInShadow(row_shadow_addr
)) continue;
564 const char *prefix
= (i
== 0) ? "=>" : " ";
565 PrintShadowBytes(&str
, prefix
, (u8
*)row_shadow_addr
, (u8
*)shadow_addr
,
568 if (flags()->print_legend
) PrintLegend(&str
);
569 Printf("%s", str
.data());
572 void ErrorGeneric::Print() {
574 Printf("%s", d
.Error());
575 uptr addr
= addr_description
.Address();
576 Report("ERROR: AddressSanitizer: %s on address %p at pc %p bp %p sp %p\n",
577 bug_descr
, (void *)addr
, pc
, bp
, sp
);
578 Printf("%s", d
.Default());
580 Printf("%s%s of size %zu at %p thread %s%s\n", d
.Access(),
581 access_size
? (is_write
? "WRITE" : "READ") : "ACCESS", access_size
,
582 (void *)addr
, AsanThreadIdAndName(tid
).c_str(), d
.Default());
585 GET_STACK_TRACE_FATAL(pc
, bp
);
588 // Pass bug_descr because we have a special case for
589 // initialization-order-fiasco
590 addr_description
.Print(bug_descr
);
591 if (shadow_val
== kAsanContiguousContainerOOBMagic
)
592 PrintContainerOverflowHint();
593 ReportErrorSummary(bug_descr
, &stack
);
594 PrintShadowMemoryForAddress(addr
);
597 } // namespace __asan