Path: blob/main/contrib/llvm-project/compiler-rt/lib/asan/asan_errors.h
35233 views
//===-- asan_errors.h -------------------------------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file is a part of AddressSanitizer, an address sanity checker.9//10// ASan-private header for error structures.11//===----------------------------------------------------------------------===//12#ifndef ASAN_ERRORS_H13#define ASAN_ERRORS_H1415#include "asan_descriptions.h"16#include "asan_scariness_score.h"17#include "sanitizer_common/sanitizer_common.h"1819namespace __asan {2021// (*) VS2013 does not implement unrestricted unions, so we need a trivial22// default constructor explicitly defined for each particular error.2324// None of the error classes own the stack traces mentioned in them.2526struct ErrorBase {27ScarinessScoreBase scariness;28u32 tid;2930ErrorBase() = default; // (*)31explicit ErrorBase(u32 tid_) : tid(tid_) {}32ErrorBase(u32 tid_, int initial_score, const char *reason) : tid(tid_) {33scariness.Clear();34scariness.Scare(initial_score, reason);35}36};3738struct ErrorDeadlySignal : ErrorBase {39SignalContext signal;4041ErrorDeadlySignal() = default; // (*)42ErrorDeadlySignal(u32 tid, const SignalContext &sig)43: ErrorBase(tid),44signal(sig) {45scariness.Clear();46if (signal.IsStackOverflow()) {47scariness.Scare(10, "stack-overflow");48} else if (!signal.is_memory_access) {49scariness.Scare(10, "signal");50} else if (signal.is_true_faulting_addr &&51signal.addr < GetPageSizeCached()) {52scariness.Scare(10, "null-deref");53} else if (signal.addr == signal.pc) {54scariness.Scare(60, "wild-jump");55} else if (signal.write_flag == SignalContext::Write) {56scariness.Scare(30, "wild-addr-write");57} else if (signal.write_flag == SignalContext::Read) {58scariness.Scare(20, "wild-addr-read");59} else {60scariness.Scare(25, "wild-addr");61}62}63void Print();64};6566struct ErrorDoubleFree : ErrorBase {67const BufferedStackTrace *second_free_stack;68HeapAddressDescription addr_description;6970ErrorDoubleFree() = default; // (*)71ErrorDoubleFree(u32 tid, BufferedStackTrace *stack, uptr addr)72: ErrorBase(tid, 42, "double-free"),73second_free_stack(stack) {74CHECK_GT(second_free_stack->size, 0);75GetHeapAddressInformation(addr, 1, &addr_description);76}77void Print();78};7980struct ErrorNewDeleteTypeMismatch : ErrorBase {81const BufferedStackTrace *free_stack;82HeapAddressDescription addr_description;83uptr delete_size;84uptr delete_alignment;8586ErrorNewDeleteTypeMismatch() = default; // (*)87ErrorNewDeleteTypeMismatch(u32 tid, BufferedStackTrace *stack, uptr addr,88uptr delete_size_, uptr delete_alignment_)89: ErrorBase(tid, 10, "new-delete-type-mismatch"),90free_stack(stack),91delete_size(delete_size_),92delete_alignment(delete_alignment_) {93GetHeapAddressInformation(addr, 1, &addr_description);94}95void Print();96};9798struct ErrorFreeNotMalloced : ErrorBase {99const BufferedStackTrace *free_stack;100AddressDescription addr_description;101102ErrorFreeNotMalloced() = default; // (*)103ErrorFreeNotMalloced(u32 tid, BufferedStackTrace *stack, uptr addr)104: ErrorBase(tid, 40, "bad-free"),105free_stack(stack),106addr_description(addr, /*shouldLockThreadRegistry=*/false) {}107void Print();108};109110struct ErrorAllocTypeMismatch : ErrorBase {111const BufferedStackTrace *dealloc_stack;112AllocType alloc_type, dealloc_type;113AddressDescription addr_description;114115ErrorAllocTypeMismatch() = default; // (*)116ErrorAllocTypeMismatch(u32 tid, BufferedStackTrace *stack, uptr addr,117AllocType alloc_type_, AllocType dealloc_type_)118: ErrorBase(tid, 10, "alloc-dealloc-mismatch"),119dealloc_stack(stack),120alloc_type(alloc_type_),121dealloc_type(dealloc_type_),122addr_description(addr, 1, false) {}123void Print();124};125126struct ErrorMallocUsableSizeNotOwned : ErrorBase {127const BufferedStackTrace *stack;128AddressDescription addr_description;129130ErrorMallocUsableSizeNotOwned() = default; // (*)131ErrorMallocUsableSizeNotOwned(u32 tid, BufferedStackTrace *stack_, uptr addr)132: ErrorBase(tid, 10, "bad-malloc_usable_size"),133stack(stack_),134addr_description(addr, /*shouldLockThreadRegistry=*/false) {}135void Print();136};137138struct ErrorSanitizerGetAllocatedSizeNotOwned : ErrorBase {139const BufferedStackTrace *stack;140AddressDescription addr_description;141142ErrorSanitizerGetAllocatedSizeNotOwned() = default; // (*)143ErrorSanitizerGetAllocatedSizeNotOwned(u32 tid, BufferedStackTrace *stack_,144uptr addr)145: ErrorBase(tid, 10, "bad-__sanitizer_get_allocated_size"),146stack(stack_),147addr_description(addr, /*shouldLockThreadRegistry=*/false) {}148void Print();149};150151struct ErrorCallocOverflow : ErrorBase {152const BufferedStackTrace *stack;153uptr count;154uptr size;155156ErrorCallocOverflow() = default; // (*)157ErrorCallocOverflow(u32 tid, BufferedStackTrace *stack_, uptr count_,158uptr size_)159: ErrorBase(tid, 10, "calloc-overflow"),160stack(stack_),161count(count_),162size(size_) {}163void Print();164};165166struct ErrorReallocArrayOverflow : ErrorBase {167const BufferedStackTrace *stack;168uptr count;169uptr size;170171ErrorReallocArrayOverflow() = default; // (*)172ErrorReallocArrayOverflow(u32 tid, BufferedStackTrace *stack_, uptr count_,173uptr size_)174: ErrorBase(tid, 10, "reallocarray-overflow"),175stack(stack_),176count(count_),177size(size_) {}178void Print();179};180181struct ErrorPvallocOverflow : ErrorBase {182const BufferedStackTrace *stack;183uptr size;184185ErrorPvallocOverflow() = default; // (*)186ErrorPvallocOverflow(u32 tid, BufferedStackTrace *stack_, uptr size_)187: ErrorBase(tid, 10, "pvalloc-overflow"),188stack(stack_),189size(size_) {}190void Print();191};192193struct ErrorInvalidAllocationAlignment : ErrorBase {194const BufferedStackTrace *stack;195uptr alignment;196197ErrorInvalidAllocationAlignment() = default; // (*)198ErrorInvalidAllocationAlignment(u32 tid, BufferedStackTrace *stack_,199uptr alignment_)200: ErrorBase(tid, 10, "invalid-allocation-alignment"),201stack(stack_),202alignment(alignment_) {}203void Print();204};205206struct ErrorInvalidAlignedAllocAlignment : ErrorBase {207const BufferedStackTrace *stack;208uptr size;209uptr alignment;210211ErrorInvalidAlignedAllocAlignment() = default; // (*)212ErrorInvalidAlignedAllocAlignment(u32 tid, BufferedStackTrace *stack_,213uptr size_, uptr alignment_)214: ErrorBase(tid, 10, "invalid-aligned-alloc-alignment"),215stack(stack_),216size(size_),217alignment(alignment_) {}218void Print();219};220221struct ErrorInvalidPosixMemalignAlignment : ErrorBase {222const BufferedStackTrace *stack;223uptr alignment;224225ErrorInvalidPosixMemalignAlignment() = default; // (*)226ErrorInvalidPosixMemalignAlignment(u32 tid, BufferedStackTrace *stack_,227uptr alignment_)228: ErrorBase(tid, 10, "invalid-posix-memalign-alignment"),229stack(stack_),230alignment(alignment_) {}231void Print();232};233234struct ErrorAllocationSizeTooBig : ErrorBase {235const BufferedStackTrace *stack;236uptr user_size;237uptr total_size;238uptr max_size;239240ErrorAllocationSizeTooBig() = default; // (*)241ErrorAllocationSizeTooBig(u32 tid, BufferedStackTrace *stack_,242uptr user_size_, uptr total_size_, uptr max_size_)243: ErrorBase(tid, 10, "allocation-size-too-big"),244stack(stack_),245user_size(user_size_),246total_size(total_size_),247max_size(max_size_) {}248void Print();249};250251struct ErrorRssLimitExceeded : ErrorBase {252const BufferedStackTrace *stack;253254ErrorRssLimitExceeded() = default; // (*)255ErrorRssLimitExceeded(u32 tid, BufferedStackTrace *stack_)256: ErrorBase(tid, 10, "rss-limit-exceeded"),257stack(stack_) {}258void Print();259};260261struct ErrorOutOfMemory : ErrorBase {262const BufferedStackTrace *stack;263uptr requested_size;264265ErrorOutOfMemory() = default; // (*)266ErrorOutOfMemory(u32 tid, BufferedStackTrace *stack_, uptr requested_size_)267: ErrorBase(tid, 10, "out-of-memory"),268stack(stack_),269requested_size(requested_size_) {}270void Print();271};272273struct ErrorStringFunctionMemoryRangesOverlap : ErrorBase {274const BufferedStackTrace *stack;275uptr length1, length2;276AddressDescription addr1_description;277AddressDescription addr2_description;278const char *function;279280ErrorStringFunctionMemoryRangesOverlap() = default; // (*)281ErrorStringFunctionMemoryRangesOverlap(u32 tid, BufferedStackTrace *stack_,282uptr addr1, uptr length1_, uptr addr2,283uptr length2_, const char *function_)284: ErrorBase(tid),285stack(stack_),286length1(length1_),287length2(length2_),288addr1_description(addr1, length1, /*shouldLockThreadRegistry=*/false),289addr2_description(addr2, length2, /*shouldLockThreadRegistry=*/false),290function(function_) {291char bug_type[100];292internal_snprintf(bug_type, sizeof(bug_type), "%s-param-overlap", function);293scariness.Clear();294scariness.Scare(10, bug_type);295}296void Print();297};298299struct ErrorStringFunctionSizeOverflow : ErrorBase {300const BufferedStackTrace *stack;301AddressDescription addr_description;302uptr size;303304ErrorStringFunctionSizeOverflow() = default; // (*)305ErrorStringFunctionSizeOverflow(u32 tid, BufferedStackTrace *stack_,306uptr addr, uptr size_)307: ErrorBase(tid, 10, "negative-size-param"),308stack(stack_),309addr_description(addr, /*shouldLockThreadRegistry=*/false),310size(size_) {}311void Print();312};313314struct ErrorBadParamsToAnnotateContiguousContainer : ErrorBase {315const BufferedStackTrace *stack;316uptr beg, end, old_mid, new_mid;317318ErrorBadParamsToAnnotateContiguousContainer() = default; // (*)319// PS4: Do we want an AddressDescription for beg?320ErrorBadParamsToAnnotateContiguousContainer(u32 tid,321BufferedStackTrace *stack_,322uptr beg_, uptr end_,323uptr old_mid_, uptr new_mid_)324: ErrorBase(tid, 10, "bad-__sanitizer_annotate_contiguous_container"),325stack(stack_),326beg(beg_),327end(end_),328old_mid(old_mid_),329new_mid(new_mid_) {}330void Print();331};332333struct ErrorBadParamsToAnnotateDoubleEndedContiguousContainer : ErrorBase {334const BufferedStackTrace *stack;335uptr storage_beg, storage_end, old_container_beg, old_container_end,336new_container_beg, new_container_end;337338ErrorBadParamsToAnnotateDoubleEndedContiguousContainer() = default; // (*)339ErrorBadParamsToAnnotateDoubleEndedContiguousContainer(340u32 tid, BufferedStackTrace *stack_, uptr storage_beg_, uptr storage_end_,341uptr old_container_beg_, uptr old_container_end_, uptr new_container_beg_,342uptr new_container_end_)343: ErrorBase(tid, 10,344"bad-__sanitizer_annotate_double_ended_contiguous_container"),345stack(stack_),346storage_beg(storage_beg_),347storage_end(storage_end_),348old_container_beg(old_container_beg_),349old_container_end(old_container_end_),350new_container_beg(new_container_beg_),351new_container_end(new_container_end_) {}352void Print();353};354355struct ErrorODRViolation : ErrorBase {356__asan_global global1, global2;357u32 stack_id1, stack_id2;358359ErrorODRViolation() = default; // (*)360ErrorODRViolation(u32 tid, const __asan_global *g1, u32 stack_id1_,361const __asan_global *g2, u32 stack_id2_)362: ErrorBase(tid, 10, "odr-violation"),363global1(*g1),364global2(*g2),365stack_id1(stack_id1_),366stack_id2(stack_id2_) {}367void Print();368};369370struct ErrorInvalidPointerPair : ErrorBase {371uptr pc, bp, sp;372AddressDescription addr1_description;373AddressDescription addr2_description;374375ErrorInvalidPointerPair() = default; // (*)376ErrorInvalidPointerPair(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr p1,377uptr p2)378: ErrorBase(tid, 10, "invalid-pointer-pair"),379pc(pc_),380bp(bp_),381sp(sp_),382addr1_description(p1, 1, /*shouldLockThreadRegistry=*/false),383addr2_description(p2, 1, /*shouldLockThreadRegistry=*/false) {}384void Print();385};386387struct ErrorGeneric : ErrorBase {388AddressDescription addr_description;389uptr pc, bp, sp;390uptr access_size;391const char *bug_descr;392bool is_write;393u8 shadow_val;394395ErrorGeneric() = default; // (*)396ErrorGeneric(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr addr, bool is_write_,397uptr access_size_);398void Print();399};400401// clang-format off402#define ASAN_FOR_EACH_ERROR_KIND(macro) \403macro(DeadlySignal) \404macro(DoubleFree) \405macro(NewDeleteTypeMismatch) \406macro(FreeNotMalloced) \407macro(AllocTypeMismatch) \408macro(MallocUsableSizeNotOwned) \409macro(SanitizerGetAllocatedSizeNotOwned) \410macro(CallocOverflow) \411macro(ReallocArrayOverflow) \412macro(PvallocOverflow) \413macro(InvalidAllocationAlignment) \414macro(InvalidAlignedAllocAlignment) \415macro(InvalidPosixMemalignAlignment) \416macro(AllocationSizeTooBig) \417macro(RssLimitExceeded) \418macro(OutOfMemory) \419macro(StringFunctionMemoryRangesOverlap) \420macro(StringFunctionSizeOverflow) \421macro(BadParamsToAnnotateContiguousContainer) \422macro(BadParamsToAnnotateDoubleEndedContiguousContainer) \423macro(ODRViolation) \424macro(InvalidPointerPair) \425macro(Generic)426// clang-format on427428#define ASAN_DEFINE_ERROR_KIND(name) kErrorKind##name,429#define ASAN_ERROR_DESCRIPTION_MEMBER(name) Error##name name;430#define ASAN_ERROR_DESCRIPTION_CONSTRUCTOR(name) \431ErrorDescription(Error##name const &e) : kind(kErrorKind##name) { \432internal_memcpy(&name, &e, sizeof(name)); \433}434#define ASAN_ERROR_DESCRIPTION_PRINT(name) \435case kErrorKind##name: \436return name.Print();437438enum ErrorKind {439kErrorKindInvalid = 0,440ASAN_FOR_EACH_ERROR_KIND(ASAN_DEFINE_ERROR_KIND)441};442443struct ErrorDescription {444ErrorKind kind;445// We're using a tagged union because it allows us to have a trivially446// copiable type and use the same structures as the public interface.447//448// We can add a wrapper around it to make it "more c++-like", but that would449// add a lot of code and the benefit wouldn't be that big.450union {451ErrorBase Base;452ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_MEMBER)453};454455ErrorDescription() { internal_memset(this, 0, sizeof(*this)); }456explicit ErrorDescription(LinkerInitialized) {}457ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_CONSTRUCTOR)458459bool IsValid() { return kind != kErrorKindInvalid; }460void Print() {461switch (kind) {462ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_PRINT)463case kErrorKindInvalid:464CHECK(0);465}466CHECK(0);467}468};469470#undef ASAN_FOR_EACH_ERROR_KIND471#undef ASAN_DEFINE_ERROR_KIND472#undef ASAN_ERROR_DESCRIPTION_MEMBER473#undef ASAN_ERROR_DESCRIPTION_CONSTRUCTOR474#undef ASAN_ERROR_DESCRIPTION_PRINT475476} // namespace __asan477478#endif // ASAN_ERRORS_H479480481