1 //===-- asan_errors.h -------------------------------------------*- 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-private header for error structures.
11 //===----------------------------------------------------------------------===//
15 #include "asan_descriptions.h"
16 #include "asan_scariness_score.h"
17 #include "sanitizer_common/sanitizer_common.h"
21 // (*) VS2013 does not implement unrestricted unions, so we need a trivial
22 // default constructor explicitly defined for each particular error.
24 // None of the error classes own the stack traces mentioned in them.
27 ScarinessScoreBase scariness
;
30 ErrorBase() = default; // (*)
31 explicit ErrorBase(u32 tid_
) : tid(tid_
) {}
32 ErrorBase(u32 tid_
, int initial_score
, const char *reason
) : tid(tid_
) {
34 scariness
.Scare(initial_score
, reason
);
38 struct ErrorDeadlySignal
: ErrorBase
{
41 ErrorDeadlySignal() = default; // (*)
42 ErrorDeadlySignal(u32 tid
, const SignalContext
&sig
)
46 if (signal
.IsStackOverflow()) {
47 scariness
.Scare(10, "stack-overflow");
48 } else if (!signal
.is_memory_access
) {
49 scariness
.Scare(10, "signal");
50 } else if (signal
.addr
< GetPageSizeCached()) {
51 scariness
.Scare(10, "null-deref");
52 } else if (signal
.addr
== signal
.pc
) {
53 scariness
.Scare(60, "wild-jump");
54 } else if (signal
.write_flag
== SignalContext::WRITE
) {
55 scariness
.Scare(30, "wild-addr-write");
56 } else if (signal
.write_flag
== SignalContext::READ
) {
57 scariness
.Scare(20, "wild-addr-read");
59 scariness
.Scare(25, "wild-addr");
65 struct ErrorDoubleFree
: ErrorBase
{
66 const BufferedStackTrace
*second_free_stack
;
67 HeapAddressDescription addr_description
;
69 ErrorDoubleFree() = default; // (*)
70 ErrorDoubleFree(u32 tid
, BufferedStackTrace
*stack
, uptr addr
)
71 : ErrorBase(tid
, 42, "double-free"),
72 second_free_stack(stack
) {
73 CHECK_GT(second_free_stack
->size
, 0);
74 GetHeapAddressInformation(addr
, 1, &addr_description
);
79 struct ErrorNewDeleteTypeMismatch
: ErrorBase
{
80 const BufferedStackTrace
*free_stack
;
81 HeapAddressDescription addr_description
;
83 uptr delete_alignment
;
85 ErrorNewDeleteTypeMismatch() = default; // (*)
86 ErrorNewDeleteTypeMismatch(u32 tid
, BufferedStackTrace
*stack
, uptr addr
,
87 uptr delete_size_
, uptr delete_alignment_
)
88 : ErrorBase(tid
, 10, "new-delete-type-mismatch"),
90 delete_size(delete_size_
),
91 delete_alignment(delete_alignment_
) {
92 GetHeapAddressInformation(addr
, 1, &addr_description
);
97 struct ErrorFreeNotMalloced
: ErrorBase
{
98 const BufferedStackTrace
*free_stack
;
99 AddressDescription addr_description
;
101 ErrorFreeNotMalloced() = default; // (*)
102 ErrorFreeNotMalloced(u32 tid
, BufferedStackTrace
*stack
, uptr addr
)
103 : ErrorBase(tid
, 40, "bad-free"),
105 addr_description(addr
, /*shouldLockThreadRegistry=*/false) {}
109 struct ErrorAllocTypeMismatch
: ErrorBase
{
110 const BufferedStackTrace
*dealloc_stack
;
111 HeapAddressDescription addr_description
;
112 AllocType alloc_type
, dealloc_type
;
114 ErrorAllocTypeMismatch() = default; // (*)
115 ErrorAllocTypeMismatch(u32 tid
, BufferedStackTrace
*stack
, uptr addr
,
116 AllocType alloc_type_
, AllocType dealloc_type_
)
117 : ErrorBase(tid
, 10, "alloc-dealloc-mismatch"),
118 dealloc_stack(stack
),
119 alloc_type(alloc_type_
),
120 dealloc_type(dealloc_type_
) {
121 GetHeapAddressInformation(addr
, 1, &addr_description
);
126 struct ErrorMallocUsableSizeNotOwned
: ErrorBase
{
127 const BufferedStackTrace
*stack
;
128 AddressDescription addr_description
;
130 ErrorMallocUsableSizeNotOwned() = default; // (*)
131 ErrorMallocUsableSizeNotOwned(u32 tid
, BufferedStackTrace
*stack_
, uptr addr
)
132 : ErrorBase(tid
, 10, "bad-malloc_usable_size"),
134 addr_description(addr
, /*shouldLockThreadRegistry=*/false) {}
138 struct ErrorSanitizerGetAllocatedSizeNotOwned
: ErrorBase
{
139 const BufferedStackTrace
*stack
;
140 AddressDescription addr_description
;
142 ErrorSanitizerGetAllocatedSizeNotOwned() = default; // (*)
143 ErrorSanitizerGetAllocatedSizeNotOwned(u32 tid
, BufferedStackTrace
*stack_
,
145 : ErrorBase(tid
, 10, "bad-__sanitizer_get_allocated_size"),
147 addr_description(addr
, /*shouldLockThreadRegistry=*/false) {}
151 struct ErrorCallocOverflow
: ErrorBase
{
152 const BufferedStackTrace
*stack
;
156 ErrorCallocOverflow() = default; // (*)
157 ErrorCallocOverflow(u32 tid
, BufferedStackTrace
*stack_
, uptr count_
,
159 : ErrorBase(tid
, 10, "calloc-overflow"),
166 struct ErrorPvallocOverflow
: ErrorBase
{
167 const BufferedStackTrace
*stack
;
170 ErrorPvallocOverflow() = default; // (*)
171 ErrorPvallocOverflow(u32 tid
, BufferedStackTrace
*stack_
, uptr size_
)
172 : ErrorBase(tid
, 10, "pvalloc-overflow"),
178 struct ErrorInvalidAllocationAlignment
: ErrorBase
{
179 const BufferedStackTrace
*stack
;
182 ErrorInvalidAllocationAlignment() = default; // (*)
183 ErrorInvalidAllocationAlignment(u32 tid
, BufferedStackTrace
*stack_
,
185 : ErrorBase(tid
, 10, "invalid-allocation-alignment"),
187 alignment(alignment_
) {}
191 struct ErrorInvalidAlignedAllocAlignment
: ErrorBase
{
192 const BufferedStackTrace
*stack
;
196 ErrorInvalidAlignedAllocAlignment() = default; // (*)
197 ErrorInvalidAlignedAllocAlignment(u32 tid
, BufferedStackTrace
*stack_
,
198 uptr size_
, uptr alignment_
)
199 : ErrorBase(tid
, 10, "invalid-aligned-alloc-alignment"),
202 alignment(alignment_
) {}
206 struct ErrorInvalidPosixMemalignAlignment
: ErrorBase
{
207 const BufferedStackTrace
*stack
;
210 ErrorInvalidPosixMemalignAlignment() = default; // (*)
211 ErrorInvalidPosixMemalignAlignment(u32 tid
, BufferedStackTrace
*stack_
,
213 : ErrorBase(tid
, 10, "invalid-posix-memalign-alignment"),
215 alignment(alignment_
) {}
219 struct ErrorAllocationSizeTooBig
: ErrorBase
{
220 const BufferedStackTrace
*stack
;
225 ErrorAllocationSizeTooBig() = default; // (*)
226 ErrorAllocationSizeTooBig(u32 tid
, BufferedStackTrace
*stack_
,
227 uptr user_size_
, uptr total_size_
, uptr max_size_
)
228 : ErrorBase(tid
, 10, "allocation-size-too-big"),
230 user_size(user_size_
),
231 total_size(total_size_
),
232 max_size(max_size_
) {}
236 struct ErrorRssLimitExceeded
: ErrorBase
{
237 const BufferedStackTrace
*stack
;
239 ErrorRssLimitExceeded() = default; // (*)
240 ErrorRssLimitExceeded(u32 tid
, BufferedStackTrace
*stack_
)
241 : ErrorBase(tid
, 10, "rss-limit-exceeded"),
246 struct ErrorOutOfMemory
: ErrorBase
{
247 const BufferedStackTrace
*stack
;
250 ErrorOutOfMemory() = default; // (*)
251 ErrorOutOfMemory(u32 tid
, BufferedStackTrace
*stack_
, uptr requested_size_
)
252 : ErrorBase(tid
, 10, "out-of-memory"),
254 requested_size(requested_size_
) {}
258 struct ErrorStringFunctionMemoryRangesOverlap
: ErrorBase
{
259 const BufferedStackTrace
*stack
;
260 uptr length1
, length2
;
261 AddressDescription addr1_description
;
262 AddressDescription addr2_description
;
263 const char *function
;
265 ErrorStringFunctionMemoryRangesOverlap() = default; // (*)
266 ErrorStringFunctionMemoryRangesOverlap(u32 tid
, BufferedStackTrace
*stack_
,
267 uptr addr1
, uptr length1_
, uptr addr2
,
268 uptr length2_
, const char *function_
)
273 addr1_description(addr1
, length1
, /*shouldLockThreadRegistry=*/false),
274 addr2_description(addr2
, length2
, /*shouldLockThreadRegistry=*/false),
275 function(function_
) {
277 internal_snprintf(bug_type
, sizeof(bug_type
), "%s-param-overlap", function
);
279 scariness
.Scare(10, bug_type
);
284 struct ErrorStringFunctionSizeOverflow
: ErrorBase
{
285 const BufferedStackTrace
*stack
;
286 AddressDescription addr_description
;
289 ErrorStringFunctionSizeOverflow() = default; // (*)
290 ErrorStringFunctionSizeOverflow(u32 tid
, BufferedStackTrace
*stack_
,
291 uptr addr
, uptr size_
)
292 : ErrorBase(tid
, 10, "negative-size-param"),
294 addr_description(addr
, /*shouldLockThreadRegistry=*/false),
299 struct ErrorBadParamsToAnnotateContiguousContainer
: ErrorBase
{
300 const BufferedStackTrace
*stack
;
301 uptr beg
, end
, old_mid
, new_mid
;
303 ErrorBadParamsToAnnotateContiguousContainer() = default; // (*)
304 // PS4: Do we want an AddressDescription for beg?
305 ErrorBadParamsToAnnotateContiguousContainer(u32 tid
,
306 BufferedStackTrace
*stack_
,
307 uptr beg_
, uptr end_
,
308 uptr old_mid_
, uptr new_mid_
)
309 : ErrorBase(tid
, 10, "bad-__sanitizer_annotate_contiguous_container"),
318 struct ErrorODRViolation
: ErrorBase
{
319 __asan_global global1
, global2
;
320 u32 stack_id1
, stack_id2
;
322 ErrorODRViolation() = default; // (*)
323 ErrorODRViolation(u32 tid
, const __asan_global
*g1
, u32 stack_id1_
,
324 const __asan_global
*g2
, u32 stack_id2_
)
325 : ErrorBase(tid
, 10, "odr-violation"),
328 stack_id1(stack_id1_
),
329 stack_id2(stack_id2_
) {}
333 struct ErrorInvalidPointerPair
: ErrorBase
{
335 AddressDescription addr1_description
;
336 AddressDescription addr2_description
;
338 ErrorInvalidPointerPair() = default; // (*)
339 ErrorInvalidPointerPair(u32 tid
, uptr pc_
, uptr bp_
, uptr sp_
, uptr p1
,
341 : ErrorBase(tid
, 10, "invalid-pointer-pair"),
345 addr1_description(p1
, 1, /*shouldLockThreadRegistry=*/false),
346 addr2_description(p2
, 1, /*shouldLockThreadRegistry=*/false) {}
350 struct ErrorGeneric
: ErrorBase
{
351 AddressDescription addr_description
;
354 const char *bug_descr
;
358 ErrorGeneric() = default; // (*)
359 ErrorGeneric(u32 tid
, uptr addr
, uptr pc_
, uptr bp_
, uptr sp_
, bool is_write_
,
365 #define ASAN_FOR_EACH_ERROR_KIND(macro) \
366 macro(DeadlySignal) \
368 macro(NewDeleteTypeMismatch) \
369 macro(FreeNotMalloced) \
370 macro(AllocTypeMismatch) \
371 macro(MallocUsableSizeNotOwned) \
372 macro(SanitizerGetAllocatedSizeNotOwned) \
373 macro(CallocOverflow) \
374 macro(PvallocOverflow) \
375 macro(InvalidAllocationAlignment) \
376 macro(InvalidAlignedAllocAlignment) \
377 macro(InvalidPosixMemalignAlignment) \
378 macro(AllocationSizeTooBig) \
379 macro(RssLimitExceeded) \
381 macro(StringFunctionMemoryRangesOverlap) \
382 macro(StringFunctionSizeOverflow) \
383 macro(BadParamsToAnnotateContiguousContainer) \
384 macro(ODRViolation) \
385 macro(InvalidPointerPair) \
389 #define ASAN_DEFINE_ERROR_KIND(name) kErrorKind##name,
390 #define ASAN_ERROR_DESCRIPTION_MEMBER(name) Error##name name;
391 #define ASAN_ERROR_DESCRIPTION_CONSTRUCTOR(name) \
392 ErrorDescription(Error##name const &e) : kind(kErrorKind##name), name(e) {}
393 #define ASAN_ERROR_DESCRIPTION_PRINT(name) \
394 case kErrorKind##name: \
398 kErrorKindInvalid
= 0,
399 ASAN_FOR_EACH_ERROR_KIND(ASAN_DEFINE_ERROR_KIND
)
402 struct ErrorDescription
{
404 // We're using a tagged union because it allows us to have a trivially
405 // copiable type and use the same structures as the public interface.
407 // We can add a wrapper around it to make it "more c++-like", but that would
408 // add a lot of code and the benefit wouldn't be that big.
411 ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_MEMBER
)
414 ErrorDescription() { internal_memset(this, 0, sizeof(*this)); }
415 explicit ErrorDescription(LinkerInitialized
) {}
416 ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_CONSTRUCTOR
)
418 bool IsValid() { return kind
!= kErrorKindInvalid
; }
421 ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_PRINT
)
422 case kErrorKindInvalid
:
429 #undef ASAN_FOR_EACH_ERROR_KIND
430 #undef ASAN_DEFINE_ERROR_KIND
431 #undef ASAN_ERROR_DESCRIPTION_MEMBER
432 #undef ASAN_ERROR_DESCRIPTION_CONSTRUCTOR
433 #undef ASAN_ERROR_DESCRIPTION_PRINT
435 } // namespace __asan
437 #endif // ASAN_ERRORS_H