brintos

brintos / llvm-project-archived public Read only

0
0
Text · 16.8 KiB · f339b35 Raw
499 lines · c
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-exception6//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_H14#define ASAN_ERRORS_H15 16#include "asan_descriptions.h"17#include "asan_scariness_score.h"18#include "sanitizer_common/sanitizer_common.h"19 20namespace __asan {21 22// (*) VS2013 does not implement unrestricted unions, so we need a trivial23// default constructor explicitly defined for each particular error.24 25// None of the error classes own the stack traces mentioned in them.26 27struct 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 39struct 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 67struct 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 81struct 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 99struct 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 111struct 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 127struct 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 139struct 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 152struct 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 167struct 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 182struct 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 194struct 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 207struct 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 222struct 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 235struct 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 252struct 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 262struct 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 274struct 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 300struct 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 315struct 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 334struct ErrorBadParamsToAnnotateDoubleEndedContiguousContainer : ErrorBase {335  const BufferedStackTrace *stack;336  uptr storage_beg, storage_end, old_container_beg, old_container_end,337      new_container_beg, new_container_end;338 339  ErrorBadParamsToAnnotateDoubleEndedContiguousContainer() = default;  // (*)340  ErrorBadParamsToAnnotateDoubleEndedContiguousContainer(341      u32 tid, BufferedStackTrace *stack_, uptr storage_beg_, uptr storage_end_,342      uptr old_container_beg_, uptr old_container_end_, uptr new_container_beg_,343      uptr new_container_end_)344      : ErrorBase(tid, 10,345                  "bad-__sanitizer_annotate_double_ended_contiguous_container"),346        stack(stack_),347        storage_beg(storage_beg_),348        storage_end(storage_end_),349        old_container_beg(old_container_beg_),350        old_container_end(old_container_end_),351        new_container_beg(new_container_beg_),352        new_container_end(new_container_end_) {}353  void Print();354};355 356struct ErrorBadParamsToCopyContiguousContainerAnnotations : ErrorBase {357  const BufferedStackTrace *stack;358  uptr old_storage_beg, old_storage_end, new_storage_beg, new_storage_end;359 360  ErrorBadParamsToCopyContiguousContainerAnnotations() = default;  // (*)361  ErrorBadParamsToCopyContiguousContainerAnnotations(362      u32 tid, BufferedStackTrace *stack_, uptr old_storage_beg_,363      uptr old_storage_end_, uptr new_storage_beg_, uptr new_storage_end_)364      : ErrorBase(tid, 10,365                  "bad-__sanitizer_copy_contiguous_container_annotations"),366        stack(stack_),367        old_storage_beg(old_storage_beg_),368        old_storage_end(old_storage_end_),369        new_storage_beg(new_storage_beg_),370        new_storage_end(new_storage_end_) {}371  void Print();372};373 374struct ErrorODRViolation : ErrorBase {375  __asan_global global1, global2;376  u32 stack_id1, stack_id2;377 378  ErrorODRViolation() = default;  // (*)379  ErrorODRViolation(u32 tid, const __asan_global *g1, u32 stack_id1_,380                    const __asan_global *g2, u32 stack_id2_)381      : ErrorBase(tid, 10, "odr-violation"),382        global1(*g1),383        global2(*g2),384        stack_id1(stack_id1_),385        stack_id2(stack_id2_) {}386  void Print();387};388 389struct ErrorInvalidPointerPair : ErrorBase {390  uptr pc, bp, sp;391  AddressDescription addr1_description;392  AddressDescription addr2_description;393 394  ErrorInvalidPointerPair() = default;  // (*)395  ErrorInvalidPointerPair(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr p1,396                          uptr p2)397      : ErrorBase(tid, 10, "invalid-pointer-pair"),398        pc(pc_),399        bp(bp_),400        sp(sp_),401        addr1_description(p1, 1, /*shouldLockThreadRegistry=*/false),402        addr2_description(p2, 1, /*shouldLockThreadRegistry=*/false) {}403  void Print();404};405 406struct ErrorGeneric : ErrorBase {407  AddressDescription addr_description;408  uptr pc, bp, sp;409  uptr access_size;410  const char *bug_descr;411  bool is_write;412  u8 shadow_val;413 414  ErrorGeneric() = default;  // (*)415  ErrorGeneric(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr addr, bool is_write_,416               uptr access_size_);417  void Print();418};419 420// clang-format off421#define ASAN_FOR_EACH_ERROR_KIND(macro)                    \422  macro(DeadlySignal)                                      \423  macro(DoubleFree)                                        \424  macro(NewDeleteTypeMismatch)                             \425  macro(FreeNotMalloced)                                   \426  macro(AllocTypeMismatch)                                 \427  macro(MallocUsableSizeNotOwned)                          \428  macro(SanitizerGetAllocatedSizeNotOwned)                 \429  macro(CallocOverflow)                                    \430  macro(ReallocArrayOverflow)                              \431  macro(PvallocOverflow)                                   \432  macro(InvalidAllocationAlignment)                        \433  macro(InvalidAlignedAllocAlignment)                      \434  macro(InvalidPosixMemalignAlignment)                     \435  macro(AllocationSizeTooBig)                              \436  macro(RssLimitExceeded)                                  \437  macro(OutOfMemory)                                       \438  macro(StringFunctionMemoryRangesOverlap)                 \439  macro(StringFunctionSizeOverflow)                        \440  macro(BadParamsToAnnotateContiguousContainer)            \441  macro(BadParamsToAnnotateDoubleEndedContiguousContainer) \442  macro(BadParamsToCopyContiguousContainerAnnotations)     \443  macro(ODRViolation)                                      \444  macro(InvalidPointerPair)                                \445  macro(Generic)446// clang-format on447 448#define ASAN_DEFINE_ERROR_KIND(name) kErrorKind##name,449#define ASAN_ERROR_DESCRIPTION_MEMBER(name) Error##name name;450#define ASAN_ERROR_DESCRIPTION_CONSTRUCTOR(name)                    \451  ErrorDescription(Error##name const &e) : kind(kErrorKind##name) { \452    internal_memcpy(&name, &e, sizeof(name));                       \453  }454#define ASAN_ERROR_DESCRIPTION_PRINT(name) \455  case kErrorKind##name:                   \456    return name.Print();457 458enum ErrorKind {459  kErrorKindInvalid = 0,460  ASAN_FOR_EACH_ERROR_KIND(ASAN_DEFINE_ERROR_KIND)461};462 463struct ErrorDescription {464  ErrorKind kind;465  // We're using a tagged union because it allows us to have a trivially466  // copiable type and use the same structures as the public interface.467  //468  // We can add a wrapper around it to make it "more c++-like", but that would469  // add a lot of code and the benefit wouldn't be that big.470  union {471    ErrorBase Base;472    ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_MEMBER)473  };474 475  ErrorDescription() { internal_memset(this, 0, sizeof(*this)); }476  explicit ErrorDescription(LinkerInitialized) {}477  ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_CONSTRUCTOR)478 479  bool IsValid() { return kind != kErrorKindInvalid; }480  void Print() {481    switch (kind) {482      ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_PRINT)483      case kErrorKindInvalid:484        CHECK(0);485    }486    CHECK(0);487  }488};489 490#undef ASAN_FOR_EACH_ERROR_KIND491#undef ASAN_DEFINE_ERROR_KIND492#undef ASAN_ERROR_DESCRIPTION_MEMBER493#undef ASAN_ERROR_DESCRIPTION_CONSTRUCTOR494#undef ASAN_ERROR_DESCRIPTION_PRINT495 496}  // namespace __asan497 498#endif  // ASAN_ERRORS_H499