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 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 GetStackTraceWithPcBpAndContext(stack
, kStackTraceMax
, sig
.pc
, sig
.bp
,
42 void ErrorDeadlySignal::Print() {
43 ReportDeadlySignal(signal
, tid
, &OnStackUnwind
, &scariness
);
46 void ErrorDoubleFree::Print() {
48 Printf("%s", d
.Warning());
51 "ERROR: AddressSanitizer: attempting %s on %p in "
53 scariness
.GetDescription(), addr_description
.addr
, tid
,
54 ThreadNameWithParenthesis(tid
, tname
, sizeof(tname
)));
55 Printf("%s", d
.Default());
57 GET_STACK_TRACE_FATAL(second_free_stack
->trace
[0],
58 second_free_stack
->top_frame_bp
);
60 addr_description
.Print();
61 ReportErrorSummary(scariness
.GetDescription(), &stack
);
64 void ErrorNewDeleteSizeMismatch::Print() {
66 Printf("%s", d
.Warning());
69 "ERROR: AddressSanitizer: %s on %p in thread "
71 scariness
.GetDescription(), addr_description
.addr
, tid
,
72 ThreadNameWithParenthesis(tid
, tname
, sizeof(tname
)));
73 Printf("%s object passed to delete has wrong type:\n", d
.Default());
75 " size of the allocated type: %zd bytes;\n"
76 " size of the deallocated type: %zd bytes.\n",
77 addr_description
.chunk_access
.chunk_size
, delete_size
);
78 CHECK_GT(free_stack
->size
, 0);
80 GET_STACK_TRACE_FATAL(free_stack
->trace
[0], free_stack
->top_frame_bp
);
82 addr_description
.Print();
83 ReportErrorSummary(scariness
.GetDescription(), &stack
);
85 "HINT: if you don't care about these errors you may set "
86 "ASAN_OPTIONS=new_delete_type_mismatch=0\n");
89 void ErrorFreeNotMalloced::Print() {
91 Printf("%s", d
.Warning());
94 "ERROR: AddressSanitizer: attempting free on address "
95 "which was not malloc()-ed: %p in thread T%d%s\n",
96 addr_description
.Address(), tid
,
97 ThreadNameWithParenthesis(tid
, tname
, sizeof(tname
)));
98 Printf("%s", d
.Default());
99 CHECK_GT(free_stack
->size
, 0);
101 GET_STACK_TRACE_FATAL(free_stack
->trace
[0], free_stack
->top_frame_bp
);
103 addr_description
.Print();
104 ReportErrorSummary(scariness
.GetDescription(), &stack
);
107 void ErrorAllocTypeMismatch::Print() {
108 static const char *alloc_names
[] = {"INVALID", "malloc", "operator new",
110 static const char *dealloc_names
[] = {"INVALID", "free", "operator delete",
111 "operator delete []"};
112 CHECK_NE(alloc_type
, dealloc_type
);
114 Printf("%s", d
.Warning());
115 Report("ERROR: AddressSanitizer: %s (%s vs %s) on %p\n",
116 scariness
.GetDescription(),
117 alloc_names
[alloc_type
], dealloc_names
[dealloc_type
],
118 addr_description
.addr
);
119 Printf("%s", d
.Default());
120 CHECK_GT(dealloc_stack
->size
, 0);
122 GET_STACK_TRACE_FATAL(dealloc_stack
->trace
[0], dealloc_stack
->top_frame_bp
);
124 addr_description
.Print();
125 ReportErrorSummary(scariness
.GetDescription(), &stack
);
127 "HINT: if you don't care about these errors you may set "
128 "ASAN_OPTIONS=alloc_dealloc_mismatch=0\n");
131 void ErrorMallocUsableSizeNotOwned::Print() {
133 Printf("%s", d
.Warning());
135 "ERROR: AddressSanitizer: attempting to call malloc_usable_size() for "
136 "pointer which is not owned: %p\n",
137 addr_description
.Address());
138 Printf("%s", d
.Default());
140 addr_description
.Print();
141 ReportErrorSummary(scariness
.GetDescription(), stack
);
144 void ErrorSanitizerGetAllocatedSizeNotOwned::Print() {
146 Printf("%s", d
.Warning());
148 "ERROR: AddressSanitizer: attempting to call "
149 "__sanitizer_get_allocated_size() for pointer which is not owned: %p\n",
150 addr_description
.Address());
151 Printf("%s", d
.Default());
153 addr_description
.Print();
154 ReportErrorSummary(scariness
.GetDescription(), stack
);
157 void ErrorStringFunctionMemoryRangesOverlap::Print() {
160 internal_snprintf(bug_type
, sizeof(bug_type
), "%s-param-overlap", function
);
161 Printf("%s", d
.Warning());
163 "ERROR: AddressSanitizer: %s: memory ranges [%p,%p) and [%p, %p) "
165 bug_type
, addr1_description
.Address(),
166 addr1_description
.Address() + length1
, addr2_description
.Address(),
167 addr2_description
.Address() + length2
);
168 Printf("%s", d
.Default());
171 addr1_description
.Print();
172 addr2_description
.Print();
173 ReportErrorSummary(bug_type
, stack
);
176 void ErrorStringFunctionSizeOverflow::Print() {
178 Printf("%s", d
.Warning());
179 Report("ERROR: AddressSanitizer: %s: (size=%zd)\n",
180 scariness
.GetDescription(), size
);
181 Printf("%s", d
.Default());
184 addr_description
.Print();
185 ReportErrorSummary(scariness
.GetDescription(), stack
);
188 void ErrorBadParamsToAnnotateContiguousContainer::Print() {
190 "ERROR: AddressSanitizer: bad parameters to "
191 "__sanitizer_annotate_contiguous_container:\n"
196 beg
, end
, old_mid
, new_mid
);
197 uptr granularity
= SHADOW_GRANULARITY
;
198 if (!IsAligned(beg
, granularity
))
199 Report("ERROR: beg is not aligned by %d\n", granularity
);
201 ReportErrorSummary(scariness
.GetDescription(), stack
);
204 void ErrorODRViolation::Print() {
206 Printf("%s", d
.Warning());
207 Report("ERROR: AddressSanitizer: %s (%p):\n", scariness
.GetDescription(),
209 Printf("%s", d
.Default());
210 InternalScopedString
g1_loc(256), g2_loc(256);
211 PrintGlobalLocation(&g1_loc
, global1
);
212 PrintGlobalLocation(&g2_loc
, global2
);
213 Printf(" [1] size=%zd '%s' %s\n", global1
.size
,
214 MaybeDemangleGlobalName(global1
.name
), g1_loc
.data());
215 Printf(" [2] size=%zd '%s' %s\n", global2
.size
,
216 MaybeDemangleGlobalName(global2
.name
), g2_loc
.data());
217 if (stack_id1
&& stack_id2
) {
218 Printf("These globals were registered at these points:\n");
220 StackDepotGet(stack_id1
).Print();
222 StackDepotGet(stack_id2
).Print();
225 "HINT: if you don't care about these errors you may set "
226 "ASAN_OPTIONS=detect_odr_violation=0\n");
227 InternalScopedString
error_msg(256);
228 error_msg
.append("%s: global '%s' at %s", scariness
.GetDescription(),
229 MaybeDemangleGlobalName(global1
.name
), g1_loc
.data());
230 ReportErrorSummary(error_msg
.data());
233 void ErrorInvalidPointerPair::Print() {
235 Printf("%s", d
.Warning());
236 Report("ERROR: AddressSanitizer: %s: %p %p\n", scariness
.GetDescription(),
237 addr1_description
.Address(), addr2_description
.Address());
238 Printf("%s", d
.Default());
239 GET_STACK_TRACE_FATAL(pc
, bp
);
241 addr1_description
.Print();
242 addr2_description
.Print();
243 ReportErrorSummary(scariness
.GetDescription(), &stack
);
246 static bool AdjacentShadowValuesAreFullyPoisoned(u8
*s
) {
247 return s
[-1] > 127 && s
[1] > 127;
250 ErrorGeneric::ErrorGeneric(u32 tid
, uptr pc_
, uptr bp_
, uptr sp_
, uptr addr
,
251 bool is_write_
, uptr access_size_
)
253 addr_description(addr
, access_size_
, /*shouldLockThreadRegistry=*/false),
257 access_size(access_size_
),
262 if (access_size
<= 9) {
263 char desr
[] = "?-byte";
264 desr
[0] = '0' + access_size
;
265 scariness
.Scare(access_size
+ access_size
/ 2, desr
);
266 } else if (access_size
>= 10) {
267 scariness
.Scare(15, "multi-byte");
269 is_write
? scariness
.Scare(20, "write") : scariness
.Scare(1, "read");
271 // Determine the error type.
272 bug_descr
= "unknown-crash";
273 if (AddrIsInMem(addr
)) {
274 u8
*shadow_addr
= (u8
*)MemToShadow(addr
);
275 // If we are accessing 16 bytes, look at the second shadow byte.
276 if (*shadow_addr
== 0 && access_size
> SHADOW_GRANULARITY
) shadow_addr
++;
277 // If we are in the partial right redzone, look at the next shadow byte.
278 if (*shadow_addr
> 0 && *shadow_addr
< 128) shadow_addr
++;
279 bool far_from_bounds
= false;
280 shadow_val
= *shadow_addr
;
281 int bug_type_score
= 0;
282 // For use-after-frees reads are almost as bad as writes.
283 int read_after_free_bonus
= 0;
284 switch (shadow_val
) {
285 case kAsanHeapLeftRedzoneMagic
:
286 case kAsanArrayCookieMagic
:
287 bug_descr
= "heap-buffer-overflow";
289 far_from_bounds
= AdjacentShadowValuesAreFullyPoisoned(shadow_addr
);
291 case kAsanHeapFreeMagic
:
292 bug_descr
= "heap-use-after-free";
294 if (!is_write
) read_after_free_bonus
= 18;
296 case kAsanStackLeftRedzoneMagic
:
297 bug_descr
= "stack-buffer-underflow";
299 far_from_bounds
= AdjacentShadowValuesAreFullyPoisoned(shadow_addr
);
301 case kAsanInitializationOrderMagic
:
302 bug_descr
= "initialization-order-fiasco";
305 case kAsanStackMidRedzoneMagic
:
306 case kAsanStackRightRedzoneMagic
:
307 bug_descr
= "stack-buffer-overflow";
309 far_from_bounds
= AdjacentShadowValuesAreFullyPoisoned(shadow_addr
);
311 case kAsanStackAfterReturnMagic
:
312 bug_descr
= "stack-use-after-return";
314 if (!is_write
) read_after_free_bonus
= 18;
316 case kAsanUserPoisonedMemoryMagic
:
317 bug_descr
= "use-after-poison";
320 case kAsanContiguousContainerOOBMagic
:
321 bug_descr
= "container-overflow";
324 case kAsanStackUseAfterScopeMagic
:
325 bug_descr
= "stack-use-after-scope";
328 case kAsanGlobalRedzoneMagic
:
329 bug_descr
= "global-buffer-overflow";
331 far_from_bounds
= AdjacentShadowValuesAreFullyPoisoned(shadow_addr
);
333 case kAsanIntraObjectRedzone
:
334 bug_descr
= "intra-object-overflow";
337 case kAsanAllocaLeftMagic
:
338 case kAsanAllocaRightMagic
:
339 bug_descr
= "dynamic-stack-buffer-overflow";
341 far_from_bounds
= AdjacentShadowValuesAreFullyPoisoned(shadow_addr
);
344 scariness
.Scare(bug_type_score
+ read_after_free_bonus
, bug_descr
);
345 if (far_from_bounds
) scariness
.Scare(10, "far-from-bounds");
350 static void PrintContainerOverflowHint() {
351 Printf("HINT: if you don't care about these errors you may set "
352 "ASAN_OPTIONS=detect_container_overflow=0.\n"
353 "If you suspect a false positive see also: "
354 "https://github.com/google/sanitizers/wiki/"
355 "AddressSanitizerContainerOverflow.\n");
358 static void PrintShadowByte(InternalScopedString
*str
, const char *before
,
359 u8 byte
, const char *after
= "\n") {
360 PrintMemoryByte(str
, before
, byte
, /*in_shadow*/true, after
);
363 static void PrintLegend(InternalScopedString
*str
) {
365 "Shadow byte legend (one shadow byte represents %d "
366 "application bytes):\n",
367 (int)SHADOW_GRANULARITY
);
368 PrintShadowByte(str
, " Addressable: ", 0);
369 str
->append(" Partially addressable: ");
370 for (u8 i
= 1; i
< SHADOW_GRANULARITY
; i
++) PrintShadowByte(str
, "", i
, " ");
372 PrintShadowByte(str
, " Heap left redzone: ",
373 kAsanHeapLeftRedzoneMagic
);
374 PrintShadowByte(str
, " Freed heap region: ", kAsanHeapFreeMagic
);
375 PrintShadowByte(str
, " Stack left redzone: ",
376 kAsanStackLeftRedzoneMagic
);
377 PrintShadowByte(str
, " Stack mid redzone: ",
378 kAsanStackMidRedzoneMagic
);
379 PrintShadowByte(str
, " Stack right redzone: ",
380 kAsanStackRightRedzoneMagic
);
381 PrintShadowByte(str
, " Stack after return: ",
382 kAsanStackAfterReturnMagic
);
383 PrintShadowByte(str
, " Stack use after scope: ",
384 kAsanStackUseAfterScopeMagic
);
385 PrintShadowByte(str
, " Global redzone: ", kAsanGlobalRedzoneMagic
);
386 PrintShadowByte(str
, " Global init order: ",
387 kAsanInitializationOrderMagic
);
388 PrintShadowByte(str
, " Poisoned by user: ",
389 kAsanUserPoisonedMemoryMagic
);
390 PrintShadowByte(str
, " Container overflow: ",
391 kAsanContiguousContainerOOBMagic
);
392 PrintShadowByte(str
, " Array cookie: ",
393 kAsanArrayCookieMagic
);
394 PrintShadowByte(str
, " Intra object redzone: ",
395 kAsanIntraObjectRedzone
);
396 PrintShadowByte(str
, " ASan internal: ", kAsanInternalHeapMagic
);
397 PrintShadowByte(str
, " Left alloca redzone: ", kAsanAllocaLeftMagic
);
398 PrintShadowByte(str
, " Right alloca redzone: ", kAsanAllocaRightMagic
);
401 static void PrintShadowBytes(InternalScopedString
*str
, const char *before
,
402 u8
*bytes
, u8
*guilty
, uptr n
) {
404 if (before
) str
->append("%s%p:", before
, bytes
);
405 for (uptr i
= 0; i
< n
; i
++) {
408 p
== guilty
? "[" : (p
- 1 == guilty
&& i
!= 0) ? "" : " ";
409 const char *after
= p
== guilty
? "]" : "";
410 PrintShadowByte(str
, before
, *p
, after
);
415 static void PrintShadowMemoryForAddress(uptr addr
) {
416 if (!AddrIsInMem(addr
)) return;
417 uptr shadow_addr
= MemToShadow(addr
);
418 const uptr n_bytes_per_row
= 16;
419 uptr aligned_shadow
= shadow_addr
& ~(n_bytes_per_row
- 1);
420 InternalScopedString
str(4096 * 8);
421 str
.append("Shadow bytes around the buggy address:\n");
422 for (int i
= -5; i
<= 5; i
++) {
423 const char *prefix
= (i
== 0) ? "=>" : " ";
424 PrintShadowBytes(&str
, prefix
, (u8
*)(aligned_shadow
+ i
* n_bytes_per_row
),
425 (u8
*)shadow_addr
, n_bytes_per_row
);
427 if (flags()->print_legend
) PrintLegend(&str
);
428 Printf("%s", str
.data());
431 void ErrorGeneric::Print() {
433 Printf("%s", d
.Warning());
434 uptr addr
= addr_description
.Address();
435 Report("ERROR: AddressSanitizer: %s on address %p at pc %p bp %p sp %p\n",
436 bug_descr
, (void *)addr
, pc
, bp
, sp
);
437 Printf("%s", d
.Default());
440 Printf("%s%s of size %zu at %p thread T%d%s%s\n", d
.Access(),
441 access_size
? (is_write
? "WRITE" : "READ") : "ACCESS", access_size
,
443 ThreadNameWithParenthesis(tid
, tname
, sizeof(tname
)), d
.Default());
446 GET_STACK_TRACE_FATAL(pc
, bp
);
449 // Pass bug_descr because we have a special case for
450 // initialization-order-fiasco
451 addr_description
.Print(bug_descr
);
452 if (shadow_val
== kAsanContiguousContainerOOBMagic
)
453 PrintContainerOverflowHint();
454 ReportErrorSummary(bug_descr
, &stack
);
455 PrintShadowMemoryForAddress(addr
);
458 } // namespace __asan