1//===-- asan_errors.cpp -----------------------------------------*- C++ -*-===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
9// This file is a part of AddressSanitizer, an address sanity checker.
10//
11// ASan implementation for error structures.
12//===----------------------------------------------------------------------===//
13
14#include "asan_errors.h"
15
16#include "asan_descriptions.h"
17#include "asan_mapping.h"
18#include "asan_poisoning.h"
19#include "asan_report.h"
20#include "asan_stack.h"
21#include "sanitizer_common/sanitizer_stackdepot.h"
22
23namespace __asan {
24
25static void OnStackUnwind(const SignalContext &sig,
26 const void *callback_context,
27 BufferedStackTrace *stack) {
28 bool fast = common_flags()->fast_unwind_on_fatal;
29#if SANITIZER_FREEBSD || SANITIZER_NETBSD
30 // On FreeBSD the slow unwinding that leverages _Unwind_Backtrace()
31 // yields the call stack of the signal's handler and not of the code
32 // that raised the signal (as it does on Linux).
33 fast = true;
34#endif
35 // Tests and maybe some users expect that scariness is going to be printed
36 // just before the stack. As only asan has scariness score we have no
37 // corresponding code in the sanitizer_common and we use this callback to
38 // print it.
39 static_cast<const ScarinessScoreBase *>(callback_context)->Print();
40 stack->Unwind(pc: StackTrace::GetNextInstructionPc(pc: sig.pc), bp: sig.bp, context: sig.context,
41 request_fast: fast);
42}
43
44void ErrorDeadlySignal::Print() {
45 ReportDeadlySignal(sig: signal, tid, unwind: &OnStackUnwind, unwind_context: &scariness);
46}
47
48void ErrorDoubleFree::Print() {
49 Decorator d;
50 Printf(format: "%s", d.Error());
51 Report(format: "ERROR: AddressSanitizer: attempting %s on %p in thread %s:\n",
52 scariness.GetDescription(), (void *)addr_description.addr,
53 AsanThreadIdAndName(tid).c_str());
54 Printf(format: "%s", d.Default());
55 scariness.Print();
56 GET_STACK_TRACE_FATAL(second_free_stack->trace[0],
57 second_free_stack->top_frame_bp);
58 stack.Print();
59 addr_description.Print();
60 ReportErrorSummary(error_type: scariness.GetDescription(), trace: &stack);
61}
62
63void ErrorNewDeleteTypeMismatch::Print() {
64 Decorator d;
65 Printf(format: "%s", d.Error());
66 Report(format: "ERROR: AddressSanitizer: %s on %p in thread %s:\n",
67 scariness.GetDescription(), (void *)addr_description.addr,
68 AsanThreadIdAndName(tid).c_str());
69 Printf(format: "%s object passed to delete has wrong type:\n", d.Default());
70 if (delete_size != 0) {
71 Printf(
72 format: " size of the allocated type: %zd bytes;\n"
73 " size of the deallocated type: %zd bytes.\n",
74 addr_description.chunk_access.chunk_size, delete_size);
75 }
76 const uptr user_alignment =
77 addr_description.chunk_access.user_requested_alignment;
78 if (delete_alignment != user_alignment) {
79 char user_alignment_str[32];
80 char delete_alignment_str[32];
81 internal_snprintf(buffer: user_alignment_str, length: sizeof(user_alignment_str),
82 format: "%zd bytes", user_alignment);
83 internal_snprintf(buffer: delete_alignment_str, length: sizeof(delete_alignment_str),
84 format: "%zd bytes", delete_alignment);
85 static const char *kDefaultAlignment = "default-aligned";
86 Printf(
87 format: " alignment of the allocated type: %s;\n"
88 " alignment of the deallocated type: %s.\n",
89 user_alignment > 0 ? user_alignment_str : kDefaultAlignment,
90 delete_alignment > 0 ? delete_alignment_str : kDefaultAlignment);
91 }
92 CHECK_GT(free_stack->size, 0);
93 scariness.Print();
94 GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp);
95 stack.Print();
96 addr_description.Print();
97 ReportErrorSummary(error_type: scariness.GetDescription(), trace: &stack);
98 Report(
99 format: "HINT: if you don't care about these errors you may set "
100 "ASAN_OPTIONS=new_delete_type_mismatch=0\n");
101}
102
103void ErrorFreeSizeMismatch::Print() {
104 Decorator d;
105 Printf(format: "%s", d.Error());
106 Report(format: "ERROR: AddressSanitizer: %s on %p in thread %s:\n",
107 scariness.GetDescription(), (void*)addr_description.addr,
108 AsanThreadIdAndName(tid).c_str());
109 Printf(format: "%s object passed to %s has wrong size or alignment:\n", d.Default(),
110 (isFreeAlignedSized() ? "free_aligned_sized" : "free_sized"));
111 if (delete_size != 0) {
112 Printf(
113 format: " size of the allocation: %zd bytes;\n"
114 " size of the deallocation: %zd bytes.\n",
115 addr_description.chunk_access.chunk_size, delete_size);
116 }
117 const uptr user_alignment =
118 addr_description.chunk_access.user_requested_alignment;
119 if (isFreeAlignedSized() && delete_alignment != user_alignment) {
120 char user_alignment_str[32];
121 char delete_alignment_str[32];
122 internal_snprintf(buffer: user_alignment_str, length: sizeof(user_alignment_str),
123 format: "%zd bytes", user_alignment);
124 internal_snprintf(buffer: delete_alignment_str, length: sizeof(delete_alignment_str),
125 format: "%zd bytes", delete_alignment);
126 static const char* kDefaultAlignment = "default-aligned";
127 Printf(
128 format: " alignment of the allocation: %s;\n"
129 " alignment of the deallocation: %s.\n",
130 user_alignment > 0 ? user_alignment_str : kDefaultAlignment,
131 delete_alignment > 0 ? delete_alignment_str : kDefaultAlignment);
132 }
133 CHECK_GT(free_stack->size, 0);
134 scariness.Print();
135 GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp);
136 stack.Print();
137 addr_description.Print();
138 ReportErrorSummary(error_type: scariness.GetDescription(), trace: &stack);
139 Report(
140 format: "HINT: if you don't care about these errors you may set "
141 "ASAN_OPTIONS=free_size_mismatch=0\n");
142}
143
144void ErrorFreeNotMalloced::Print() {
145 Decorator d;
146 Printf(format: "%s", d.Error());
147 Report(
148 format: "ERROR: AddressSanitizer: attempting free on address "
149 "which was not malloc()-ed: %p in thread %s\n",
150 (void *)addr_description.Address(), AsanThreadIdAndName(tid).c_str());
151 Printf(format: "%s", d.Default());
152 CHECK_GT(free_stack->size, 0);
153 scariness.Print();
154 GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp);
155 stack.Print();
156 addr_description.Print();
157 ReportErrorSummary(error_type: scariness.GetDescription(), trace: &stack);
158}
159
160void ErrorAllocTypeMismatch::Print() {
161 static const char *alloc_names[] = {"INVALID", "malloc", "operator new",
162 "operator new []"};
163 static const char *dealloc_names[] = {"INVALID", "free", "operator delete",
164 "operator delete []"};
165 CHECK_NE(alloc_type, dealloc_type);
166 Decorator d;
167 Printf(format: "%s", d.Error());
168 Report(format: "ERROR: AddressSanitizer: %s (%s vs %s) on %p\n",
169 scariness.GetDescription(), alloc_names[alloc_type],
170 dealloc_names[dealloc_type], (void *)addr_description.Address());
171 Printf(format: "%s", d.Default());
172 CHECK_GT(dealloc_stack->size, 0);
173 scariness.Print();
174 GET_STACK_TRACE_FATAL(dealloc_stack->trace[0], dealloc_stack->top_frame_bp);
175 stack.Print();
176 addr_description.Print();
177 ReportErrorSummary(error_type: scariness.GetDescription(), trace: &stack);
178 Report(
179 format: "HINT: if you don't care about these errors you may set "
180 "ASAN_OPTIONS=alloc_dealloc_mismatch=0\n");
181}
182
183void ErrorMallocUsableSizeNotOwned::Print() {
184 Decorator d;
185 Printf(format: "%s", d.Error());
186 Report(
187 format: "ERROR: AddressSanitizer: attempting to call malloc_usable_size() for "
188 "pointer which is not owned: %p\n",
189 (void *)addr_description.Address());
190 Printf(format: "%s", d.Default());
191 stack->Print();
192 addr_description.Print();
193 ReportErrorSummary(error_type: scariness.GetDescription(), trace: stack);
194}
195
196void ErrorSanitizerGetAllocatedSizeNotOwned::Print() {
197 Decorator d;
198 Printf(format: "%s", d.Error());
199 Report(
200 format: "ERROR: AddressSanitizer: attempting to call "
201 "__sanitizer_get_allocated_size() for pointer which is not owned: %p\n",
202 (void *)addr_description.Address());
203 Printf(format: "%s", d.Default());
204 stack->Print();
205 addr_description.Print();
206 ReportErrorSummary(error_type: scariness.GetDescription(), trace: stack);
207}
208
209void ErrorCallocOverflow::Print() {
210 Decorator d;
211 Printf(format: "%s", d.Error());
212 Report(
213 format: "ERROR: AddressSanitizer: calloc parameters overflow: count * size "
214 "(%zd * %zd) cannot be represented in type size_t (thread %s)\n",
215 count, size, AsanThreadIdAndName(tid).c_str());
216 Printf(format: "%s", d.Default());
217 stack->Print();
218 PrintHintAllocatorCannotReturnNull();
219 ReportErrorSummary(error_type: scariness.GetDescription(), trace: stack);
220}
221
222void ErrorReallocArrayOverflow::Print() {
223 Decorator d;
224 Printf(format: "%s", d.Error());
225 Report(
226 format: "ERROR: AddressSanitizer: reallocarray parameters overflow: count * size "
227 "(%zd * %zd) cannot be represented in type size_t (thread %s)\n",
228 count, size, AsanThreadIdAndName(tid).c_str());
229 Printf(format: "%s", d.Default());
230 stack->Print();
231 PrintHintAllocatorCannotReturnNull();
232 ReportErrorSummary(error_type: scariness.GetDescription(), trace: stack);
233}
234
235void ErrorPvallocOverflow::Print() {
236 Decorator d;
237 Printf(format: "%s", d.Error());
238 Report(
239 format: "ERROR: AddressSanitizer: pvalloc parameters overflow: size 0x%zx "
240 "rounded up to system page size 0x%zx cannot be represented in type "
241 "size_t (thread %s)\n",
242 size, GetPageSizeCached(), AsanThreadIdAndName(tid).c_str());
243 Printf(format: "%s", d.Default());
244 stack->Print();
245 PrintHintAllocatorCannotReturnNull();
246 ReportErrorSummary(error_type: scariness.GetDescription(), trace: stack);
247}
248
249void ErrorInvalidAllocationAlignment::Print() {
250 Decorator d;
251 Printf(format: "%s", d.Error());
252 Report(
253 format: "ERROR: AddressSanitizer: invalid allocation alignment: %zd, "
254 "alignment must be a power of two (thread %s)\n",
255 alignment, AsanThreadIdAndName(tid).c_str());
256 Printf(format: "%s", d.Default());
257 stack->Print();
258 PrintHintAllocatorCannotReturnNull();
259 ReportErrorSummary(error_type: scariness.GetDescription(), trace: stack);
260}
261
262void ErrorInvalidAlignedAllocAlignment::Print() {
263 Decorator d;
264 Printf(format: "%s", d.Error());
265#if SANITIZER_POSIX
266 Report(format: "ERROR: AddressSanitizer: invalid alignment requested in "
267 "aligned_alloc: %zd, alignment must be a power of two and the "
268 "requested size 0x%zx must be a multiple of alignment "
269 "(thread %s)\n", alignment, size, AsanThreadIdAndName(tid).c_str());
270#else
271 Report("ERROR: AddressSanitizer: invalid alignment requested in "
272 "aligned_alloc: %zd, the requested size 0x%zx must be a multiple of "
273 "alignment (thread %s)\n", alignment, size,
274 AsanThreadIdAndName(tid).c_str());
275#endif
276 Printf(format: "%s", d.Default());
277 stack->Print();
278 PrintHintAllocatorCannotReturnNull();
279 ReportErrorSummary(error_type: scariness.GetDescription(), trace: stack);
280}
281
282void ErrorInvalidPosixMemalignAlignment::Print() {
283 Decorator d;
284 Printf(format: "%s", d.Error());
285 Report(
286 format: "ERROR: AddressSanitizer: invalid alignment requested in posix_memalign: "
287 "%zd, alignment must be a power of two and a multiple of sizeof(void*) "
288 "== %zd (thread %s)\n",
289 alignment, sizeof(void *), AsanThreadIdAndName(tid).c_str());
290 Printf(format: "%s", d.Default());
291 stack->Print();
292 PrintHintAllocatorCannotReturnNull();
293 ReportErrorSummary(error_type: scariness.GetDescription(), trace: stack);
294}
295
296void ErrorAllocationSizeTooBig::Print() {
297 Decorator d;
298 Printf(format: "%s", d.Error());
299 Report(
300 format: "ERROR: AddressSanitizer: requested allocation size 0x%zx (0x%zx after "
301 "adjustments for alignment, red zones etc.) exceeds maximum supported "
302 "size of 0x%zx (thread %s)\n",
303 user_size, total_size, max_size, AsanThreadIdAndName(tid).c_str());
304 Printf(format: "%s", d.Default());
305 stack->Print();
306 PrintHintAllocatorCannotReturnNull();
307 ReportErrorSummary(error_type: scariness.GetDescription(), trace: stack);
308}
309
310void ErrorRssLimitExceeded::Print() {
311 Decorator d;
312 Printf(format: "%s", d.Error());
313 Report(
314 format: "ERROR: AddressSanitizer: specified RSS limit exceeded, currently set to "
315 "soft_rss_limit_mb=%zd\n", common_flags()->soft_rss_limit_mb);
316 Printf(format: "%s", d.Default());
317 stack->Print();
318 PrintHintAllocatorCannotReturnNull();
319 ReportErrorSummary(error_type: scariness.GetDescription(), trace: stack);
320}
321
322void ErrorOutOfMemory::Print() {
323 Decorator d;
324 Printf(format: "%s", d.Error());
325 ERROR_OOM("allocator is trying to allocate 0x%zx bytes\n", requested_size);
326 Printf(format: "%s", d.Default());
327 stack->Print();
328 PrintHintAllocatorCannotReturnNull();
329 ReportErrorSummary(error_type: scariness.GetDescription(), trace: stack);
330}
331
332void ErrorStringFunctionMemoryRangesOverlap::Print() {
333 Decorator d;
334 char bug_type[100];
335 internal_snprintf(buffer: bug_type, length: sizeof(bug_type), format: "%s-param-overlap", function);
336 Printf(format: "%s", d.Error());
337 Report(
338 format: "ERROR: AddressSanitizer: %s: memory ranges [%p,%p) and [%p, %p) "
339 "overlap\n",
340 bug_type, (void *)addr1_description.Address(),
341 (void *)(addr1_description.Address() + length1),
342 (void *)addr2_description.Address(),
343 (void *)(addr2_description.Address() + length2));
344 Printf(format: "%s", d.Default());
345 scariness.Print();
346 stack->Print();
347 addr1_description.Print();
348 addr2_description.Print();
349 ReportErrorSummary(error_type: bug_type, trace: stack);
350}
351
352void ErrorStringFunctionSizeOverflow::Print() {
353 Decorator d;
354 Printf(format: "%s", d.Error());
355 Report(format: "ERROR: AddressSanitizer: %s: (size=%zd)\n",
356 scariness.GetDescription(), size);
357 Printf(format: "%s", d.Default());
358 scariness.Print();
359 stack->Print();
360 addr_description.Print();
361 ReportErrorSummary(error_type: scariness.GetDescription(), trace: stack);
362}
363
364void ErrorBadParamsToAnnotateContiguousContainer::Print() {
365 Report(
366 format: "ERROR: AddressSanitizer: bad parameters to "
367 "__sanitizer_annotate_contiguous_container:\n"
368 " beg : %p\n"
369 " end : %p\n"
370 " old_mid : %p\n"
371 " new_mid : %p\n",
372 (void *)beg, (void *)end, (void *)old_mid, (void *)new_mid);
373 stack->Print();
374 ReportErrorSummary(error_type: scariness.GetDescription(), trace: stack);
375}
376
377void ErrorBadParamsToAnnotateDoubleEndedContiguousContainer::Print() {
378 Report(
379 format: "ERROR: AddressSanitizer: bad parameters to "
380 "__sanitizer_annotate_double_ended_contiguous_container:\n"
381 " storage_beg : %p\n"
382 " storage_end : %p\n"
383 " old_container_beg : %p\n"
384 " old_container_end : %p\n"
385 " new_container_beg : %p\n"
386 " new_container_end : %p\n",
387 (void *)storage_beg, (void *)storage_end, (void *)old_container_beg,
388 (void *)old_container_end, (void *)new_container_beg,
389 (void *)new_container_end);
390 stack->Print();
391 ReportErrorSummary(error_type: scariness.GetDescription(), trace: stack);
392}
393
394void ErrorBadParamsToCopyContiguousContainerAnnotations::Print() {
395 Report(
396 format: "ERROR: AddressSanitizer: bad parameters to "
397 "__sanitizer_copy_contiguous_container_annotations:\n"
398 " src_storage_beg : %p\n"
399 " src_storage_end : %p\n"
400 " dst_storage_beg : %p\n"
401 " new_storage_end : %p\n",
402 (void *)old_storage_beg, (void *)old_storage_end, (void *)new_storage_beg,
403 (void *)new_storage_end);
404 stack->Print();
405 ReportErrorSummary(error_type: scariness.GetDescription(), trace: stack);
406}
407
408void ErrorODRViolation::Print() {
409 Decorator d;
410 Printf(format: "%s", d.Error());
411 Report(format: "ERROR: AddressSanitizer: %s (%p):\n", scariness.GetDescription(),
412 (void *)global1.beg);
413 Printf(format: "%s", d.Default());
414 InternalScopedString g1_loc;
415 InternalScopedString g2_loc;
416 PrintGlobalLocation(str: &g1_loc, g: global1, /*print_module_name=*/true);
417 PrintGlobalLocation(str: &g2_loc, g: global2, /*print_module_name=*/true);
418 Printf(format: " [1] size=%zd '%s' %s\n", global1.size,
419 MaybeDemangleGlobalName(name: global1.name), g1_loc.data());
420 Printf(format: " [2] size=%zd '%s' %s\n", global2.size,
421 MaybeDemangleGlobalName(name: global2.name), g2_loc.data());
422 if (stack_id1 && stack_id2) {
423 Printf(format: "These globals were registered at these points:\n");
424 Printf(format: " [1]:\n");
425 StackDepotGet(id: stack_id1).Print();
426 Printf(format: " [2]:\n");
427 StackDepotGet(id: stack_id2).Print();
428 }
429 Report(
430 format: "HINT: if you don't care about these errors you may set "
431 "ASAN_OPTIONS=detect_odr_violation=0\n");
432 InternalScopedString error_msg;
433 error_msg.AppendF(format: "%s: global '%s' at %s", scariness.GetDescription(),
434 MaybeDemangleGlobalName(name: global1.name), g1_loc.data());
435 ReportErrorSummary(error_message: error_msg.data());
436}
437
438void ErrorInvalidPointerPair::Print() {
439 Decorator d;
440 Printf(format: "%s", d.Error());
441 Report(format: "ERROR: AddressSanitizer: %s: %p %p\n", scariness.GetDescription(),
442 (void *)addr1_description.Address(),
443 (void *)addr2_description.Address());
444 Printf(format: "%s", d.Default());
445 GET_STACK_TRACE_FATAL(pc, bp);
446 stack.Print();
447 addr1_description.Print();
448 addr2_description.Print();
449 ReportErrorSummary(error_type: scariness.GetDescription(), trace: &stack);
450}
451
452static bool AdjacentShadowValuesAreFullyPoisoned(u8 *s) {
453 return s[-1] > 127 && s[1] > 127;
454}
455
456ErrorGeneric::ErrorGeneric(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr addr,
457 bool is_write_, uptr access_size_)
458 : ErrorBase(tid),
459 addr_description(addr, access_size_, /*shouldLockThreadRegistry=*/false),
460 pc(pc_),
461 bp(bp_),
462 sp(sp_),
463 access_size(access_size_),
464 is_write(is_write_),
465 shadow_val(0) {
466 scariness.Clear();
467 if (access_size) {
468 if (access_size <= 9) {
469 char desr[] = "?-byte";
470 desr[0] = '0' + access_size;
471 scariness.Scare(add_to_score: access_size + access_size / 2, reason: desr);
472 } else if (access_size >= 10) {
473 scariness.Scare(add_to_score: 15, reason: "multi-byte");
474 }
475 is_write ? scariness.Scare(add_to_score: 20, reason: "write") : scariness.Scare(add_to_score: 1, reason: "read");
476
477 // Determine the error type.
478 bug_descr = "unknown-crash";
479 if (AddrIsInMem(a: addr)) {
480 u8 *shadow_addr = (u8 *)MemToShadow(p: addr);
481 // If we are accessing 16 bytes, look at the second shadow byte.
482 if (*shadow_addr == 0 && access_size > ASAN_SHADOW_GRANULARITY)
483 shadow_addr++;
484 // If we are in the partial right redzone, look at the next shadow byte.
485 if (*shadow_addr > 0 && *shadow_addr < 128) shadow_addr++;
486 bool far_from_bounds = false;
487 shadow_val = *shadow_addr;
488 int bug_type_score = 0;
489 // For use-after-frees reads are almost as bad as writes.
490 int read_after_free_bonus = 0;
491 switch (shadow_val) {
492 case kAsanHeapLeftRedzoneMagic:
493 case kAsanArrayCookieMagic:
494 bug_descr = "heap-buffer-overflow";
495 bug_type_score = 10;
496 far_from_bounds = AdjacentShadowValuesAreFullyPoisoned(s: shadow_addr);
497 break;
498 case kAsanHeapFreeMagic:
499 bug_descr = "heap-use-after-free";
500 bug_type_score = 20;
501 if (!is_write) read_after_free_bonus = 18;
502 break;
503 case kAsanStackLeftRedzoneMagic:
504 bug_descr = "stack-buffer-underflow";
505 bug_type_score = 25;
506 far_from_bounds = AdjacentShadowValuesAreFullyPoisoned(s: shadow_addr);
507 break;
508 case kAsanInitializationOrderMagic:
509 bug_descr = "initialization-order-fiasco";
510 bug_type_score = 1;
511 break;
512 case kAsanStackMidRedzoneMagic:
513 case kAsanStackRightRedzoneMagic:
514 bug_descr = "stack-buffer-overflow";
515 bug_type_score = 25;
516 far_from_bounds = AdjacentShadowValuesAreFullyPoisoned(s: shadow_addr);
517 break;
518 case kAsanStackAfterReturnMagic:
519 bug_descr = "stack-use-after-return";
520 bug_type_score = 30;
521 if (!is_write) read_after_free_bonus = 18;
522 break;
523 case kAsanUserPoisonedMemoryMagic:
524 bug_descr = "use-after-poison";
525 bug_type_score = 20;
526 break;
527 case kAsanContiguousContainerOOBMagic:
528 bug_descr = "container-overflow";
529 bug_type_score = 10;
530 break;
531 case kAsanStackUseAfterScopeMagic:
532 bug_descr = "stack-use-after-scope";
533 bug_type_score = 10;
534 break;
535 case kAsanGlobalRedzoneMagic:
536 bug_descr = "global-buffer-overflow";
537 bug_type_score = 10;
538 far_from_bounds = AdjacentShadowValuesAreFullyPoisoned(s: shadow_addr);
539 break;
540 case kAsanIntraObjectRedzone:
541 bug_descr = "intra-object-overflow";
542 bug_type_score = 10;
543 break;
544 case kAsanAllocaLeftMagic:
545 case kAsanAllocaRightMagic:
546 bug_descr = "dynamic-stack-buffer-overflow";
547 bug_type_score = 25;
548 far_from_bounds = AdjacentShadowValuesAreFullyPoisoned(s: shadow_addr);
549 break;
550 }
551 scariness.Scare(add_to_score: bug_type_score + read_after_free_bonus, reason: bug_descr);
552 if (far_from_bounds) scariness.Scare(add_to_score: 10, reason: "far-from-bounds");
553 }
554 }
555}
556
557static void PrintContainerOverflowHint() {
558 Printf(
559 format: "HINT: if you don't care about these errors you may set "
560 "ASAN_OPTIONS=detect_container_overflow=0.\n"
561 "Or if supported by the container library, pass "
562 "-D__SANITIZER_DISABLE_CONTAINER_OVERFLOW__ to the compiler to disable "
563 " instrumentation.\n"
564 "If you suspect a false positive see also: "
565 "https://github.com/google/sanitizers/wiki/"
566 "AddressSanitizerContainerOverflow.\n");
567}
568
569static void PrintShadowByte(InternalScopedString *str, const char *before,
570 u8 byte, const char *after = "\n") {
571 PrintMemoryByte(str, before, byte, /*in_shadow*/true, after);
572}
573
574static void PrintLegend(InternalScopedString *str) {
575 str->AppendF(
576 format: "Shadow byte legend (one shadow byte represents %d "
577 "application bytes):\n",
578 (int)ASAN_SHADOW_GRANULARITY);
579 PrintShadowByte(str, before: " Addressable: ", byte: 0);
580 str->AppendF(format: " Partially addressable: ");
581 for (u8 i = 1; i < ASAN_SHADOW_GRANULARITY; i++)
582 PrintShadowByte(str, before: "", byte: i, after: " ");
583 str->AppendF(format: "\n");
584 PrintShadowByte(str, before: " Heap left redzone: ",
585 byte: kAsanHeapLeftRedzoneMagic);
586 PrintShadowByte(str, before: " Freed heap region: ", byte: kAsanHeapFreeMagic);
587 PrintShadowByte(str, before: " Stack left redzone: ",
588 byte: kAsanStackLeftRedzoneMagic);
589 PrintShadowByte(str, before: " Stack mid redzone: ",
590 byte: kAsanStackMidRedzoneMagic);
591 PrintShadowByte(str, before: " Stack right redzone: ",
592 byte: kAsanStackRightRedzoneMagic);
593 PrintShadowByte(str, before: " Stack after return: ",
594 byte: kAsanStackAfterReturnMagic);
595 PrintShadowByte(str, before: " Stack use after scope: ",
596 byte: kAsanStackUseAfterScopeMagic);
597 PrintShadowByte(str, before: " Global redzone: ", byte: kAsanGlobalRedzoneMagic);
598 PrintShadowByte(str, before: " Global init order: ",
599 byte: kAsanInitializationOrderMagic);
600 PrintShadowByte(str, before: " Poisoned by user: ",
601 byte: kAsanUserPoisonedMemoryMagic);
602 PrintShadowByte(str, before: " Container overflow: ",
603 byte: kAsanContiguousContainerOOBMagic);
604 PrintShadowByte(str, before: " Array cookie: ",
605 byte: kAsanArrayCookieMagic);
606 PrintShadowByte(str, before: " Intra object redzone: ",
607 byte: kAsanIntraObjectRedzone);
608 PrintShadowByte(str, before: " ASan internal: ", byte: kAsanInternalHeapMagic);
609 PrintShadowByte(str, before: " Left alloca redzone: ", byte: kAsanAllocaLeftMagic);
610 PrintShadowByte(str, before: " Right alloca redzone: ", byte: kAsanAllocaRightMagic);
611}
612
613static void PrintShadowBytes(InternalScopedString *str, const char *before,
614 u8 *bytes, u8 *guilty, uptr n) {
615 Decorator d;
616 if (before)
617 str->AppendF(format: "%s%p:", before,
618 (void *)ShadowToMem(p: reinterpret_cast<uptr>(bytes)));
619 for (uptr i = 0; i < n; i++) {
620 u8 *p = bytes + i;
621 const char *before =
622 p == guilty ? "[" : (p - 1 == guilty && i != 0) ? "" : " ";
623 const char *after = p == guilty ? "]" : "";
624 PrintShadowByte(str, before, byte: *p, after);
625 }
626 str->AppendF(format: "\n");
627}
628
629static void PrintShadowMemoryForAddress(uptr addr) {
630 if (!AddrIsInMem(a: addr)) return;
631 uptr shadow_addr = MemToShadow(p: addr);
632 const uptr n_bytes_per_row = 16;
633 uptr aligned_shadow = shadow_addr & ~(n_bytes_per_row - 1);
634 InternalScopedString str;
635 str.AppendF(format: "Shadow bytes around the buggy address:\n");
636 for (int i = -5; i <= 5; i++) {
637 uptr row_shadow_addr = aligned_shadow + i * n_bytes_per_row;
638 // Skip rows that would be outside the shadow range. This can happen when
639 // the user address is near the bottom, top, or shadow gap of the address
640 // space.
641 if (!AddrIsInShadow(a: row_shadow_addr)) continue;
642 const char *prefix = (i == 0) ? "=>" : " ";
643 PrintShadowBytes(str: &str, before: prefix, bytes: (u8 *)row_shadow_addr, guilty: (u8 *)shadow_addr,
644 n: n_bytes_per_row);
645 }
646 if (flags()->print_legend) PrintLegend(str: &str);
647 Printf(format: "%s", str.data());
648}
649
650static void CheckPoisonRecords(uptr addr) {
651 if (!AddrIsInMem(a: addr))
652 return;
653
654 u8 *shadow_addr = (u8 *)MemToShadow(p: addr);
655 // If we are in the partial right redzone, look at the next shadow byte.
656 if (*shadow_addr > 0 && *shadow_addr < 128)
657 shadow_addr++;
658 u8 shadow_val = *shadow_addr;
659
660 if (shadow_val != kAsanUserPoisonedMemoryMagic)
661 return;
662
663 Printf(format: "\n");
664
665 if (flags()->poison_history_size <= 0) {
666 Printf(
667 format: "NOTE: the stack trace above identifies the code that *accessed* "
668 "the poisoned memory.\n");
669 Printf(
670 format: "To identify the code that *poisoned* the memory, try the "
671 "experimental setting ASAN_OPTIONS=poison_history_size=<size>.\n");
672 return;
673 }
674
675 PoisonRecord record;
676 if (FindPoisonRecord(addr, match&: record)) {
677 StackTrace poison_stack = StackDepotGet(id: record.stack_id);
678 if (poison_stack.size > 0) {
679 Printf(format: "Memory was manually poisoned by thread T%u:\n", record.thread_id);
680 poison_stack.Print();
681 }
682 } else {
683 Printf(format: "ERROR: no matching poison tracking record found.\n");
684 Printf(format: "Try a larger value for ASAN_OPTIONS=poison_history_size=<size>.\n");
685 }
686}
687
688void ErrorGeneric::Print() {
689 Decorator d;
690 Printf(format: "%s", d.Error());
691 uptr addr = addr_description.Address();
692 Report(format: "ERROR: AddressSanitizer: %s on address %p at pc %p bp %p sp %p\n",
693 bug_descr, (void *)addr, (void *)pc, (void *)bp, (void *)sp);
694 Printf(format: "%s", d.Default());
695
696 Printf(format: "%s%s of size %zu at %p thread %s%s\n", d.Access(),
697 access_size ? (is_write ? "WRITE" : "READ") : "ACCESS", access_size,
698 (void *)addr, AsanThreadIdAndName(tid).c_str(), d.Default());
699
700 scariness.Print();
701 GET_STACK_TRACE_FATAL(pc, bp);
702 stack.Print();
703
704 // Pass bug_descr because we have a special case for
705 // initialization-order-fiasco
706 addr_description.Print(bug_descr);
707 if (shadow_val == kAsanContiguousContainerOOBMagic)
708 PrintContainerOverflowHint();
709 ReportErrorSummary(error_type: bug_descr, trace: &stack);
710 PrintShadowMemoryForAddress(addr);
711
712 // This is an experimental flag, hence we don't make a special handler.
713 CheckPoisonRecords(addr);
714}
715
716} // namespace __asan
717