123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456 |
- //===-- asan_errors.h -------------------------------------------*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // This file is a part of AddressSanitizer, an address sanity checker.
- //
- // ASan-private header for error structures.
- //===----------------------------------------------------------------------===//
- #ifndef ASAN_ERRORS_H
- #define ASAN_ERRORS_H
- #include "asan_descriptions.h"
- #include "asan_scariness_score.h"
- #include "sanitizer_common/sanitizer_common.h"
- namespace __asan {
- // (*) VS2013 does not implement unrestricted unions, so we need a trivial
- // default constructor explicitly defined for each particular error.
- // None of the error classes own the stack traces mentioned in them.
- struct ErrorBase {
- ScarinessScoreBase scariness;
- u32 tid;
- ErrorBase() = default; // (*)
- explicit ErrorBase(u32 tid_) : tid(tid_) {}
- ErrorBase(u32 tid_, int initial_score, const char *reason) : tid(tid_) {
- scariness.Clear();
- scariness.Scare(initial_score, reason);
- }
- };
- struct ErrorDeadlySignal : ErrorBase {
- SignalContext signal;
- ErrorDeadlySignal() = default; // (*)
- ErrorDeadlySignal(u32 tid, const SignalContext &sig)
- : ErrorBase(tid),
- signal(sig) {
- scariness.Clear();
- if (signal.IsStackOverflow()) {
- scariness.Scare(10, "stack-overflow");
- } else if (!signal.is_memory_access) {
- scariness.Scare(10, "signal");
- } else if (signal.is_true_faulting_addr &&
- signal.addr < GetPageSizeCached()) {
- scariness.Scare(10, "null-deref");
- } else if (signal.addr == signal.pc) {
- scariness.Scare(60, "wild-jump");
- } else if (signal.write_flag == SignalContext::Write) {
- scariness.Scare(30, "wild-addr-write");
- } else if (signal.write_flag == SignalContext::Read) {
- scariness.Scare(20, "wild-addr-read");
- } else {
- scariness.Scare(25, "wild-addr");
- }
- }
- void Print();
- };
- struct ErrorDoubleFree : ErrorBase {
- const BufferedStackTrace *second_free_stack;
- HeapAddressDescription addr_description;
- ErrorDoubleFree() = default; // (*)
- ErrorDoubleFree(u32 tid, BufferedStackTrace *stack, uptr addr)
- : ErrorBase(tid, 42, "double-free"),
- second_free_stack(stack) {
- CHECK_GT(second_free_stack->size, 0);
- GetHeapAddressInformation(addr, 1, &addr_description);
- }
- void Print();
- };
- struct ErrorNewDeleteTypeMismatch : ErrorBase {
- const BufferedStackTrace *free_stack;
- HeapAddressDescription addr_description;
- uptr delete_size;
- uptr delete_alignment;
- ErrorNewDeleteTypeMismatch() = default; // (*)
- ErrorNewDeleteTypeMismatch(u32 tid, BufferedStackTrace *stack, uptr addr,
- uptr delete_size_, uptr delete_alignment_)
- : ErrorBase(tid, 10, "new-delete-type-mismatch"),
- free_stack(stack),
- delete_size(delete_size_),
- delete_alignment(delete_alignment_) {
- GetHeapAddressInformation(addr, 1, &addr_description);
- }
- void Print();
- };
- struct ErrorFreeNotMalloced : ErrorBase {
- const BufferedStackTrace *free_stack;
- AddressDescription addr_description;
- ErrorFreeNotMalloced() = default; // (*)
- ErrorFreeNotMalloced(u32 tid, BufferedStackTrace *stack, uptr addr)
- : ErrorBase(tid, 40, "bad-free"),
- free_stack(stack),
- addr_description(addr, /*shouldLockThreadRegistry=*/false) {}
- void Print();
- };
- struct ErrorAllocTypeMismatch : ErrorBase {
- const BufferedStackTrace *dealloc_stack;
- AllocType alloc_type, dealloc_type;
- AddressDescription addr_description;
- ErrorAllocTypeMismatch() = default; // (*)
- ErrorAllocTypeMismatch(u32 tid, BufferedStackTrace *stack, uptr addr,
- AllocType alloc_type_, AllocType dealloc_type_)
- : ErrorBase(tid, 10, "alloc-dealloc-mismatch"),
- dealloc_stack(stack),
- alloc_type(alloc_type_),
- dealloc_type(dealloc_type_),
- addr_description(addr, 1, false) {}
- void Print();
- };
- struct ErrorMallocUsableSizeNotOwned : ErrorBase {
- const BufferedStackTrace *stack;
- AddressDescription addr_description;
- ErrorMallocUsableSizeNotOwned() = default; // (*)
- ErrorMallocUsableSizeNotOwned(u32 tid, BufferedStackTrace *stack_, uptr addr)
- : ErrorBase(tid, 10, "bad-malloc_usable_size"),
- stack(stack_),
- addr_description(addr, /*shouldLockThreadRegistry=*/false) {}
- void Print();
- };
- struct ErrorSanitizerGetAllocatedSizeNotOwned : ErrorBase {
- const BufferedStackTrace *stack;
- AddressDescription addr_description;
- ErrorSanitizerGetAllocatedSizeNotOwned() = default; // (*)
- ErrorSanitizerGetAllocatedSizeNotOwned(u32 tid, BufferedStackTrace *stack_,
- uptr addr)
- : ErrorBase(tid, 10, "bad-__sanitizer_get_allocated_size"),
- stack(stack_),
- addr_description(addr, /*shouldLockThreadRegistry=*/false) {}
- void Print();
- };
- struct ErrorCallocOverflow : ErrorBase {
- const BufferedStackTrace *stack;
- uptr count;
- uptr size;
- ErrorCallocOverflow() = default; // (*)
- ErrorCallocOverflow(u32 tid, BufferedStackTrace *stack_, uptr count_,
- uptr size_)
- : ErrorBase(tid, 10, "calloc-overflow"),
- stack(stack_),
- count(count_),
- size(size_) {}
- void Print();
- };
- struct ErrorReallocArrayOverflow : ErrorBase {
- const BufferedStackTrace *stack;
- uptr count;
- uptr size;
- ErrorReallocArrayOverflow() = default; // (*)
- ErrorReallocArrayOverflow(u32 tid, BufferedStackTrace *stack_, uptr count_,
- uptr size_)
- : ErrorBase(tid, 10, "reallocarray-overflow"),
- stack(stack_),
- count(count_),
- size(size_) {}
- void Print();
- };
- struct ErrorPvallocOverflow : ErrorBase {
- const BufferedStackTrace *stack;
- uptr size;
- ErrorPvallocOverflow() = default; // (*)
- ErrorPvallocOverflow(u32 tid, BufferedStackTrace *stack_, uptr size_)
- : ErrorBase(tid, 10, "pvalloc-overflow"),
- stack(stack_),
- size(size_) {}
- void Print();
- };
- struct ErrorInvalidAllocationAlignment : ErrorBase {
- const BufferedStackTrace *stack;
- uptr alignment;
- ErrorInvalidAllocationAlignment() = default; // (*)
- ErrorInvalidAllocationAlignment(u32 tid, BufferedStackTrace *stack_,
- uptr alignment_)
- : ErrorBase(tid, 10, "invalid-allocation-alignment"),
- stack(stack_),
- alignment(alignment_) {}
- void Print();
- };
- struct ErrorInvalidAlignedAllocAlignment : ErrorBase {
- const BufferedStackTrace *stack;
- uptr size;
- uptr alignment;
- ErrorInvalidAlignedAllocAlignment() = default; // (*)
- ErrorInvalidAlignedAllocAlignment(u32 tid, BufferedStackTrace *stack_,
- uptr size_, uptr alignment_)
- : ErrorBase(tid, 10, "invalid-aligned-alloc-alignment"),
- stack(stack_),
- size(size_),
- alignment(alignment_) {}
- void Print();
- };
- struct ErrorInvalidPosixMemalignAlignment : ErrorBase {
- const BufferedStackTrace *stack;
- uptr alignment;
- ErrorInvalidPosixMemalignAlignment() = default; // (*)
- ErrorInvalidPosixMemalignAlignment(u32 tid, BufferedStackTrace *stack_,
- uptr alignment_)
- : ErrorBase(tid, 10, "invalid-posix-memalign-alignment"),
- stack(stack_),
- alignment(alignment_) {}
- void Print();
- };
- struct ErrorAllocationSizeTooBig : ErrorBase {
- const BufferedStackTrace *stack;
- uptr user_size;
- uptr total_size;
- uptr max_size;
- ErrorAllocationSizeTooBig() = default; // (*)
- ErrorAllocationSizeTooBig(u32 tid, BufferedStackTrace *stack_,
- uptr user_size_, uptr total_size_, uptr max_size_)
- : ErrorBase(tid, 10, "allocation-size-too-big"),
- stack(stack_),
- user_size(user_size_),
- total_size(total_size_),
- max_size(max_size_) {}
- void Print();
- };
- struct ErrorRssLimitExceeded : ErrorBase {
- const BufferedStackTrace *stack;
- ErrorRssLimitExceeded() = default; // (*)
- ErrorRssLimitExceeded(u32 tid, BufferedStackTrace *stack_)
- : ErrorBase(tid, 10, "rss-limit-exceeded"),
- stack(stack_) {}
- void Print();
- };
- struct ErrorOutOfMemory : ErrorBase {
- const BufferedStackTrace *stack;
- uptr requested_size;
- ErrorOutOfMemory() = default; // (*)
- ErrorOutOfMemory(u32 tid, BufferedStackTrace *stack_, uptr requested_size_)
- : ErrorBase(tid, 10, "out-of-memory"),
- stack(stack_),
- requested_size(requested_size_) {}
- void Print();
- };
- struct ErrorStringFunctionMemoryRangesOverlap : ErrorBase {
- const BufferedStackTrace *stack;
- uptr length1, length2;
- AddressDescription addr1_description;
- AddressDescription addr2_description;
- const char *function;
- ErrorStringFunctionMemoryRangesOverlap() = default; // (*)
- ErrorStringFunctionMemoryRangesOverlap(u32 tid, BufferedStackTrace *stack_,
- uptr addr1, uptr length1_, uptr addr2,
- uptr length2_, const char *function_)
- : ErrorBase(tid),
- stack(stack_),
- length1(length1_),
- length2(length2_),
- addr1_description(addr1, length1, /*shouldLockThreadRegistry=*/false),
- addr2_description(addr2, length2, /*shouldLockThreadRegistry=*/false),
- function(function_) {
- char bug_type[100];
- internal_snprintf(bug_type, sizeof(bug_type), "%s-param-overlap", function);
- scariness.Clear();
- scariness.Scare(10, bug_type);
- }
- void Print();
- };
- struct ErrorStringFunctionSizeOverflow : ErrorBase {
- const BufferedStackTrace *stack;
- AddressDescription addr_description;
- uptr size;
- ErrorStringFunctionSizeOverflow() = default; // (*)
- ErrorStringFunctionSizeOverflow(u32 tid, BufferedStackTrace *stack_,
- uptr addr, uptr size_)
- : ErrorBase(tid, 10, "negative-size-param"),
- stack(stack_),
- addr_description(addr, /*shouldLockThreadRegistry=*/false),
- size(size_) {}
- void Print();
- };
- struct ErrorBadParamsToAnnotateContiguousContainer : ErrorBase {
- const BufferedStackTrace *stack;
- uptr beg, end, old_mid, new_mid;
- ErrorBadParamsToAnnotateContiguousContainer() = default; // (*)
- // PS4: Do we want an AddressDescription for beg?
- ErrorBadParamsToAnnotateContiguousContainer(u32 tid,
- BufferedStackTrace *stack_,
- uptr beg_, uptr end_,
- uptr old_mid_, uptr new_mid_)
- : ErrorBase(tid, 10, "bad-__sanitizer_annotate_contiguous_container"),
- stack(stack_),
- beg(beg_),
- end(end_),
- old_mid(old_mid_),
- new_mid(new_mid_) {}
- void Print();
- };
- struct ErrorODRViolation : ErrorBase {
- __asan_global global1, global2;
- u32 stack_id1, stack_id2;
- ErrorODRViolation() = default; // (*)
- ErrorODRViolation(u32 tid, const __asan_global *g1, u32 stack_id1_,
- const __asan_global *g2, u32 stack_id2_)
- : ErrorBase(tid, 10, "odr-violation"),
- global1(*g1),
- global2(*g2),
- stack_id1(stack_id1_),
- stack_id2(stack_id2_) {}
- void Print();
- };
- struct ErrorInvalidPointerPair : ErrorBase {
- uptr pc, bp, sp;
- AddressDescription addr1_description;
- AddressDescription addr2_description;
- ErrorInvalidPointerPair() = default; // (*)
- ErrorInvalidPointerPair(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr p1,
- uptr p2)
- : ErrorBase(tid, 10, "invalid-pointer-pair"),
- pc(pc_),
- bp(bp_),
- sp(sp_),
- addr1_description(p1, 1, /*shouldLockThreadRegistry=*/false),
- addr2_description(p2, 1, /*shouldLockThreadRegistry=*/false) {}
- void Print();
- };
- struct ErrorGeneric : ErrorBase {
- AddressDescription addr_description;
- uptr pc, bp, sp;
- uptr access_size;
- const char *bug_descr;
- bool is_write;
- u8 shadow_val;
- ErrorGeneric() = default; // (*)
- ErrorGeneric(u32 tid, uptr addr, uptr pc_, uptr bp_, uptr sp_, bool is_write_,
- uptr access_size_);
- void Print();
- };
- // clang-format off
- #define ASAN_FOR_EACH_ERROR_KIND(macro) \
- macro(DeadlySignal) \
- macro(DoubleFree) \
- macro(NewDeleteTypeMismatch) \
- macro(FreeNotMalloced) \
- macro(AllocTypeMismatch) \
- macro(MallocUsableSizeNotOwned) \
- macro(SanitizerGetAllocatedSizeNotOwned) \
- macro(CallocOverflow) \
- macro(ReallocArrayOverflow) \
- macro(PvallocOverflow) \
- macro(InvalidAllocationAlignment) \
- macro(InvalidAlignedAllocAlignment) \
- macro(InvalidPosixMemalignAlignment) \
- macro(AllocationSizeTooBig) \
- macro(RssLimitExceeded) \
- macro(OutOfMemory) \
- macro(StringFunctionMemoryRangesOverlap) \
- macro(StringFunctionSizeOverflow) \
- macro(BadParamsToAnnotateContiguousContainer) \
- macro(ODRViolation) \
- macro(InvalidPointerPair) \
- macro(Generic)
- // clang-format on
- #define ASAN_DEFINE_ERROR_KIND(name) kErrorKind##name,
- #define ASAN_ERROR_DESCRIPTION_MEMBER(name) Error##name name;
- #define ASAN_ERROR_DESCRIPTION_CONSTRUCTOR(name) \
- ErrorDescription(Error##name const &e) : kind(kErrorKind##name) { \
- internal_memcpy(&name, &e, sizeof(name)); \
- }
- #define ASAN_ERROR_DESCRIPTION_PRINT(name) \
- case kErrorKind##name: \
- return name.Print();
- enum ErrorKind {
- kErrorKindInvalid = 0,
- ASAN_FOR_EACH_ERROR_KIND(ASAN_DEFINE_ERROR_KIND)
- };
- struct ErrorDescription {
- ErrorKind kind;
- // We're using a tagged union because it allows us to have a trivially
- // copiable type and use the same structures as the public interface.
- //
- // We can add a wrapper around it to make it "more c++-like", but that would
- // add a lot of code and the benefit wouldn't be that big.
- union {
- ErrorBase Base;
- ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_MEMBER)
- };
- ErrorDescription() { internal_memset(this, 0, sizeof(*this)); }
- explicit ErrorDescription(LinkerInitialized) {}
- ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_CONSTRUCTOR)
- bool IsValid() { return kind != kErrorKindInvalid; }
- void Print() {
- switch (kind) {
- ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_PRINT)
- case kErrorKindInvalid:
- CHECK(0);
- }
- CHECK(0);
- }
- };
- #undef ASAN_FOR_EACH_ERROR_KIND
- #undef ASAN_DEFINE_ERROR_KIND
- #undef ASAN_ERROR_DESCRIPTION_MEMBER
- #undef ASAN_ERROR_DESCRIPTION_CONSTRUCTOR
- #undef ASAN_ERROR_DESCRIPTION_PRINT
- } // namespace __asan
- #endif // ASAN_ERRORS_H
|