Home | History | Annotate | Line # | Download | only in asan
      1 //===-- asan_errors.h -------------------------------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file is a part of AddressSanitizer, an address sanity checker.
     11 //
     12 // ASan-private header for error structures.
     13 //===----------------------------------------------------------------------===//
     14 #ifndef ASAN_ERRORS_H
     15 #define ASAN_ERRORS_H
     16 
     17 #include "asan_descriptions.h"
     18 #include "asan_scariness_score.h"
     19 #include "sanitizer_common/sanitizer_common.h"
     20 
     21 namespace __asan {
     22 
     23 // (*) VS2013 does not implement unrestricted unions, so we need a trivial
     24 // default constructor explicitly defined for each particular error.
     25 
     26 // None of the error classes own the stack traces mentioned in them.
     27 
     28 struct ErrorBase {
     29   ScarinessScoreBase scariness;
     30   u32 tid;
     31 
     32   ErrorBase() = default;  // (*)
     33   explicit ErrorBase(u32 tid_) : tid(tid_) {}
     34   ErrorBase(u32 tid_, int initial_score, const char *reason) : tid(tid_) {
     35     scariness.Clear();
     36     scariness.Scare(initial_score, reason);
     37   }
     38 };
     39 
     40 struct ErrorDeadlySignal : ErrorBase {
     41   SignalContext signal;
     42 
     43   ErrorDeadlySignal() = default;  // (*)
     44   ErrorDeadlySignal(u32 tid, const SignalContext &sig)
     45       : ErrorBase(tid),
     46         signal(sig) {
     47     scariness.Clear();
     48     if (signal.IsStackOverflow()) {
     49       scariness.Scare(10, "stack-overflow");
     50     } else if (!signal.is_memory_access) {
     51       scariness.Scare(10, "signal");
     52     } else if (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 ErrorPvallocOverflow : ErrorBase {
    168   const BufferedStackTrace *stack;
    169   uptr size;
    170 
    171   ErrorPvallocOverflow() = default;  // (*)
    172   ErrorPvallocOverflow(u32 tid, BufferedStackTrace *stack_, uptr size_)
    173       : ErrorBase(tid, 10, "pvalloc-overflow"),
    174         stack(stack_),
    175         size(size_) {}
    176   void Print();
    177 };
    178 
    179 struct ErrorInvalidAllocationAlignment : ErrorBase {
    180   const BufferedStackTrace *stack;
    181   uptr alignment;
    182 
    183   ErrorInvalidAllocationAlignment() = default;  // (*)
    184   ErrorInvalidAllocationAlignment(u32 tid, BufferedStackTrace *stack_,
    185                                   uptr alignment_)
    186       : ErrorBase(tid, 10, "invalid-allocation-alignment"),
    187         stack(stack_),
    188         alignment(alignment_) {}
    189   void Print();
    190 };
    191 
    192 struct ErrorInvalidAlignedAllocAlignment : ErrorBase {
    193   const BufferedStackTrace *stack;
    194   uptr size;
    195   uptr alignment;
    196 
    197   ErrorInvalidAlignedAllocAlignment() = default;  // (*)
    198   ErrorInvalidAlignedAllocAlignment(u32 tid, BufferedStackTrace *stack_,
    199                                     uptr size_, uptr alignment_)
    200       : ErrorBase(tid, 10, "invalid-aligned-alloc-alignment"),
    201         stack(stack_),
    202         size(size_),
    203         alignment(alignment_) {}
    204   void Print();
    205 };
    206 
    207 struct ErrorInvalidPosixMemalignAlignment : ErrorBase {
    208   const BufferedStackTrace *stack;
    209   uptr alignment;
    210 
    211   ErrorInvalidPosixMemalignAlignment() = default;  // (*)
    212   ErrorInvalidPosixMemalignAlignment(u32 tid, BufferedStackTrace *stack_,
    213                                      uptr alignment_)
    214       : ErrorBase(tid, 10, "invalid-posix-memalign-alignment"),
    215         stack(stack_),
    216         alignment(alignment_) {}
    217   void Print();
    218 };
    219 
    220 struct ErrorAllocationSizeTooBig : ErrorBase {
    221   const BufferedStackTrace *stack;
    222   uptr user_size;
    223   uptr total_size;
    224   uptr max_size;
    225 
    226   ErrorAllocationSizeTooBig() = default;  // (*)
    227   ErrorAllocationSizeTooBig(u32 tid, BufferedStackTrace *stack_,
    228                             uptr user_size_, uptr total_size_, uptr max_size_)
    229       : ErrorBase(tid, 10, "allocation-size-too-big"),
    230         stack(stack_),
    231         user_size(user_size_),
    232         total_size(total_size_),
    233         max_size(max_size_) {}
    234   void Print();
    235 };
    236 
    237 struct ErrorRssLimitExceeded : ErrorBase {
    238   const BufferedStackTrace *stack;
    239 
    240   ErrorRssLimitExceeded() = default;  // (*)
    241   ErrorRssLimitExceeded(u32 tid, BufferedStackTrace *stack_)
    242       : ErrorBase(tid, 10, "rss-limit-exceeded"),
    243         stack(stack_) {}
    244   void Print();
    245 };
    246 
    247 struct ErrorOutOfMemory : ErrorBase {
    248   const BufferedStackTrace *stack;
    249   uptr requested_size;
    250 
    251   ErrorOutOfMemory() = default;  // (*)
    252   ErrorOutOfMemory(u32 tid, BufferedStackTrace *stack_, uptr requested_size_)
    253       : ErrorBase(tid, 10, "out-of-memory"),
    254         stack(stack_),
    255         requested_size(requested_size_) {}
    256   void Print();
    257 };
    258 
    259 struct ErrorStringFunctionMemoryRangesOverlap : ErrorBase {
    260   const BufferedStackTrace *stack;
    261   uptr length1, length2;
    262   AddressDescription addr1_description;
    263   AddressDescription addr2_description;
    264   const char *function;
    265 
    266   ErrorStringFunctionMemoryRangesOverlap() = default;  // (*)
    267   ErrorStringFunctionMemoryRangesOverlap(u32 tid, BufferedStackTrace *stack_,
    268                                          uptr addr1, uptr length1_, uptr addr2,
    269                                          uptr length2_, const char *function_)
    270       : ErrorBase(tid),
    271         stack(stack_),
    272         length1(length1_),
    273         length2(length2_),
    274         addr1_description(addr1, length1, /*shouldLockThreadRegistry=*/false),
    275         addr2_description(addr2, length2, /*shouldLockThreadRegistry=*/false),
    276         function(function_) {
    277     char bug_type[100];
    278     internal_snprintf(bug_type, sizeof(bug_type), "%s-param-overlap", function);
    279     scariness.Clear();
    280     scariness.Scare(10, bug_type);
    281   }
    282   void Print();
    283 };
    284 
    285 struct ErrorStringFunctionSizeOverflow : ErrorBase {
    286   const BufferedStackTrace *stack;
    287   AddressDescription addr_description;
    288   uptr size;
    289 
    290   ErrorStringFunctionSizeOverflow() = default;  // (*)
    291   ErrorStringFunctionSizeOverflow(u32 tid, BufferedStackTrace *stack_,
    292                                   uptr addr, uptr size_)
    293       : ErrorBase(tid, 10, "negative-size-param"),
    294         stack(stack_),
    295         addr_description(addr, /*shouldLockThreadRegistry=*/false),
    296         size(size_) {}
    297   void Print();
    298 };
    299 
    300 struct ErrorBadParamsToAnnotateContiguousContainer : ErrorBase {
    301   const BufferedStackTrace *stack;
    302   uptr beg, end, old_mid, new_mid;
    303 
    304   ErrorBadParamsToAnnotateContiguousContainer() = default;  // (*)
    305   // PS4: Do we want an AddressDescription for beg?
    306   ErrorBadParamsToAnnotateContiguousContainer(u32 tid,
    307                                               BufferedStackTrace *stack_,
    308                                               uptr beg_, uptr end_,
    309                                               uptr old_mid_, uptr new_mid_)
    310       : ErrorBase(tid, 10, "bad-__sanitizer_annotate_contiguous_container"),
    311         stack(stack_),
    312         beg(beg_),
    313         end(end_),
    314         old_mid(old_mid_),
    315         new_mid(new_mid_) {}
    316   void Print();
    317 };
    318 
    319 struct ErrorODRViolation : ErrorBase {
    320   __asan_global global1, global2;
    321   u32 stack_id1, stack_id2;
    322 
    323   ErrorODRViolation() = default;  // (*)
    324   ErrorODRViolation(u32 tid, const __asan_global *g1, u32 stack_id1_,
    325                     const __asan_global *g2, u32 stack_id2_)
    326       : ErrorBase(tid, 10, "odr-violation"),
    327         global1(*g1),
    328         global2(*g2),
    329         stack_id1(stack_id1_),
    330         stack_id2(stack_id2_) {}
    331   void Print();
    332 };
    333 
    334 struct ErrorInvalidPointerPair : ErrorBase {
    335   uptr pc, bp, sp;
    336   AddressDescription addr1_description;
    337   AddressDescription addr2_description;
    338 
    339   ErrorInvalidPointerPair() = default;  // (*)
    340   ErrorInvalidPointerPair(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr p1,
    341                           uptr p2)
    342       : ErrorBase(tid, 10, "invalid-pointer-pair"),
    343         pc(pc_),
    344         bp(bp_),
    345         sp(sp_),
    346         addr1_description(p1, 1, /*shouldLockThreadRegistry=*/false),
    347         addr2_description(p2, 1, /*shouldLockThreadRegistry=*/false) {}
    348   void Print();
    349 };
    350 
    351 struct ErrorGeneric : ErrorBase {
    352   AddressDescription addr_description;
    353   uptr pc, bp, sp;
    354   uptr access_size;
    355   const char *bug_descr;
    356   bool is_write;
    357   u8 shadow_val;
    358 
    359   ErrorGeneric() = default;  // (*)
    360   ErrorGeneric(u32 tid, uptr addr, uptr pc_, uptr bp_, uptr sp_, bool is_write_,
    361                uptr access_size_);
    362   void Print();
    363 };
    364 
    365 // clang-format off
    366 #define ASAN_FOR_EACH_ERROR_KIND(macro)         \
    367   macro(DeadlySignal)                           \
    368   macro(DoubleFree)                             \
    369   macro(NewDeleteTypeMismatch)                  \
    370   macro(FreeNotMalloced)                        \
    371   macro(AllocTypeMismatch)                      \
    372   macro(MallocUsableSizeNotOwned)               \
    373   macro(SanitizerGetAllocatedSizeNotOwned)      \
    374   macro(CallocOverflow)                         \
    375   macro(PvallocOverflow)                        \
    376   macro(InvalidAllocationAlignment)             \
    377   macro(InvalidAlignedAllocAlignment)           \
    378   macro(InvalidPosixMemalignAlignment)          \
    379   macro(AllocationSizeTooBig)                   \
    380   macro(RssLimitExceeded)                       \
    381   macro(OutOfMemory)                            \
    382   macro(StringFunctionMemoryRangesOverlap)      \
    383   macro(StringFunctionSizeOverflow)             \
    384   macro(BadParamsToAnnotateContiguousContainer) \
    385   macro(ODRViolation)                           \
    386   macro(InvalidPointerPair)                     \
    387   macro(Generic)
    388 // clang-format on
    389 
    390 #define ASAN_DEFINE_ERROR_KIND(name) kErrorKind##name,
    391 #define ASAN_ERROR_DESCRIPTION_MEMBER(name) Error##name name;
    392 #define ASAN_ERROR_DESCRIPTION_CONSTRUCTOR(name) \
    393   ErrorDescription(Error##name const &e) : kind(kErrorKind##name), name(e) {}
    394 #define ASAN_ERROR_DESCRIPTION_PRINT(name) \
    395   case kErrorKind##name:                   \
    396     return name.Print();
    397 
    398 enum ErrorKind {
    399   kErrorKindInvalid = 0,
    400   ASAN_FOR_EACH_ERROR_KIND(ASAN_DEFINE_ERROR_KIND)
    401 };
    402 
    403 struct ErrorDescription {
    404   ErrorKind kind;
    405   // We're using a tagged union because it allows us to have a trivially
    406   // copiable type and use the same structures as the public interface.
    407   //
    408   // We can add a wrapper around it to make it "more c++-like", but that would
    409   // add a lot of code and the benefit wouldn't be that big.
    410   union {
    411     ErrorBase Base;
    412     ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_MEMBER)
    413   };
    414 
    415   ErrorDescription() { internal_memset(this, 0, sizeof(*this)); }
    416   explicit ErrorDescription(LinkerInitialized) {}
    417   ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_CONSTRUCTOR)
    418 
    419   bool IsValid() { return kind != kErrorKindInvalid; }
    420   void Print() {
    421     switch (kind) {
    422       ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_PRINT)
    423       case kErrorKindInvalid:
    424         CHECK(0);
    425     }
    426     CHECK(0);
    427   }
    428 };
    429 
    430 #undef ASAN_FOR_EACH_ERROR_KIND
    431 #undef ASAN_DEFINE_ERROR_KIND
    432 #undef ASAN_ERROR_DESCRIPTION_MEMBER
    433 #undef ASAN_ERROR_DESCRIPTION_CONSTRUCTOR
    434 #undef ASAN_ERROR_DESCRIPTION_PRINT
    435 
    436 }  // namespace __asan
    437 
    438 #endif  // ASAN_ERRORS_H
    439