Home | History | Annotate | Line # | Download | only in asan
asan_errors.h revision 1.1.1.1.4.2
      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 struct ErrorBase {
     22   ErrorBase() = default;
     23   explicit ErrorBase(u32 tid_) : tid(tid_) {}
     24   ScarinessScoreBase scariness;
     25   u32 tid;
     26 };
     27 
     28 struct ErrorStackOverflow : ErrorBase {
     29   uptr addr, pc, bp, sp;
     30   // ErrorStackOverflow never owns the context.
     31   void *context;
     32   // VS2013 doesn't implement unrestricted unions, so we need a trivial default
     33   // constructor
     34   ErrorStackOverflow() = default;
     35   ErrorStackOverflow(u32 tid, const SignalContext &sig)
     36       : ErrorBase(tid),
     37         addr(sig.addr),
     38         pc(sig.pc),
     39         bp(sig.bp),
     40         sp(sig.sp),
     41         context(sig.context) {
     42     scariness.Clear();
     43     scariness.Scare(10, "stack-overflow");
     44   }
     45   void Print();
     46 };
     47 
     48 struct ErrorDeadlySignal : ErrorBase {
     49   uptr addr, pc, bp, sp;
     50   // ErrorDeadlySignal never owns the context.
     51   void *context;
     52   int signo;
     53   SignalContext::WriteFlag write_flag;
     54   bool is_memory_access;
     55   // VS2013 doesn't implement unrestricted unions, so we need a trivial default
     56   // constructor
     57   ErrorDeadlySignal() = default;
     58   ErrorDeadlySignal(u32 tid, const SignalContext &sig, int signo_)
     59       : ErrorBase(tid),
     60         addr(sig.addr),
     61         pc(sig.pc),
     62         bp(sig.bp),
     63         sp(sig.sp),
     64         context(sig.context),
     65         signo(signo_),
     66         write_flag(sig.write_flag),
     67         is_memory_access(sig.is_memory_access) {
     68     scariness.Clear();
     69     if (is_memory_access) {
     70       if (addr < GetPageSizeCached()) {
     71         scariness.Scare(10, "null-deref");
     72       } else if (addr == pc) {
     73         scariness.Scare(60, "wild-jump");
     74       } else if (write_flag == SignalContext::WRITE) {
     75         scariness.Scare(30, "wild-addr-write");
     76       } else if (write_flag == SignalContext::READ) {
     77         scariness.Scare(20, "wild-addr-read");
     78       } else {
     79         scariness.Scare(25, "wild-addr");
     80       }
     81     } else {
     82       scariness.Scare(10, "signal");
     83     }
     84   }
     85   void Print();
     86 };
     87 
     88 struct ErrorDoubleFree : ErrorBase {
     89   // ErrorDoubleFree doesn't own the stack trace.
     90   const BufferedStackTrace *second_free_stack;
     91   HeapAddressDescription addr_description;
     92   // VS2013 doesn't implement unrestricted unions, so we need a trivial default
     93   // constructor
     94   ErrorDoubleFree() = default;
     95   ErrorDoubleFree(u32 tid, BufferedStackTrace *stack, uptr addr)
     96       : ErrorBase(tid), second_free_stack(stack) {
     97     CHECK_GT(second_free_stack->size, 0);
     98     GetHeapAddressInformation(addr, 1, &addr_description);
     99     scariness.Clear();
    100     scariness.Scare(42, "double-free");
    101   }
    102   void Print();
    103 };
    104 
    105 struct ErrorNewDeleteSizeMismatch : ErrorBase {
    106   // ErrorNewDeleteSizeMismatch doesn't own the stack trace.
    107   const BufferedStackTrace *free_stack;
    108   HeapAddressDescription addr_description;
    109   uptr delete_size;
    110   // VS2013 doesn't implement unrestricted unions, so we need a trivial default
    111   // constructor
    112   ErrorNewDeleteSizeMismatch() = default;
    113   ErrorNewDeleteSizeMismatch(u32 tid, BufferedStackTrace *stack, uptr addr,
    114                              uptr delete_size_)
    115       : ErrorBase(tid), free_stack(stack), delete_size(delete_size_) {
    116     GetHeapAddressInformation(addr, 1, &addr_description);
    117     scariness.Clear();
    118     scariness.Scare(10, "new-delete-type-mismatch");
    119   }
    120   void Print();
    121 };
    122 
    123 struct ErrorFreeNotMalloced : ErrorBase {
    124   // ErrorFreeNotMalloced doesn't own the stack trace.
    125   const BufferedStackTrace *free_stack;
    126   AddressDescription addr_description;
    127   // VS2013 doesn't implement unrestricted unions, so we need a trivial default
    128   // constructor
    129   ErrorFreeNotMalloced() = default;
    130   ErrorFreeNotMalloced(u32 tid, BufferedStackTrace *stack, uptr addr)
    131       : ErrorBase(tid),
    132         free_stack(stack),
    133         addr_description(addr, /*shouldLockThreadRegistry=*/false) {
    134     scariness.Clear();
    135     scariness.Scare(40, "bad-free");
    136   }
    137   void Print();
    138 };
    139 
    140 struct ErrorAllocTypeMismatch : ErrorBase {
    141   // ErrorAllocTypeMismatch doesn't own the stack trace.
    142   const BufferedStackTrace *dealloc_stack;
    143   HeapAddressDescription addr_description;
    144   AllocType alloc_type, dealloc_type;
    145   // VS2013 doesn't implement unrestricted unions, so we need a trivial default
    146   // constructor
    147   ErrorAllocTypeMismatch() = default;
    148   ErrorAllocTypeMismatch(u32 tid, BufferedStackTrace *stack, uptr addr,
    149                          AllocType alloc_type_, AllocType dealloc_type_)
    150       : ErrorBase(tid),
    151         dealloc_stack(stack),
    152         alloc_type(alloc_type_),
    153         dealloc_type(dealloc_type_) {
    154     GetHeapAddressInformation(addr, 1, &addr_description);
    155     scariness.Clear();
    156     scariness.Scare(10, "alloc-dealloc-mismatch");
    157   };
    158   void Print();
    159 };
    160 
    161 struct ErrorMallocUsableSizeNotOwned : ErrorBase {
    162   // ErrorMallocUsableSizeNotOwned doesn't own the stack trace.
    163   const BufferedStackTrace *stack;
    164   AddressDescription addr_description;
    165   // VS2013 doesn't implement unrestricted unions, so we need a trivial default
    166   // constructor
    167   ErrorMallocUsableSizeNotOwned() = default;
    168   ErrorMallocUsableSizeNotOwned(u32 tid, BufferedStackTrace *stack_, uptr addr)
    169       : ErrorBase(tid),
    170         stack(stack_),
    171         addr_description(addr, /*shouldLockThreadRegistry=*/false) {
    172     scariness.Clear();
    173   }
    174   void Print();
    175 };
    176 
    177 struct ErrorSanitizerGetAllocatedSizeNotOwned : ErrorBase {
    178   // ErrorSanitizerGetAllocatedSizeNotOwned doesn't own the stack trace.
    179   const BufferedStackTrace *stack;
    180   AddressDescription addr_description;
    181   // VS2013 doesn't implement unrestricted unions, so we need a trivial default
    182   // constructor
    183   ErrorSanitizerGetAllocatedSizeNotOwned() = default;
    184   ErrorSanitizerGetAllocatedSizeNotOwned(u32 tid, BufferedStackTrace *stack_,
    185                                          uptr addr)
    186       : ErrorBase(tid),
    187         stack(stack_),
    188         addr_description(addr, /*shouldLockThreadRegistry=*/false) {
    189     scariness.Clear();
    190   }
    191   void Print();
    192 };
    193 
    194 struct ErrorStringFunctionMemoryRangesOverlap : ErrorBase {
    195   // ErrorStringFunctionMemoryRangesOverlap doesn't own the stack trace.
    196   const BufferedStackTrace *stack;
    197   uptr length1, length2;
    198   AddressDescription addr1_description;
    199   AddressDescription addr2_description;
    200   const char *function;
    201   // VS2013 doesn't implement unrestricted unions, so we need a trivial default
    202   // constructor
    203   ErrorStringFunctionMemoryRangesOverlap() = default;
    204   ErrorStringFunctionMemoryRangesOverlap(u32 tid, BufferedStackTrace *stack_,
    205                                          uptr addr1, uptr length1_, uptr addr2,
    206                                          uptr length2_, const char *function_)
    207       : ErrorBase(tid),
    208         stack(stack_),
    209         length1(length1_),
    210         length2(length2_),
    211         addr1_description(addr1, length1, /*shouldLockThreadRegistry=*/false),
    212         addr2_description(addr2, length2, /*shouldLockThreadRegistry=*/false),
    213         function(function_) {
    214     char bug_type[100];
    215     internal_snprintf(bug_type, sizeof(bug_type), "%s-param-overlap", function);
    216     scariness.Clear();
    217     scariness.Scare(10, bug_type);
    218   }
    219   void Print();
    220 };
    221 
    222 struct ErrorStringFunctionSizeOverflow : ErrorBase {
    223   // ErrorStringFunctionSizeOverflow doesn't own the stack trace.
    224   const BufferedStackTrace *stack;
    225   AddressDescription addr_description;
    226   uptr size;
    227   // VS2013 doesn't implement unrestricted unions, so we need a trivial default
    228   // constructor
    229   ErrorStringFunctionSizeOverflow() = default;
    230   ErrorStringFunctionSizeOverflow(u32 tid, BufferedStackTrace *stack_,
    231                                   uptr addr, uptr size_)
    232       : ErrorBase(tid),
    233         stack(stack_),
    234         addr_description(addr, /*shouldLockThreadRegistry=*/false),
    235         size(size_) {
    236     scariness.Clear();
    237     scariness.Scare(10, "negative-size-param");
    238   }
    239   void Print();
    240 };
    241 
    242 struct ErrorBadParamsToAnnotateContiguousContainer : ErrorBase {
    243   // ErrorBadParamsToAnnotateContiguousContainer doesn't own the stack trace.
    244   const BufferedStackTrace *stack;
    245   uptr beg, end, old_mid, new_mid;
    246   // VS2013 doesn't implement unrestricted unions, so we need a trivial default
    247   // constructor
    248   ErrorBadParamsToAnnotateContiguousContainer() = default;
    249   // PS4: Do we want an AddressDescription for beg?
    250   ErrorBadParamsToAnnotateContiguousContainer(u32 tid,
    251                                               BufferedStackTrace *stack_,
    252                                               uptr beg_, uptr end_,
    253                                               uptr old_mid_, uptr new_mid_)
    254       : ErrorBase(tid),
    255         stack(stack_),
    256         beg(beg_),
    257         end(end_),
    258         old_mid(old_mid_),
    259         new_mid(new_mid_) {}
    260   void Print();
    261 };
    262 
    263 struct ErrorODRViolation : ErrorBase {
    264   __asan_global global1, global2;
    265   u32 stack_id1, stack_id2;
    266   // VS2013 doesn't implement unrestricted unions, so we need a trivial default
    267   // constructor
    268   ErrorODRViolation() = default;
    269   ErrorODRViolation(u32 tid, const __asan_global *g1, u32 stack_id1_,
    270                     const __asan_global *g2, u32 stack_id2_)
    271       : ErrorBase(tid),
    272         global1(*g1),
    273         global2(*g2),
    274         stack_id1(stack_id1_),
    275         stack_id2(stack_id2_) {}
    276   void Print();
    277 };
    278 
    279 struct ErrorInvalidPointerPair : ErrorBase {
    280   uptr pc, bp, sp;
    281   AddressDescription addr1_description;
    282   AddressDescription addr2_description;
    283   // VS2013 doesn't implement unrestricted unions, so we need a trivial default
    284   // constructor
    285   ErrorInvalidPointerPair() = default;
    286   ErrorInvalidPointerPair(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr p1,
    287                           uptr p2)
    288       : ErrorBase(tid),
    289         pc(pc_),
    290         bp(bp_),
    291         sp(sp_),
    292         addr1_description(p1, 1, /*shouldLockThreadRegistry=*/false),
    293         addr2_description(p2, 1, /*shouldLockThreadRegistry=*/false) {}
    294   void Print();
    295 };
    296 
    297 struct ErrorGeneric : ErrorBase {
    298   AddressDescription addr_description;
    299   uptr pc, bp, sp;
    300   uptr access_size;
    301   const char *bug_descr;
    302   bool is_write;
    303   u8 shadow_val;
    304   // VS2013 doesn't implement unrestricted unions, so we need a trivial default
    305   // constructor
    306   ErrorGeneric() = default;
    307   ErrorGeneric(u32 tid, uptr addr, uptr pc_, uptr bp_, uptr sp_, bool is_write_,
    308                uptr access_size_);
    309   void Print();
    310 };
    311 
    312 // clang-format off
    313 #define ASAN_FOR_EACH_ERROR_KIND(macro)         \
    314   macro(StackOverflow)                          \
    315   macro(DeadlySignal)                           \
    316   macro(DoubleFree)                             \
    317   macro(NewDeleteSizeMismatch)                  \
    318   macro(FreeNotMalloced)                        \
    319   macro(AllocTypeMismatch)                      \
    320   macro(MallocUsableSizeNotOwned)               \
    321   macro(SanitizerGetAllocatedSizeNotOwned)      \
    322   macro(StringFunctionMemoryRangesOverlap)      \
    323   macro(StringFunctionSizeOverflow)             \
    324   macro(BadParamsToAnnotateContiguousContainer) \
    325   macro(ODRViolation)                           \
    326   macro(InvalidPointerPair)                     \
    327   macro(Generic)
    328 // clang-format on
    329 
    330 #define ASAN_DEFINE_ERROR_KIND(name) kErrorKind##name,
    331 #define ASAN_ERROR_DESCRIPTION_MEMBER(name) Error##name name;
    332 #define ASAN_ERROR_DESCRIPTION_CONSTRUCTOR(name) \
    333   ErrorDescription(Error##name const &e) : kind(kErrorKind##name), name(e) {}
    334 #define ASAN_ERROR_DESCRIPTION_PRINT(name) \
    335   case kErrorKind##name:                   \
    336     return name.Print();
    337 
    338 enum ErrorKind {
    339   kErrorKindInvalid = 0,
    340   ASAN_FOR_EACH_ERROR_KIND(ASAN_DEFINE_ERROR_KIND)
    341 };
    342 
    343 struct ErrorDescription {
    344   ErrorKind kind;
    345   // We're using a tagged union because it allows us to have a trivially
    346   // copiable type and use the same structures as the public interface.
    347   //
    348   // We can add a wrapper around it to make it "more c++-like", but that would
    349   // add a lot of code and the benefit wouldn't be that big.
    350   union {
    351     ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_MEMBER)
    352   };
    353 
    354   ErrorDescription() { internal_memset(this, 0, sizeof(*this)); }
    355   ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_CONSTRUCTOR)
    356 
    357   bool IsValid() { return kind != kErrorKindInvalid; }
    358   void Print() {
    359     switch (kind) {
    360       ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_PRINT)
    361       case kErrorKindInvalid:
    362         CHECK(0);
    363     }
    364     CHECK(0);
    365   }
    366 };
    367 
    368 #undef ASAN_FOR_EACH_ERROR_KIND
    369 #undef ASAN_DEFINE_ERROR_KIND
    370 #undef ASAN_ERROR_DESCRIPTION_MEMBER
    371 #undef ASAN_ERROR_DESCRIPTION_CONSTRUCTOR
    372 #undef ASAN_ERROR_DESCRIPTION_PRINT
    373 
    374 }  // namespace __asan
    375 
    376 #endif  // ASAN_ERRORS_H
    377