1 //===-- asan_errors.cc ------------------------------------------*- C++ -*-===//
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 // ASan implementation for error structures.
11 //===----------------------------------------------------------------------===//
13 #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 void ErrorStackOverflow::Print() {
25 Printf("%s", d
.Warning());
27 "ERROR: AddressSanitizer: stack-overflow on address %p"
28 " (pc %p bp %p sp %p T%d)\n",
29 (void *)addr
, (void *)pc
, (void *)bp
, (void *)sp
, tid
);
30 Printf("%s", d
.EndWarning());
32 BufferedStackTrace stack
;
33 GetStackTraceWithPcBpAndContext(&stack
, kStackTraceMax
, pc
, bp
, context
,
34 common_flags()->fast_unwind_on_fatal
);
36 ReportErrorSummary("stack-overflow", &stack
);
39 static void MaybeDumpInstructionBytes(uptr pc
) {
40 if (!flags()->dump_instruction_bytes
|| (pc
< GetPageSizeCached())) return;
41 InternalScopedString
str(1024);
42 str
.append("First 16 instruction bytes at pc: ");
43 if (IsAccessibleMemoryRange(pc
, 16)) {
44 for (int i
= 0; i
< 16; ++i
) {
45 PrintMemoryByte(&str
, "", ((u8
*)pc
)[i
], /*in_shadow*/ false, " ");
49 str
.append("unaccessible\n");
51 Report("%s", str
.data());
54 void ErrorDeadlySignal::Print() {
56 Printf("%s", d
.Warning());
57 const char *description
= DescribeSignalOrException(signo
);
59 "ERROR: AddressSanitizer: %s on unknown address %p (pc %p bp %p sp %p "
61 description
, (void *)addr
, (void *)pc
, (void *)bp
, (void *)sp
, tid
);
62 Printf("%s", d
.EndWarning());
63 if (pc
< GetPageSizeCached()) Report("Hint: pc points to the zero page.\n");
64 if (is_memory_access
) {
65 const char *access_type
=
66 write_flag
== SignalContext::WRITE
68 : (write_flag
== SignalContext::READ
? "READ" : "UNKNOWN");
69 Report("The signal is caused by a %s memory access.\n", access_type
);
70 if (addr
< GetPageSizeCached())
71 Report("Hint: address points to the zero page.\n");
74 BufferedStackTrace stack
;
75 GetStackTraceWithPcBpAndContext(&stack
, kStackTraceMax
, pc
, bp
, context
,
76 common_flags()->fast_unwind_on_fatal
);
78 MaybeDumpInstructionBytes(pc
);
79 Printf("AddressSanitizer can not provide additional info.\n");
80 ReportErrorSummary(description
, &stack
);
83 void ErrorDoubleFree::Print() {
85 Printf("%s", d
.Warning());
88 "ERROR: AddressSanitizer: attempting double-free on %p in "
90 addr_description
.addr
, tid
,
91 ThreadNameWithParenthesis(tid
, tname
, sizeof(tname
)));
92 Printf("%s", d
.EndWarning());
94 GET_STACK_TRACE_FATAL(second_free_stack
->trace
[0],
95 second_free_stack
->top_frame_bp
);
97 addr_description
.Print();
98 ReportErrorSummary("double-free", &stack
);
101 void ErrorNewDeleteSizeMismatch::Print() {
103 Printf("%s", d
.Warning());
106 "ERROR: AddressSanitizer: new-delete-type-mismatch on %p in thread "
108 addr_description
.addr
, tid
,
109 ThreadNameWithParenthesis(tid
, tname
, sizeof(tname
)));
110 Printf("%s object passed to delete has wrong type:\n", d
.EndWarning());
112 " size of the allocated type: %zd bytes;\n"
113 " size of the deallocated type: %zd bytes.\n",
114 addr_description
.chunk_access
.chunk_size
, delete_size
);
115 CHECK_GT(free_stack
->size
, 0);
117 GET_STACK_TRACE_FATAL(free_stack
->trace
[0], free_stack
->top_frame_bp
);
119 addr_description
.Print();
120 ReportErrorSummary("new-delete-type-mismatch", &stack
);
122 "HINT: if you don't care about these errors you may set "
123 "ASAN_OPTIONS=new_delete_type_mismatch=0\n");
126 void ErrorFreeNotMalloced::Print() {
128 Printf("%s", d
.Warning());
131 "ERROR: AddressSanitizer: attempting free on address "
132 "which was not malloc()-ed: %p in thread T%d%s\n",
133 addr_description
.Address(), tid
,
134 ThreadNameWithParenthesis(tid
, tname
, sizeof(tname
)));
135 Printf("%s", d
.EndWarning());
136 CHECK_GT(free_stack
->size
, 0);
138 GET_STACK_TRACE_FATAL(free_stack
->trace
[0], free_stack
->top_frame_bp
);
140 addr_description
.Print();
141 ReportErrorSummary("bad-free", &stack
);
144 void ErrorAllocTypeMismatch::Print() {
145 static const char *alloc_names
[] = {"INVALID", "malloc", "operator new",
147 static const char *dealloc_names
[] = {"INVALID", "free", "operator delete",
148 "operator delete []"};
149 CHECK_NE(alloc_type
, dealloc_type
);
151 Printf("%s", d
.Warning());
152 Report("ERROR: AddressSanitizer: alloc-dealloc-mismatch (%s vs %s) on %p\n",
153 alloc_names
[alloc_type
], dealloc_names
[dealloc_type
],
154 addr_description
.addr
);
155 Printf("%s", d
.EndWarning());
156 CHECK_GT(dealloc_stack
->size
, 0);
158 GET_STACK_TRACE_FATAL(dealloc_stack
->trace
[0], dealloc_stack
->top_frame_bp
);
160 addr_description
.Print();
161 ReportErrorSummary("alloc-dealloc-mismatch", &stack
);
163 "HINT: if you don't care about these errors you may set "
164 "ASAN_OPTIONS=alloc_dealloc_mismatch=0\n");
167 void ErrorMallocUsableSizeNotOwned::Print() {
169 Printf("%s", d
.Warning());
171 "ERROR: AddressSanitizer: attempting to call malloc_usable_size() for "
172 "pointer which is not owned: %p\n",
173 addr_description
.Address());
174 Printf("%s", d
.EndWarning());
176 addr_description
.Print();
177 ReportErrorSummary("bad-malloc_usable_size", stack
);
180 void ErrorSanitizerGetAllocatedSizeNotOwned::Print() {
182 Printf("%s", d
.Warning());
184 "ERROR: AddressSanitizer: attempting to call "
185 "__sanitizer_get_allocated_size() for pointer which is not owned: %p\n",
186 addr_description
.Address());
187 Printf("%s", d
.EndWarning());
189 addr_description
.Print();
190 ReportErrorSummary("bad-__sanitizer_get_allocated_size", stack
);
193 void ErrorStringFunctionMemoryRangesOverlap::Print() {
196 internal_snprintf(bug_type
, sizeof(bug_type
), "%s-param-overlap", function
);
197 Printf("%s", d
.Warning());
199 "ERROR: AddressSanitizer: %s: memory ranges [%p,%p) and [%p, %p) "
201 bug_type
, addr1_description
.Address(),
202 addr1_description
.Address() + length1
, addr2_description
.Address(),
203 addr2_description
.Address() + length2
);
204 Printf("%s", d
.EndWarning());
207 addr1_description
.Print();
208 addr2_description
.Print();
209 ReportErrorSummary(bug_type
, stack
);
212 void ErrorStringFunctionSizeOverflow::Print() {
214 Printf("%s", d
.Warning());
215 const char *bug_type
= "negative-size-param";
216 Report("ERROR: AddressSanitizer: %s: (size=%zd)\n", bug_type
, size
);
217 Printf("%s", d
.EndWarning());
220 addr_description
.Print();
221 ReportErrorSummary(bug_type
, stack
);
224 void ErrorBadParamsToAnnotateContiguousContainer::Print() {
226 "ERROR: AddressSanitizer: bad parameters to "
227 "__sanitizer_annotate_contiguous_container:\n"
232 beg
, end
, old_mid
, new_mid
);
233 uptr granularity
= SHADOW_GRANULARITY
;
234 if (!IsAligned(beg
, granularity
))
235 Report("ERROR: beg is not aligned by %d\n", granularity
);
237 ReportErrorSummary("bad-__sanitizer_annotate_contiguous_container", stack
);
240 void ErrorODRViolation::Print() {
242 Printf("%s", d
.Warning());
243 Report("ERROR: AddressSanitizer: odr-violation (%p):\n", global1
.beg
);
244 Printf("%s", d
.EndWarning());
245 InternalScopedString
g1_loc(256), g2_loc(256);
246 PrintGlobalLocation(&g1_loc
, global1
);
247 PrintGlobalLocation(&g2_loc
, global2
);
248 Printf(" [1] size=%zd '%s' %s\n", global1
.size
,
249 MaybeDemangleGlobalName(global1
.name
), g1_loc
.data());
250 Printf(" [2] size=%zd '%s' %s\n", global2
.size
,
251 MaybeDemangleGlobalName(global2
.name
), g2_loc
.data());
252 if (stack_id1
&& stack_id2
) {
253 Printf("These globals were registered at these points:\n");
255 StackDepotGet(stack_id1
).Print();
257 StackDepotGet(stack_id2
).Print();
260 "HINT: if you don't care about these errors you may set "
261 "ASAN_OPTIONS=detect_odr_violation=0\n");
262 InternalScopedString
error_msg(256);
263 error_msg
.append("odr-violation: global '%s' at %s",
264 MaybeDemangleGlobalName(global1
.name
), g1_loc
.data());
265 ReportErrorSummary(error_msg
.data());
268 void ErrorInvalidPointerPair::Print() {
269 const char *bug_type
= "invalid-pointer-pair";
271 Printf("%s", d
.Warning());
272 Report("ERROR: AddressSanitizer: invalid-pointer-pair: %p %p\n",
273 addr1_description
.Address(), addr2_description
.Address());
274 Printf("%s", d
.EndWarning());
275 GET_STACK_TRACE_FATAL(pc
, bp
);
277 addr1_description
.Print();
278 addr2_description
.Print();
279 ReportErrorSummary(bug_type
, &stack
);
282 static bool AdjacentShadowValuesAreFullyPoisoned(u8
*s
) {
283 return s
[-1] > 127 && s
[1] > 127;
286 ErrorGeneric::ErrorGeneric(u32 tid
, uptr pc_
, uptr bp_
, uptr sp_
, uptr addr
,
287 bool is_write_
, uptr access_size_
)
289 addr_description(addr
, access_size_
, /*shouldLockThreadRegistry=*/false),
293 access_size(access_size_
),
298 if (access_size
<= 9) {
299 char desr
[] = "?-byte";
300 desr
[0] = '0' + access_size
;
301 scariness
.Scare(access_size
+ access_size
/ 2, desr
);
302 } else if (access_size
>= 10) {
303 scariness
.Scare(15, "multi-byte");
305 is_write
? scariness
.Scare(20, "write") : scariness
.Scare(1, "read");
307 // Determine the error type.
308 bug_descr
= "unknown-crash";
309 if (AddrIsInMem(addr
)) {
310 u8
*shadow_addr
= (u8
*)MemToShadow(addr
);
311 // If we are accessing 16 bytes, look at the second shadow byte.
312 if (*shadow_addr
== 0 && access_size
> SHADOW_GRANULARITY
) shadow_addr
++;
313 // If we are in the partial right redzone, look at the next shadow byte.
314 if (*shadow_addr
> 0 && *shadow_addr
< 128) shadow_addr
++;
315 bool far_from_bounds
= false;
316 shadow_val
= *shadow_addr
;
317 int bug_type_score
= 0;
318 // For use-after-frees reads are almost as bad as writes.
319 int read_after_free_bonus
= 0;
320 switch (shadow_val
) {
321 case kAsanHeapLeftRedzoneMagic
:
322 case kAsanArrayCookieMagic
:
323 bug_descr
= "heap-buffer-overflow";
325 far_from_bounds
= AdjacentShadowValuesAreFullyPoisoned(shadow_addr
);
327 case kAsanHeapFreeMagic
:
328 bug_descr
= "heap-use-after-free";
330 if (!is_write
) read_after_free_bonus
= 18;
332 case kAsanStackLeftRedzoneMagic
:
333 bug_descr
= "stack-buffer-underflow";
335 far_from_bounds
= AdjacentShadowValuesAreFullyPoisoned(shadow_addr
);
337 case kAsanInitializationOrderMagic
:
338 bug_descr
= "initialization-order-fiasco";
341 case kAsanStackMidRedzoneMagic
:
342 case kAsanStackRightRedzoneMagic
:
343 bug_descr
= "stack-buffer-overflow";
345 far_from_bounds
= AdjacentShadowValuesAreFullyPoisoned(shadow_addr
);
347 case kAsanStackAfterReturnMagic
:
348 bug_descr
= "stack-use-after-return";
350 if (!is_write
) read_after_free_bonus
= 18;
352 case kAsanUserPoisonedMemoryMagic
:
353 bug_descr
= "use-after-poison";
356 case kAsanContiguousContainerOOBMagic
:
357 bug_descr
= "container-overflow";
360 case kAsanStackUseAfterScopeMagic
:
361 bug_descr
= "stack-use-after-scope";
364 case kAsanGlobalRedzoneMagic
:
365 bug_descr
= "global-buffer-overflow";
367 far_from_bounds
= AdjacentShadowValuesAreFullyPoisoned(shadow_addr
);
369 case kAsanIntraObjectRedzone
:
370 bug_descr
= "intra-object-overflow";
373 case kAsanAllocaLeftMagic
:
374 case kAsanAllocaRightMagic
:
375 bug_descr
= "dynamic-stack-buffer-overflow";
377 far_from_bounds
= AdjacentShadowValuesAreFullyPoisoned(shadow_addr
);
380 scariness
.Scare(bug_type_score
+ read_after_free_bonus
, bug_descr
);
381 if (far_from_bounds
) scariness
.Scare(10, "far-from-bounds");
386 static void PrintContainerOverflowHint() {
387 Printf("HINT: if you don't care about these errors you may set "
388 "ASAN_OPTIONS=detect_container_overflow=0.\n"
389 "If you suspect a false positive see also: "
390 "https://github.com/google/sanitizers/wiki/"
391 "AddressSanitizerContainerOverflow.\n");
394 static void PrintShadowByte(InternalScopedString
*str
, const char *before
,
395 u8 byte
, const char *after
= "\n") {
396 PrintMemoryByte(str
, before
, byte
, /*in_shadow*/true, after
);
399 static void PrintLegend(InternalScopedString
*str
) {
401 "Shadow byte legend (one shadow byte represents %d "
402 "application bytes):\n",
403 (int)SHADOW_GRANULARITY
);
404 PrintShadowByte(str
, " Addressable: ", 0);
405 str
->append(" Partially addressable: ");
406 for (u8 i
= 1; i
< SHADOW_GRANULARITY
; i
++) PrintShadowByte(str
, "", i
, " ");
408 PrintShadowByte(str
, " Heap left redzone: ",
409 kAsanHeapLeftRedzoneMagic
);
410 PrintShadowByte(str
, " Freed heap region: ", kAsanHeapFreeMagic
);
411 PrintShadowByte(str
, " Stack left redzone: ",
412 kAsanStackLeftRedzoneMagic
);
413 PrintShadowByte(str
, " Stack mid redzone: ",
414 kAsanStackMidRedzoneMagic
);
415 PrintShadowByte(str
, " Stack right redzone: ",
416 kAsanStackRightRedzoneMagic
);
417 PrintShadowByte(str
, " Stack after return: ",
418 kAsanStackAfterReturnMagic
);
419 PrintShadowByte(str
, " Stack use after scope: ",
420 kAsanStackUseAfterScopeMagic
);
421 PrintShadowByte(str
, " Global redzone: ", kAsanGlobalRedzoneMagic
);
422 PrintShadowByte(str
, " Global init order: ",
423 kAsanInitializationOrderMagic
);
424 PrintShadowByte(str
, " Poisoned by user: ",
425 kAsanUserPoisonedMemoryMagic
);
426 PrintShadowByte(str
, " Container overflow: ",
427 kAsanContiguousContainerOOBMagic
);
428 PrintShadowByte(str
, " Array cookie: ",
429 kAsanArrayCookieMagic
);
430 PrintShadowByte(str
, " Intra object redzone: ",
431 kAsanIntraObjectRedzone
);
432 PrintShadowByte(str
, " ASan internal: ", kAsanInternalHeapMagic
);
433 PrintShadowByte(str
, " Left alloca redzone: ", kAsanAllocaLeftMagic
);
434 PrintShadowByte(str
, " Right alloca redzone: ", kAsanAllocaRightMagic
);
437 static void PrintShadowBytes(InternalScopedString
*str
, const char *before
,
438 u8
*bytes
, u8
*guilty
, uptr n
) {
440 if (before
) str
->append("%s%p:", before
, bytes
);
441 for (uptr i
= 0; i
< n
; i
++) {
444 p
== guilty
? "[" : (p
- 1 == guilty
&& i
!= 0) ? "" : " ";
445 const char *after
= p
== guilty
? "]" : "";
446 PrintShadowByte(str
, before
, *p
, after
);
451 static void PrintShadowMemoryForAddress(uptr addr
) {
452 if (!AddrIsInMem(addr
)) return;
453 uptr shadow_addr
= MemToShadow(addr
);
454 const uptr n_bytes_per_row
= 16;
455 uptr aligned_shadow
= shadow_addr
& ~(n_bytes_per_row
- 1);
456 InternalScopedString
str(4096 * 8);
457 str
.append("Shadow bytes around the buggy address:\n");
458 for (int i
= -5; i
<= 5; i
++) {
459 const char *prefix
= (i
== 0) ? "=>" : " ";
460 PrintShadowBytes(&str
, prefix
, (u8
*)(aligned_shadow
+ i
* n_bytes_per_row
),
461 (u8
*)shadow_addr
, n_bytes_per_row
);
463 if (flags()->print_legend
) PrintLegend(&str
);
464 Printf("%s", str
.data());
467 void ErrorGeneric::Print() {
469 Printf("%s", d
.Warning());
470 uptr addr
= addr_description
.Address();
471 Report("ERROR: AddressSanitizer: %s on address %p at pc %p bp %p sp %p\n",
472 bug_descr
, (void *)addr
, pc
, bp
, sp
);
473 Printf("%s", d
.EndWarning());
476 Printf("%s%s of size %zu at %p thread T%d%s%s\n", d
.Access(),
477 access_size
? (is_write
? "WRITE" : "READ") : "ACCESS", access_size
,
479 ThreadNameWithParenthesis(tid
, tname
, sizeof(tname
)), d
.EndAccess());
482 GET_STACK_TRACE_FATAL(pc
, bp
);
485 // Pass bug_descr because we have a special case for
486 // initialization-order-fiasco
487 addr_description
.Print(bug_descr
);
488 if (shadow_val
== kAsanContiguousContainerOOBMagic
)
489 PrintContainerOverflowHint();
490 ReportErrorSummary(bug_descr
, &stack
);
491 PrintShadowMemoryForAddress(addr
);
494 } // namespace __asan