1 //===-- asan_errors.h -------------------------------------------*- 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-private header for error structures.
12 //===----------------------------------------------------------------------===//
16 #include "asan_descriptions.h"
17 #include "asan_scariness_score.h"
18 #include "sanitizer_common/sanitizer_common.h"
22 // (*) VS2013 does not implement unrestricted unions, so we need a trivial
23 // default constructor explicitly defined for each particular error.
25 // None of the error classes own the stack traces mentioned in them.
28 ScarinessScoreBase scariness
;
31 ErrorBase() = default; // (*)
32 explicit ErrorBase(u32 tid_
) : tid(tid_
) {}
33 ErrorBase(u32 tid_
, int initial_score
, const char *reason
) : tid(tid_
) {
35 scariness
.Scare(initial_score
, reason
);
39 struct ErrorDeadlySignal
: ErrorBase
{
42 ErrorDeadlySignal() = default; // (*)
43 ErrorDeadlySignal(u32 tid
, const SignalContext
&sig
)
47 if (signal
.IsStackOverflow()) {
48 scariness
.Scare(10, "stack-overflow");
49 } else if (!signal
.is_memory_access
) {
50 scariness
.Scare(10, "signal");
51 } else if (signal
.is_true_faulting_addr
&&
52 signal
.addr
< GetPageSizeCached()) {
53 scariness
.Scare(10, "null-deref");
54 } else if (signal
.addr
== signal
.pc
) {
55 scariness
.Scare(60, "wild-jump");
56 } else if (signal
.write_flag
== SignalContext::WRITE
) {
57 scariness
.Scare(30, "wild-addr-write");
58 } else if (signal
.write_flag
== SignalContext::READ
) {
59 scariness
.Scare(20, "wild-addr-read");
61 scariness
.Scare(25, "wild-addr");
67 struct ErrorDoubleFree
: ErrorBase
{
68 const BufferedStackTrace
*second_free_stack
;
69 HeapAddressDescription addr_description
;
71 ErrorDoubleFree() = default; // (*)
72 ErrorDoubleFree(u32 tid
, BufferedStackTrace
*stack
, uptr addr
)
73 : ErrorBase(tid
, 42, "double-free"),
74 second_free_stack(stack
) {
75 CHECK_GT(second_free_stack
->size
, 0);
76 GetHeapAddressInformation(addr
, 1, &addr_description
);
81 struct ErrorNewDeleteTypeMismatch
: ErrorBase
{
82 const BufferedStackTrace
*free_stack
;
83 HeapAddressDescription addr_description
;
85 uptr delete_alignment
;
87 ErrorNewDeleteTypeMismatch() = default; // (*)
88 ErrorNewDeleteTypeMismatch(u32 tid
, BufferedStackTrace
*stack
, uptr addr
,
89 uptr delete_size_
, uptr delete_alignment_
)
90 : ErrorBase(tid
, 10, "new-delete-type-mismatch"),
92 delete_size(delete_size_
),
93 delete_alignment(delete_alignment_
) {
94 GetHeapAddressInformation(addr
, 1, &addr_description
);
99 struct ErrorFreeNotMalloced
: ErrorBase
{
100 const BufferedStackTrace
*free_stack
;
101 AddressDescription addr_description
;
103 ErrorFreeNotMalloced() = default; // (*)
104 ErrorFreeNotMalloced(u32 tid
, BufferedStackTrace
*stack
, uptr addr
)
105 : ErrorBase(tid
, 40, "bad-free"),
107 addr_description(addr
, /*shouldLockThreadRegistry=*/false) {}
111 struct ErrorAllocTypeMismatch
: ErrorBase
{
112 const BufferedStackTrace
*dealloc_stack
;
113 AllocType alloc_type
, dealloc_type
;
114 AddressDescription addr_description
;
116 ErrorAllocTypeMismatch() = default; // (*)
117 ErrorAllocTypeMismatch(u32 tid
, BufferedStackTrace
*stack
, uptr addr
,
118 AllocType alloc_type_
, AllocType dealloc_type_
)
119 : ErrorBase(tid
, 10, "alloc-dealloc-mismatch"),
120 dealloc_stack(stack
),
121 alloc_type(alloc_type_
),
122 dealloc_type(dealloc_type_
),
123 addr_description(addr
, 1, false) {}
127 struct ErrorMallocUsableSizeNotOwned
: ErrorBase
{
128 const BufferedStackTrace
*stack
;
129 AddressDescription addr_description
;
131 ErrorMallocUsableSizeNotOwned() = default; // (*)
132 ErrorMallocUsableSizeNotOwned(u32 tid
, BufferedStackTrace
*stack_
, uptr addr
)
133 : ErrorBase(tid
, 10, "bad-malloc_usable_size"),
135 addr_description(addr
, /*shouldLockThreadRegistry=*/false) {}
139 struct ErrorSanitizerGetAllocatedSizeNotOwned
: ErrorBase
{
140 const BufferedStackTrace
*stack
;
141 AddressDescription addr_description
;
143 ErrorSanitizerGetAllocatedSizeNotOwned() = default; // (*)
144 ErrorSanitizerGetAllocatedSizeNotOwned(u32 tid
, BufferedStackTrace
*stack_
,
146 : ErrorBase(tid
, 10, "bad-__sanitizer_get_allocated_size"),
148 addr_description(addr
, /*shouldLockThreadRegistry=*/false) {}
152 struct ErrorCallocOverflow
: ErrorBase
{
153 const BufferedStackTrace
*stack
;
157 ErrorCallocOverflow() = default; // (*)
158 ErrorCallocOverflow(u32 tid
, BufferedStackTrace
*stack_
, uptr count_
,
160 : ErrorBase(tid
, 10, "calloc-overflow"),
167 struct ErrorReallocArrayOverflow
: ErrorBase
{
168 const BufferedStackTrace
*stack
;
172 ErrorReallocArrayOverflow() = default; // (*)
173 ErrorReallocArrayOverflow(u32 tid
, BufferedStackTrace
*stack_
, uptr count_
,
175 : ErrorBase(tid
, 10, "reallocarray-overflow"),
182 struct ErrorPvallocOverflow
: ErrorBase
{
183 const BufferedStackTrace
*stack
;
186 ErrorPvallocOverflow() = default; // (*)
187 ErrorPvallocOverflow(u32 tid
, BufferedStackTrace
*stack_
, uptr size_
)
188 : ErrorBase(tid
, 10, "pvalloc-overflow"),
194 struct ErrorInvalidAllocationAlignment
: ErrorBase
{
195 const BufferedStackTrace
*stack
;
198 ErrorInvalidAllocationAlignment() = default; // (*)
199 ErrorInvalidAllocationAlignment(u32 tid
, BufferedStackTrace
*stack_
,
201 : ErrorBase(tid
, 10, "invalid-allocation-alignment"),
203 alignment(alignment_
) {}
207 struct ErrorInvalidAlignedAllocAlignment
: ErrorBase
{
208 const BufferedStackTrace
*stack
;
212 ErrorInvalidAlignedAllocAlignment() = default; // (*)
213 ErrorInvalidAlignedAllocAlignment(u32 tid
, BufferedStackTrace
*stack_
,
214 uptr size_
, uptr alignment_
)
215 : ErrorBase(tid
, 10, "invalid-aligned-alloc-alignment"),
218 alignment(alignment_
) {}
222 struct ErrorInvalidPosixMemalignAlignment
: ErrorBase
{
223 const BufferedStackTrace
*stack
;
226 ErrorInvalidPosixMemalignAlignment() = default; // (*)
227 ErrorInvalidPosixMemalignAlignment(u32 tid
, BufferedStackTrace
*stack_
,
229 : ErrorBase(tid
, 10, "invalid-posix-memalign-alignment"),
231 alignment(alignment_
) {}
235 struct ErrorAllocationSizeTooBig
: ErrorBase
{
236 const BufferedStackTrace
*stack
;
241 ErrorAllocationSizeTooBig() = default; // (*)
242 ErrorAllocationSizeTooBig(u32 tid
, BufferedStackTrace
*stack_
,
243 uptr user_size_
, uptr total_size_
, uptr max_size_
)
244 : ErrorBase(tid
, 10, "allocation-size-too-big"),
246 user_size(user_size_
),
247 total_size(total_size_
),
248 max_size(max_size_
) {}
252 struct ErrorRssLimitExceeded
: ErrorBase
{
253 const BufferedStackTrace
*stack
;
255 ErrorRssLimitExceeded() = default; // (*)
256 ErrorRssLimitExceeded(u32 tid
, BufferedStackTrace
*stack_
)
257 : ErrorBase(tid
, 10, "rss-limit-exceeded"),
262 struct ErrorOutOfMemory
: ErrorBase
{
263 const BufferedStackTrace
*stack
;
266 ErrorOutOfMemory() = default; // (*)
267 ErrorOutOfMemory(u32 tid
, BufferedStackTrace
*stack_
, uptr requested_size_
)
268 : ErrorBase(tid
, 10, "out-of-memory"),
270 requested_size(requested_size_
) {}
274 struct ErrorStringFunctionMemoryRangesOverlap
: ErrorBase
{
275 const BufferedStackTrace
*stack
;
276 uptr length1
, length2
;
277 AddressDescription addr1_description
;
278 AddressDescription addr2_description
;
279 const char *function
;
281 ErrorStringFunctionMemoryRangesOverlap() = default; // (*)
282 ErrorStringFunctionMemoryRangesOverlap(u32 tid
, BufferedStackTrace
*stack_
,
283 uptr addr1
, uptr length1_
, uptr addr2
,
284 uptr length2_
, const char *function_
)
289 addr1_description(addr1
, length1
, /*shouldLockThreadRegistry=*/false),
290 addr2_description(addr2
, length2
, /*shouldLockThreadRegistry=*/false),
291 function(function_
) {
293 internal_snprintf(bug_type
, sizeof(bug_type
), "%s-param-overlap", function
);
295 scariness
.Scare(10, bug_type
);
300 struct ErrorStringFunctionSizeOverflow
: ErrorBase
{
301 const BufferedStackTrace
*stack
;
302 AddressDescription addr_description
;
305 ErrorStringFunctionSizeOverflow() = default; // (*)
306 ErrorStringFunctionSizeOverflow(u32 tid
, BufferedStackTrace
*stack_
,
307 uptr addr
, uptr size_
)
308 : ErrorBase(tid
, 10, "negative-size-param"),
310 addr_description(addr
, /*shouldLockThreadRegistry=*/false),
315 struct ErrorBadParamsToAnnotateContiguousContainer
: ErrorBase
{
316 const BufferedStackTrace
*stack
;
317 uptr beg
, end
, old_mid
, new_mid
;
319 ErrorBadParamsToAnnotateContiguousContainer() = default; // (*)
320 // PS4: Do we want an AddressDescription for beg?
321 ErrorBadParamsToAnnotateContiguousContainer(u32 tid
,
322 BufferedStackTrace
*stack_
,
323 uptr beg_
, uptr end_
,
324 uptr old_mid_
, uptr new_mid_
)
325 : ErrorBase(tid
, 10, "bad-__sanitizer_annotate_contiguous_container"),
334 struct ErrorODRViolation
: ErrorBase
{
335 __asan_global global1
, global2
;
336 u32 stack_id1
, stack_id2
;
338 ErrorODRViolation() = default; // (*)
339 ErrorODRViolation(u32 tid
, const __asan_global
*g1
, u32 stack_id1_
,
340 const __asan_global
*g2
, u32 stack_id2_
)
341 : ErrorBase(tid
, 10, "odr-violation"),
344 stack_id1(stack_id1_
),
345 stack_id2(stack_id2_
) {}
349 struct ErrorInvalidPointerPair
: ErrorBase
{
351 AddressDescription addr1_description
;
352 AddressDescription addr2_description
;
354 ErrorInvalidPointerPair() = default; // (*)
355 ErrorInvalidPointerPair(u32 tid
, uptr pc_
, uptr bp_
, uptr sp_
, uptr p1
,
357 : ErrorBase(tid
, 10, "invalid-pointer-pair"),
361 addr1_description(p1
, 1, /*shouldLockThreadRegistry=*/false),
362 addr2_description(p2
, 1, /*shouldLockThreadRegistry=*/false) {}
366 struct ErrorGeneric
: ErrorBase
{
367 AddressDescription addr_description
;
370 const char *bug_descr
;
374 ErrorGeneric() = default; // (*)
375 ErrorGeneric(u32 tid
, uptr addr
, uptr pc_
, uptr bp_
, uptr sp_
, bool is_write_
,
381 #define ASAN_FOR_EACH_ERROR_KIND(macro) \
382 macro(DeadlySignal) \
384 macro(NewDeleteTypeMismatch) \
385 macro(FreeNotMalloced) \
386 macro(AllocTypeMismatch) \
387 macro(MallocUsableSizeNotOwned) \
388 macro(SanitizerGetAllocatedSizeNotOwned) \
389 macro(CallocOverflow) \
390 macro(ReallocArrayOverflow) \
391 macro(PvallocOverflow) \
392 macro(InvalidAllocationAlignment) \
393 macro(InvalidAlignedAllocAlignment) \
394 macro(InvalidPosixMemalignAlignment) \
395 macro(AllocationSizeTooBig) \
396 macro(RssLimitExceeded) \
398 macro(StringFunctionMemoryRangesOverlap) \
399 macro(StringFunctionSizeOverflow) \
400 macro(BadParamsToAnnotateContiguousContainer) \
401 macro(ODRViolation) \
402 macro(InvalidPointerPair) \
406 #define ASAN_DEFINE_ERROR_KIND(name) kErrorKind##name,
407 #define ASAN_ERROR_DESCRIPTION_MEMBER(name) Error##name name;
408 #define ASAN_ERROR_DESCRIPTION_CONSTRUCTOR(name) \
409 ErrorDescription(Error##name const &e) : kind(kErrorKind##name) { \
410 internal_memcpy(&name, &e, sizeof(name)); \
412 #define ASAN_ERROR_DESCRIPTION_PRINT(name) \
413 case kErrorKind##name: \
417 kErrorKindInvalid
= 0,
418 ASAN_FOR_EACH_ERROR_KIND(ASAN_DEFINE_ERROR_KIND
)
421 struct ErrorDescription
{
423 // We're using a tagged union because it allows us to have a trivially
424 // copiable type and use the same structures as the public interface.
426 // We can add a wrapper around it to make it "more c++-like", but that would
427 // add a lot of code and the benefit wouldn't be that big.
430 ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_MEMBER
)
433 ErrorDescription() { internal_memset(this, 0, sizeof(*this)); }
434 explicit ErrorDescription(LinkerInitialized
) {}
435 ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_CONSTRUCTOR
)
437 bool IsValid() { return kind
!= kErrorKindInvalid
; }
440 ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_PRINT
)
441 case kErrorKindInvalid
:
448 #undef ASAN_FOR_EACH_ERROR_KIND
449 #undef ASAN_DEFINE_ERROR_KIND
450 #undef ASAN_ERROR_DESCRIPTION_MEMBER
451 #undef ASAN_ERROR_DESCRIPTION_CONSTRUCTOR
452 #undef ASAN_ERROR_DESCRIPTION_PRINT
454 } // namespace __asan
456 #endif // ASAN_ERRORS_H