Home | History | Annotate | Line # | Download | only in asan
asan_errors.h revision 1.1.1.4
      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 addr, uptr pc_, uptr bp_, uptr sp_, 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
    457