(root)/
gcc-13.2.0/
libsanitizer/
asan/
asan_errors.h
       1  //===-- asan_errors.h -------------------------------------------*- C++ -*-===//
       2  //
       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
       6  //
       7  //===----------------------------------------------------------------------===//
       8  //
       9  // This file is a part of AddressSanitizer, an address sanity checker.
      10  //
      11  // ASan-private header for error structures.
      12  //===----------------------------------------------------------------------===//
      13  #ifndef ASAN_ERRORS_H
      14  #define ASAN_ERRORS_H
      15  
      16  #include "asan_descriptions.h"
      17  #include "asan_scariness_score.h"
      18  #include "sanitizer_common/sanitizer_common.h"
      19  
      20  namespace __asan {
      21  
      22  // (*) VS2013 does not implement unrestricted unions, so we need a trivial
      23  // default constructor explicitly defined for each particular error.
      24  
      25  // None of the error classes own the stack traces mentioned in them.
      26  
      27  struct ErrorBase {
      28    ScarinessScoreBase scariness;
      29    u32 tid;
      30  
      31    ErrorBase() = default;  // (*)
      32    explicit ErrorBase(u32 tid_) : tid(tid_) {}
      33    ErrorBase(u32 tid_, int initial_score, const char *reason) : tid(tid_) {
      34      scariness.Clear();
      35      scariness.Scare(initial_score, reason);
      36    }
      37  };
      38  
      39  struct ErrorDeadlySignal : ErrorBase {
      40    SignalContext signal;
      41  
      42    ErrorDeadlySignal() = default;  // (*)
      43    ErrorDeadlySignal(u32 tid, const SignalContext &sig)
      44        : ErrorBase(tid),
      45          signal(sig) {
      46      scariness.Clear();
      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");
      60      } else {
      61        scariness.Scare(25, "wild-addr");
      62      }
      63    }
      64    void Print();
      65  };
      66  
      67  struct ErrorDoubleFree : ErrorBase {
      68    const BufferedStackTrace *second_free_stack;
      69    HeapAddressDescription addr_description;
      70  
      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);
      77    }
      78    void Print();
      79  };
      80  
      81  struct ErrorNewDeleteTypeMismatch : ErrorBase {
      82    const BufferedStackTrace *free_stack;
      83    HeapAddressDescription addr_description;
      84    uptr delete_size;
      85    uptr delete_alignment;
      86  
      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"),
      91          free_stack(stack),
      92          delete_size(delete_size_),
      93          delete_alignment(delete_alignment_) {
      94      GetHeapAddressInformation(addr, 1, &addr_description);
      95    }
      96    void Print();
      97  };
      98  
      99  struct ErrorFreeNotMalloced : ErrorBase {
     100    const BufferedStackTrace *free_stack;
     101    AddressDescription addr_description;
     102  
     103    ErrorFreeNotMalloced() = default;  // (*)
     104    ErrorFreeNotMalloced(u32 tid, BufferedStackTrace *stack, uptr addr)
     105        : ErrorBase(tid, 40, "bad-free"),
     106          free_stack(stack),
     107          addr_description(addr, /*shouldLockThreadRegistry=*/false) {}
     108    void Print();
     109  };
     110  
     111  struct ErrorAllocTypeMismatch : ErrorBase {
     112    const BufferedStackTrace *dealloc_stack;
     113    AllocType alloc_type, dealloc_type;
     114    AddressDescription addr_description;
     115  
     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) {}
     124    void Print();
     125  };
     126  
     127  struct ErrorMallocUsableSizeNotOwned : ErrorBase {
     128    const BufferedStackTrace *stack;
     129    AddressDescription addr_description;
     130  
     131    ErrorMallocUsableSizeNotOwned() = default;  // (*)
     132    ErrorMallocUsableSizeNotOwned(u32 tid, BufferedStackTrace *stack_, uptr addr)
     133        : ErrorBase(tid, 10, "bad-malloc_usable_size"),
     134          stack(stack_),
     135          addr_description(addr, /*shouldLockThreadRegistry=*/false) {}
     136    void Print();
     137  };
     138  
     139  struct ErrorSanitizerGetAllocatedSizeNotOwned : ErrorBase {
     140    const BufferedStackTrace *stack;
     141    AddressDescription addr_description;
     142  
     143    ErrorSanitizerGetAllocatedSizeNotOwned() = default;  // (*)
     144    ErrorSanitizerGetAllocatedSizeNotOwned(u32 tid, BufferedStackTrace *stack_,
     145                                           uptr addr)
     146        : ErrorBase(tid, 10, "bad-__sanitizer_get_allocated_size"),
     147          stack(stack_),
     148          addr_description(addr, /*shouldLockThreadRegistry=*/false) {}
     149    void Print();
     150  };
     151  
     152  struct ErrorCallocOverflow : ErrorBase {
     153    const BufferedStackTrace *stack;
     154    uptr count;
     155    uptr size;
     156  
     157    ErrorCallocOverflow() = default;  // (*)
     158    ErrorCallocOverflow(u32 tid, BufferedStackTrace *stack_, uptr count_,
     159                        uptr size_)
     160        : ErrorBase(tid, 10, "calloc-overflow"),
     161          stack(stack_),
     162          count(count_),
     163          size(size_) {}
     164    void Print();
     165  };
     166  
     167  struct ErrorReallocArrayOverflow : ErrorBase {
     168    const BufferedStackTrace *stack;
     169    uptr count;
     170    uptr size;
     171  
     172    ErrorReallocArrayOverflow() = default;  // (*)
     173    ErrorReallocArrayOverflow(u32 tid, BufferedStackTrace *stack_, uptr count_,
     174                              uptr size_)
     175        : ErrorBase(tid, 10, "reallocarray-overflow"),
     176          stack(stack_),
     177          count(count_),
     178          size(size_) {}
     179    void Print();
     180  };
     181  
     182  struct ErrorPvallocOverflow : ErrorBase {
     183    const BufferedStackTrace *stack;
     184    uptr size;
     185  
     186    ErrorPvallocOverflow() = default;  // (*)
     187    ErrorPvallocOverflow(u32 tid, BufferedStackTrace *stack_, uptr size_)
     188        : ErrorBase(tid, 10, "pvalloc-overflow"),
     189          stack(stack_),
     190          size(size_) {}
     191    void Print();
     192  };
     193  
     194  struct ErrorInvalidAllocationAlignment : ErrorBase {
     195    const BufferedStackTrace *stack;
     196    uptr alignment;
     197  
     198    ErrorInvalidAllocationAlignment() = default;  // (*)
     199    ErrorInvalidAllocationAlignment(u32 tid, BufferedStackTrace *stack_,
     200                                    uptr alignment_)
     201        : ErrorBase(tid, 10, "invalid-allocation-alignment"),
     202          stack(stack_),
     203          alignment(alignment_) {}
     204    void Print();
     205  };
     206  
     207  struct ErrorInvalidAlignedAllocAlignment : ErrorBase {
     208    const BufferedStackTrace *stack;
     209    uptr size;
     210    uptr alignment;
     211  
     212    ErrorInvalidAlignedAllocAlignment() = default;  // (*)
     213    ErrorInvalidAlignedAllocAlignment(u32 tid, BufferedStackTrace *stack_,
     214                                      uptr size_, uptr alignment_)
     215        : ErrorBase(tid, 10, "invalid-aligned-alloc-alignment"),
     216          stack(stack_),
     217          size(size_),
     218          alignment(alignment_) {}
     219    void Print();
     220  };
     221  
     222  struct ErrorInvalidPosixMemalignAlignment : ErrorBase {
     223    const BufferedStackTrace *stack;
     224    uptr alignment;
     225  
     226    ErrorInvalidPosixMemalignAlignment() = default;  // (*)
     227    ErrorInvalidPosixMemalignAlignment(u32 tid, BufferedStackTrace *stack_,
     228                                       uptr alignment_)
     229        : ErrorBase(tid, 10, "invalid-posix-memalign-alignment"),
     230          stack(stack_),
     231          alignment(alignment_) {}
     232    void Print();
     233  };
     234  
     235  struct ErrorAllocationSizeTooBig : ErrorBase {
     236    const BufferedStackTrace *stack;
     237    uptr user_size;
     238    uptr total_size;
     239    uptr max_size;
     240  
     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"),
     245          stack(stack_),
     246          user_size(user_size_),
     247          total_size(total_size_),
     248          max_size(max_size_) {}
     249    void Print();
     250  };
     251  
     252  struct ErrorRssLimitExceeded : ErrorBase {
     253    const BufferedStackTrace *stack;
     254  
     255    ErrorRssLimitExceeded() = default;  // (*)
     256    ErrorRssLimitExceeded(u32 tid, BufferedStackTrace *stack_)
     257        : ErrorBase(tid, 10, "rss-limit-exceeded"),
     258          stack(stack_) {}
     259    void Print();
     260  };
     261  
     262  struct ErrorOutOfMemory : ErrorBase {
     263    const BufferedStackTrace *stack;
     264    uptr requested_size;
     265  
     266    ErrorOutOfMemory() = default;  // (*)
     267    ErrorOutOfMemory(u32 tid, BufferedStackTrace *stack_, uptr requested_size_)
     268        : ErrorBase(tid, 10, "out-of-memory"),
     269          stack(stack_),
     270          requested_size(requested_size_) {}
     271    void Print();
     272  };
     273  
     274  struct ErrorStringFunctionMemoryRangesOverlap : ErrorBase {
     275    const BufferedStackTrace *stack;
     276    uptr length1, length2;
     277    AddressDescription addr1_description;
     278    AddressDescription addr2_description;
     279    const char *function;
     280  
     281    ErrorStringFunctionMemoryRangesOverlap() = default;  // (*)
     282    ErrorStringFunctionMemoryRangesOverlap(u32 tid, BufferedStackTrace *stack_,
     283                                           uptr addr1, uptr length1_, uptr addr2,
     284                                           uptr length2_, const char *function_)
     285        : ErrorBase(tid),
     286          stack(stack_),
     287          length1(length1_),
     288          length2(length2_),
     289          addr1_description(addr1, length1, /*shouldLockThreadRegistry=*/false),
     290          addr2_description(addr2, length2, /*shouldLockThreadRegistry=*/false),
     291          function(function_) {
     292      char bug_type[100];
     293      internal_snprintf(bug_type, sizeof(bug_type), "%s-param-overlap", function);
     294      scariness.Clear();
     295      scariness.Scare(10, bug_type);
     296    }
     297    void Print();
     298  };
     299  
     300  struct ErrorStringFunctionSizeOverflow : ErrorBase {
     301    const BufferedStackTrace *stack;
     302    AddressDescription addr_description;
     303    uptr size;
     304  
     305    ErrorStringFunctionSizeOverflow() = default;  // (*)
     306    ErrorStringFunctionSizeOverflow(u32 tid, BufferedStackTrace *stack_,
     307                                    uptr addr, uptr size_)
     308        : ErrorBase(tid, 10, "negative-size-param"),
     309          stack(stack_),
     310          addr_description(addr, /*shouldLockThreadRegistry=*/false),
     311          size(size_) {}
     312    void Print();
     313  };
     314  
     315  struct ErrorBadParamsToAnnotateContiguousContainer : ErrorBase {
     316    const BufferedStackTrace *stack;
     317    uptr beg, end, old_mid, new_mid;
     318  
     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"),
     326          stack(stack_),
     327          beg(beg_),
     328          end(end_),
     329          old_mid(old_mid_),
     330          new_mid(new_mid_) {}
     331    void Print();
     332  };
     333  
     334  struct ErrorODRViolation : ErrorBase {
     335    __asan_global global1, global2;
     336    u32 stack_id1, stack_id2;
     337  
     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"),
     342          global1(*g1),
     343          global2(*g2),
     344          stack_id1(stack_id1_),
     345          stack_id2(stack_id2_) {}
     346    void Print();
     347  };
     348  
     349  struct ErrorInvalidPointerPair : ErrorBase {
     350    uptr pc, bp, sp;
     351    AddressDescription addr1_description;
     352    AddressDescription addr2_description;
     353  
     354    ErrorInvalidPointerPair() = default;  // (*)
     355    ErrorInvalidPointerPair(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr p1,
     356                            uptr p2)
     357        : ErrorBase(tid, 10, "invalid-pointer-pair"),
     358          pc(pc_),
     359          bp(bp_),
     360          sp(sp_),
     361          addr1_description(p1, 1, /*shouldLockThreadRegistry=*/false),
     362          addr2_description(p2, 1, /*shouldLockThreadRegistry=*/false) {}
     363    void Print();
     364  };
     365  
     366  struct ErrorGeneric : ErrorBase {
     367    AddressDescription addr_description;
     368    uptr pc, bp, sp;
     369    uptr access_size;
     370    const char *bug_descr;
     371    bool is_write;
     372    u8 shadow_val;
     373  
     374    ErrorGeneric() = default;  // (*)
     375    ErrorGeneric(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr addr, bool is_write_,
     376                 uptr access_size_);
     377    void Print();
     378  };
     379  
     380  // clang-format off
     381  #define ASAN_FOR_EACH_ERROR_KIND(macro)         \
     382    macro(DeadlySignal)                           \
     383    macro(DoubleFree)                             \
     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)                       \
     397    macro(OutOfMemory)                            \
     398    macro(StringFunctionMemoryRangesOverlap)      \
     399    macro(StringFunctionSizeOverflow)             \
     400    macro(BadParamsToAnnotateContiguousContainer) \
     401    macro(ODRViolation)                           \
     402    macro(InvalidPointerPair)                     \
     403    macro(Generic)
     404  // clang-format on
     405  
     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));                       \
     411    }
     412  #define ASAN_ERROR_DESCRIPTION_PRINT(name) \
     413    case kErrorKind##name:                   \
     414      return name.Print();
     415  
     416  enum ErrorKind {
     417    kErrorKindInvalid = 0,
     418    ASAN_FOR_EACH_ERROR_KIND(ASAN_DEFINE_ERROR_KIND)
     419  };
     420  
     421  struct ErrorDescription {
     422    ErrorKind kind;
     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.
     425    //
     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.
     428    union {
     429      ErrorBase Base;
     430      ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_MEMBER)
     431    };
     432  
     433    ErrorDescription() { internal_memset(this, 0, sizeof(*this)); }
     434    explicit ErrorDescription(LinkerInitialized) {}
     435    ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_CONSTRUCTOR)
     436  
     437    bool IsValid() { return kind != kErrorKindInvalid; }
     438    void Print() {
     439      switch (kind) {
     440        ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_PRINT)
     441        case kErrorKindInvalid:
     442          CHECK(0);
     443      }
     444      CHECK(0);
     445    }
     446  };
     447  
     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
     453  
     454  }  // namespace __asan
     455  
     456  #endif  // ASAN_ERRORS_H