Home | History | Annotate | Line # | Download | only in asan
asan_errors.h revision 1.1.1.3
      1 //===-- asan_errors.h -------------------------------------------*- C++ -*-===//
      2 //
      3 // This file is distributed under the University of Illinois Open Source
      4 // License. See LICENSE.TXT for details.
      5 //
      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_H
     13 #define ASAN_ERRORS_H
     14 
     15 #include "asan_descriptions.h"
     16 #include "asan_scariness_score.h"
     17 #include "sanitizer_common/sanitizer_common.h"
     18 
     19 namespace __asan {
     20 
     21 // (*) VS2013 does not implement unrestricted unions, so we need a trivial
     22 // default constructor explicitly defined for each particular error.
     23 
     24 // None of the error classes own the stack traces mentioned in them.
     25 
     26 struct ErrorBase {
     27   ScarinessScoreBase scariness;
     28   u32 tid;
     29 
     30   ErrorBase() = default;  // (*)
     31   explicit ErrorBase(u32 tid_) : tid(tid_) {}
     32   ErrorBase(u32 tid_, int initial_score, const char *reason) : tid(tid_) {
     33     scariness.Clear();
     34     scariness.Scare(initial_score, reason);
     35   }
     36 };
     37 
     38 struct ErrorDeadlySignal : ErrorBase {
     39   SignalContext signal;
     40 
     41   ErrorDeadlySignal() = default;  // (*)
     42   ErrorDeadlySignal(u32 tid, const SignalContext &sig)
     43       : ErrorBase(tid),
     44         signal(sig) {
     45     scariness.Clear();
     46     if (signal.IsStackOverflow()) {
     47       scariness.Scare(10, "stack-overflow");
     48     } else if (!signal.is_memory_access) {
     49       scariness.Scare(10, "signal");
     50     } else if (signal.addr < GetPageSizeCached()) {
     51       scariness.Scare(10, "null-deref");
     52     } else if (signal.addr == signal.pc) {
     53       scariness.Scare(60, "wild-jump");
     54     } else if (signal.write_flag == SignalContext::WRITE) {
     55       scariness.Scare(30, "wild-addr-write");
     56     } else if (signal.write_flag == SignalContext::READ) {
     57       scariness.Scare(20, "wild-addr-read");
     58     } else {
     59       scariness.Scare(25, "wild-addr");
     60     }
     61   }
     62   void Print();
     63 };
     64 
     65 struct ErrorDoubleFree : ErrorBase {
     66   const BufferedStackTrace *second_free_stack;
     67   HeapAddressDescription addr_description;
     68 
     69   ErrorDoubleFree() = default;  // (*)
     70   ErrorDoubleFree(u32 tid, BufferedStackTrace *stack, uptr addr)
     71       : ErrorBase(tid, 42, "double-free"),
     72         second_free_stack(stack) {
     73     CHECK_GT(second_free_stack->size, 0);
     74     GetHeapAddressInformation(addr, 1, &addr_description);
     75   }
     76   void Print();
     77 };
     78 
     79 struct ErrorNewDeleteTypeMismatch : ErrorBase {
     80   const BufferedStackTrace *free_stack;
     81   HeapAddressDescription addr_description;
     82   uptr delete_size;
     83   uptr delete_alignment;
     84 
     85   ErrorNewDeleteTypeMismatch() = default;  // (*)
     86   ErrorNewDeleteTypeMismatch(u32 tid, BufferedStackTrace *stack, uptr addr,
     87                              uptr delete_size_, uptr delete_alignment_)
     88       : ErrorBase(tid, 10, "new-delete-type-mismatch"),
     89         free_stack(stack),
     90         delete_size(delete_size_),
     91         delete_alignment(delete_alignment_) {
     92     GetHeapAddressInformation(addr, 1, &addr_description);
     93   }
     94   void Print();
     95 };
     96 
     97 struct ErrorFreeNotMalloced : ErrorBase {
     98   const BufferedStackTrace *free_stack;
     99   AddressDescription addr_description;
    100 
    101   ErrorFreeNotMalloced() = default;  // (*)
    102   ErrorFreeNotMalloced(u32 tid, BufferedStackTrace *stack, uptr addr)
    103       : ErrorBase(tid, 40, "bad-free"),
    104         free_stack(stack),
    105         addr_description(addr, /*shouldLockThreadRegistry=*/false) {}
    106   void Print();
    107 };
    108 
    109 struct ErrorAllocTypeMismatch : ErrorBase {
    110   const BufferedStackTrace *dealloc_stack;
    111   AllocType alloc_type, dealloc_type;
    112   AddressDescription addr_description;
    113 
    114   ErrorAllocTypeMismatch() = default;  // (*)
    115   ErrorAllocTypeMismatch(u32 tid, BufferedStackTrace *stack, uptr addr,
    116                          AllocType alloc_type_, AllocType dealloc_type_)
    117       : ErrorBase(tid, 10, "alloc-dealloc-mismatch"),
    118         dealloc_stack(stack),
    119         alloc_type(alloc_type_),
    120         dealloc_type(dealloc_type_),
    121         addr_description(addr, 1, false) {}
    122   void Print();
    123 };
    124 
    125 struct ErrorMallocUsableSizeNotOwned : ErrorBase {
    126   const BufferedStackTrace *stack;
    127   AddressDescription addr_description;
    128 
    129   ErrorMallocUsableSizeNotOwned() = default;  // (*)
    130   ErrorMallocUsableSizeNotOwned(u32 tid, BufferedStackTrace *stack_, uptr addr)
    131       : ErrorBase(tid, 10, "bad-malloc_usable_size"),
    132         stack(stack_),
    133         addr_description(addr, /*shouldLockThreadRegistry=*/false) {}
    134   void Print();
    135 };
    136 
    137 struct ErrorSanitizerGetAllocatedSizeNotOwned : ErrorBase {
    138   const BufferedStackTrace *stack;
    139   AddressDescription addr_description;
    140 
    141   ErrorSanitizerGetAllocatedSizeNotOwned() = default;  // (*)
    142   ErrorSanitizerGetAllocatedSizeNotOwned(u32 tid, BufferedStackTrace *stack_,
    143                                          uptr addr)
    144       : ErrorBase(tid, 10, "bad-__sanitizer_get_allocated_size"),
    145         stack(stack_),
    146         addr_description(addr, /*shouldLockThreadRegistry=*/false) {}
    147   void Print();
    148 };
    149 
    150 struct ErrorCallocOverflow : ErrorBase {
    151   const BufferedStackTrace *stack;
    152   uptr count;
    153   uptr size;
    154 
    155   ErrorCallocOverflow() = default;  // (*)
    156   ErrorCallocOverflow(u32 tid, BufferedStackTrace *stack_, uptr count_,
    157                       uptr size_)
    158       : ErrorBase(tid, 10, "calloc-overflow"),
    159         stack(stack_),
    160         count(count_),
    161         size(size_) {}
    162   void Print();
    163 };
    164 
    165 struct ErrorPvallocOverflow : ErrorBase {
    166   const BufferedStackTrace *stack;
    167   uptr size;
    168 
    169   ErrorPvallocOverflow() = default;  // (*)
    170   ErrorPvallocOverflow(u32 tid, BufferedStackTrace *stack_, uptr size_)
    171       : ErrorBase(tid, 10, "pvalloc-overflow"),
    172         stack(stack_),
    173         size(size_) {}
    174   void Print();
    175 };
    176 
    177 struct ErrorInvalidAllocationAlignment : ErrorBase {
    178   const BufferedStackTrace *stack;
    179   uptr alignment;
    180 
    181   ErrorInvalidAllocationAlignment() = default;  // (*)
    182   ErrorInvalidAllocationAlignment(u32 tid, BufferedStackTrace *stack_,
    183                                   uptr alignment_)
    184       : ErrorBase(tid, 10, "invalid-allocation-alignment"),
    185         stack(stack_),
    186         alignment(alignment_) {}
    187   void Print();
    188 };
    189 
    190 struct ErrorInvalidAlignedAllocAlignment : ErrorBase {
    191   const BufferedStackTrace *stack;
    192   uptr size;
    193   uptr alignment;
    194 
    195   ErrorInvalidAlignedAllocAlignment() = default;  // (*)
    196   ErrorInvalidAlignedAllocAlignment(u32 tid, BufferedStackTrace *stack_,
    197                                     uptr size_, uptr alignment_)
    198       : ErrorBase(tid, 10, "invalid-aligned-alloc-alignment"),
    199         stack(stack_),
    200         size(size_),
    201         alignment(alignment_) {}
    202   void Print();
    203 };
    204 
    205 struct ErrorInvalidPosixMemalignAlignment : ErrorBase {
    206   const BufferedStackTrace *stack;
    207   uptr alignment;
    208 
    209   ErrorInvalidPosixMemalignAlignment() = default;  // (*)
    210   ErrorInvalidPosixMemalignAlignment(u32 tid, BufferedStackTrace *stack_,
    211                                      uptr alignment_)
    212       : ErrorBase(tid, 10, "invalid-posix-memalign-alignment"),
    213         stack(stack_),
    214         alignment(alignment_) {}
    215   void Print();
    216 };
    217 
    218 struct ErrorAllocationSizeTooBig : ErrorBase {
    219   const BufferedStackTrace *stack;
    220   uptr user_size;
    221   uptr total_size;
    222   uptr max_size;
    223 
    224   ErrorAllocationSizeTooBig() = default;  // (*)
    225   ErrorAllocationSizeTooBig(u32 tid, BufferedStackTrace *stack_,
    226                             uptr user_size_, uptr total_size_, uptr max_size_)
    227       : ErrorBase(tid, 10, "allocation-size-too-big"),
    228         stack(stack_),
    229         user_size(user_size_),
    230         total_size(total_size_),
    231         max_size(max_size_) {}
    232   void Print();
    233 };
    234 
    235 struct ErrorRssLimitExceeded : ErrorBase {
    236   const BufferedStackTrace *stack;
    237 
    238   ErrorRssLimitExceeded() = default;  // (*)
    239   ErrorRssLimitExceeded(u32 tid, BufferedStackTrace *stack_)
    240       : ErrorBase(tid, 10, "rss-limit-exceeded"),
    241         stack(stack_) {}
    242   void Print();
    243 };
    244 
    245 struct ErrorOutOfMemory : ErrorBase {
    246   const BufferedStackTrace *stack;
    247   uptr requested_size;
    248 
    249   ErrorOutOfMemory() = default;  // (*)
    250   ErrorOutOfMemory(u32 tid, BufferedStackTrace *stack_, uptr requested_size_)
    251       : ErrorBase(tid, 10, "out-of-memory"),
    252         stack(stack_),
    253         requested_size(requested_size_) {}
    254   void Print();
    255 };
    256 
    257 struct ErrorStringFunctionMemoryRangesOverlap : ErrorBase {
    258   const BufferedStackTrace *stack;
    259   uptr length1, length2;
    260   AddressDescription addr1_description;
    261   AddressDescription addr2_description;
    262   const char *function;
    263 
    264   ErrorStringFunctionMemoryRangesOverlap() = default;  // (*)
    265   ErrorStringFunctionMemoryRangesOverlap(u32 tid, BufferedStackTrace *stack_,
    266                                          uptr addr1, uptr length1_, uptr addr2,
    267                                          uptr length2_, const char *function_)
    268       : ErrorBase(tid),
    269         stack(stack_),
    270         length1(length1_),
    271         length2(length2_),
    272         addr1_description(addr1, length1, /*shouldLockThreadRegistry=*/false),
    273         addr2_description(addr2, length2, /*shouldLockThreadRegistry=*/false),
    274         function(function_) {
    275     char bug_type[100];
    276     internal_snprintf(bug_type, sizeof(bug_type), "%s-param-overlap", function);
    277     scariness.Clear();
    278     scariness.Scare(10, bug_type);
    279   }
    280   void Print();
    281 };
    282 
    283 struct ErrorStringFunctionSizeOverflow : ErrorBase {
    284   const BufferedStackTrace *stack;
    285   AddressDescription addr_description;
    286   uptr size;
    287 
    288   ErrorStringFunctionSizeOverflow() = default;  // (*)
    289   ErrorStringFunctionSizeOverflow(u32 tid, BufferedStackTrace *stack_,
    290                                   uptr addr, uptr size_)
    291       : ErrorBase(tid, 10, "negative-size-param"),
    292         stack(stack_),
    293         addr_description(addr, /*shouldLockThreadRegistry=*/false),
    294         size(size_) {}
    295   void Print();
    296 };
    297 
    298 struct ErrorBadParamsToAnnotateContiguousContainer : ErrorBase {
    299   const BufferedStackTrace *stack;
    300   uptr beg, end, old_mid, new_mid;
    301 
    302   ErrorBadParamsToAnnotateContiguousContainer() = default;  // (*)
    303   // PS4: Do we want an AddressDescription for beg?
    304   ErrorBadParamsToAnnotateContiguousContainer(u32 tid,
    305                                               BufferedStackTrace *stack_,
    306                                               uptr beg_, uptr end_,
    307                                               uptr old_mid_, uptr new_mid_)
    308       : ErrorBase(tid, 10, "bad-__sanitizer_annotate_contiguous_container"),
    309         stack(stack_),
    310         beg(beg_),
    311         end(end_),
    312         old_mid(old_mid_),
    313         new_mid(new_mid_) {}
    314   void Print();
    315 };
    316 
    317 struct ErrorODRViolation : ErrorBase {
    318   __asan_global global1, global2;
    319   u32 stack_id1, stack_id2;
    320 
    321   ErrorODRViolation() = default;  // (*)
    322   ErrorODRViolation(u32 tid, const __asan_global *g1, u32 stack_id1_,
    323                     const __asan_global *g2, u32 stack_id2_)
    324       : ErrorBase(tid, 10, "odr-violation"),
    325         global1(*g1),
    326         global2(*g2),
    327         stack_id1(stack_id1_),
    328         stack_id2(stack_id2_) {}
    329   void Print();
    330 };
    331 
    332 struct ErrorInvalidPointerPair : ErrorBase {
    333   uptr pc, bp, sp;
    334   AddressDescription addr1_description;
    335   AddressDescription addr2_description;
    336 
    337   ErrorInvalidPointerPair() = default;  // (*)
    338   ErrorInvalidPointerPair(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr p1,
    339                           uptr p2)
    340       : ErrorBase(tid, 10, "invalid-pointer-pair"),
    341         pc(pc_),
    342         bp(bp_),
    343         sp(sp_),
    344         addr1_description(p1, 1, /*shouldLockThreadRegistry=*/false),
    345         addr2_description(p2, 1, /*shouldLockThreadRegistry=*/false) {}
    346   void Print();
    347 };
    348 
    349 struct ErrorGeneric : ErrorBase {
    350   AddressDescription addr_description;
    351   uptr pc, bp, sp;
    352   uptr access_size;
    353   const char *bug_descr;
    354   bool is_write;
    355   u8 shadow_val;
    356 
    357   ErrorGeneric() = default;  // (*)
    358   ErrorGeneric(u32 tid, uptr addr, uptr pc_, uptr bp_, uptr sp_, bool is_write_,
    359                uptr access_size_);
    360   void Print();
    361 };
    362 
    363 // clang-format off
    364 #define ASAN_FOR_EACH_ERROR_KIND(macro)         \
    365   macro(DeadlySignal)                           \
    366   macro(DoubleFree)                             \
    367   macro(NewDeleteTypeMismatch)                  \
    368   macro(FreeNotMalloced)                        \
    369   macro(AllocTypeMismatch)                      \
    370   macro(MallocUsableSizeNotOwned)               \
    371   macro(SanitizerGetAllocatedSizeNotOwned)      \
    372   macro(CallocOverflow)                         \
    373   macro(PvallocOverflow)                        \
    374   macro(InvalidAllocationAlignment)             \
    375   macro(InvalidAlignedAllocAlignment)           \
    376   macro(InvalidPosixMemalignAlignment)          \
    377   macro(AllocationSizeTooBig)                   \
    378   macro(RssLimitExceeded)                       \
    379   macro(OutOfMemory)                            \
    380   macro(StringFunctionMemoryRangesOverlap)      \
    381   macro(StringFunctionSizeOverflow)             \
    382   macro(BadParamsToAnnotateContiguousContainer) \
    383   macro(ODRViolation)                           \
    384   macro(InvalidPointerPair)                     \
    385   macro(Generic)
    386 // clang-format on
    387 
    388 #define ASAN_DEFINE_ERROR_KIND(name) kErrorKind##name,
    389 #define ASAN_ERROR_DESCRIPTION_MEMBER(name) Error##name name;
    390 #define ASAN_ERROR_DESCRIPTION_CONSTRUCTOR(name) \
    391   ErrorDescription(Error##name const &e) : kind(kErrorKind##name), name(e) {}
    392 #define ASAN_ERROR_DESCRIPTION_PRINT(name) \
    393   case kErrorKind##name:                   \
    394     return name.Print();
    395 
    396 enum ErrorKind {
    397   kErrorKindInvalid = 0,
    398   ASAN_FOR_EACH_ERROR_KIND(ASAN_DEFINE_ERROR_KIND)
    399 };
    400 
    401 struct ErrorDescription {
    402   ErrorKind kind;
    403   // We're using a tagged union because it allows us to have a trivially
    404   // copiable type and use the same structures as the public interface.
    405   //
    406   // We can add a wrapper around it to make it "more c++-like", but that would
    407   // add a lot of code and the benefit wouldn't be that big.
    408   union {
    409     ErrorBase Base;
    410     ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_MEMBER)
    411   };
    412 
    413   ErrorDescription() { internal_memset(this, 0, sizeof(*this)); }
    414   explicit ErrorDescription(LinkerInitialized) {}
    415   ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_CONSTRUCTOR)
    416 
    417   bool IsValid() { return kind != kErrorKindInvalid; }
    418   void Print() {
    419     switch (kind) {
    420       ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_PRINT)
    421       case kErrorKindInvalid:
    422         CHECK(0);
    423     }
    424     CHECK(0);
    425   }
    426 };
    427 
    428 #undef ASAN_FOR_EACH_ERROR_KIND
    429 #undef ASAN_DEFINE_ERROR_KIND
    430 #undef ASAN_ERROR_DESCRIPTION_MEMBER
    431 #undef ASAN_ERROR_DESCRIPTION_CONSTRUCTOR
    432 #undef ASAN_ERROR_DESCRIPTION_PRINT
    433 
    434 }  // namespace __asan
    435 
    436 #endif  // ASAN_ERRORS_H
    437