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