391 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			391 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
	
//===-- asan_errors.h -------------------------------------------*- C++ -*-===//
 | 
						|
//
 | 
						|
//                     The LLVM Compiler Infrastructure
 | 
						|
//
 | 
						|
// This file is distributed under the University of Illinois Open Source
 | 
						|
// License. See LICENSE.TXT for details.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
//
 | 
						|
// This file is a part of AddressSanitizer, an address sanity checker.
 | 
						|
//
 | 
						|
// ASan-private header for error structures.
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
#ifndef ASAN_ERRORS_H
 | 
						|
#define ASAN_ERRORS_H
 | 
						|
 | 
						|
#include "asan_descriptions.h"
 | 
						|
#include "asan_scariness_score.h"
 | 
						|
#include "sanitizer_common/sanitizer_common.h"
 | 
						|
 | 
						|
namespace __asan {
 | 
						|
 | 
						|
struct ErrorBase {
 | 
						|
  ErrorBase() = default;
 | 
						|
  explicit ErrorBase(u32 tid_) : tid(tid_) {}
 | 
						|
  ScarinessScoreBase scariness;
 | 
						|
  u32 tid;
 | 
						|
};
 | 
						|
 | 
						|
struct ErrorStackOverflow : ErrorBase {
 | 
						|
  uptr addr, pc, bp, sp;
 | 
						|
  // ErrorStackOverflow never owns the context.
 | 
						|
  void *context;
 | 
						|
  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
 | 
						|
  // constructor
 | 
						|
  ErrorStackOverflow() = default;
 | 
						|
  ErrorStackOverflow(u32 tid, const SignalContext &sig)
 | 
						|
      : ErrorBase(tid),
 | 
						|
        addr(sig.addr),
 | 
						|
        pc(sig.pc),
 | 
						|
        bp(sig.bp),
 | 
						|
        sp(sig.sp),
 | 
						|
        context(sig.context) {
 | 
						|
    scariness.Clear();
 | 
						|
    scariness.Scare(10, "stack-overflow");
 | 
						|
  }
 | 
						|
  void Print();
 | 
						|
};
 | 
						|
 | 
						|
struct ErrorDeadlySignal : ErrorBase {
 | 
						|
  uptr addr, pc, bp, sp;
 | 
						|
  // ErrorDeadlySignal never owns the context.
 | 
						|
  void *context;
 | 
						|
  int signo;
 | 
						|
  SignalContext::WriteFlag write_flag;
 | 
						|
  bool is_memory_access;
 | 
						|
  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
 | 
						|
  // constructor
 | 
						|
  ErrorDeadlySignal() = default;
 | 
						|
  ErrorDeadlySignal(u32 tid, const SignalContext &sig, int signo_)
 | 
						|
      : ErrorBase(tid),
 | 
						|
        addr(sig.addr),
 | 
						|
        pc(sig.pc),
 | 
						|
        bp(sig.bp),
 | 
						|
        sp(sig.sp),
 | 
						|
        context(sig.context),
 | 
						|
        signo(signo_),
 | 
						|
        write_flag(sig.write_flag),
 | 
						|
        is_memory_access(sig.is_memory_access) {
 | 
						|
    scariness.Clear();
 | 
						|
    if (is_memory_access) {
 | 
						|
      if (addr < GetPageSizeCached()) {
 | 
						|
        scariness.Scare(10, "null-deref");
 | 
						|
      } else if (addr == pc) {
 | 
						|
        scariness.Scare(60, "wild-jump");
 | 
						|
      } else if (write_flag == SignalContext::WRITE) {
 | 
						|
        scariness.Scare(30, "wild-addr-write");
 | 
						|
      } else if (write_flag == SignalContext::READ) {
 | 
						|
        scariness.Scare(20, "wild-addr-read");
 | 
						|
      } else {
 | 
						|
        scariness.Scare(25, "wild-addr");
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      scariness.Scare(10, "signal");
 | 
						|
    }
 | 
						|
  }
 | 
						|
  void Print();
 | 
						|
};
 | 
						|
 | 
						|
struct ErrorDoubleFree : ErrorBase {
 | 
						|
  // ErrorDoubleFree doesn't own the stack trace.
 | 
						|
  const BufferedStackTrace *second_free_stack;
 | 
						|
  HeapAddressDescription addr_description;
 | 
						|
  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
 | 
						|
  // constructor
 | 
						|
  ErrorDoubleFree() = default;
 | 
						|
  ErrorDoubleFree(u32 tid, BufferedStackTrace *stack, uptr addr)
 | 
						|
      : ErrorBase(tid), second_free_stack(stack) {
 | 
						|
    CHECK_GT(second_free_stack->size, 0);
 | 
						|
    GetHeapAddressInformation(addr, 1, &addr_description);
 | 
						|
    scariness.Clear();
 | 
						|
    scariness.Scare(42, "double-free");
 | 
						|
  }
 | 
						|
  void Print();
 | 
						|
};
 | 
						|
 | 
						|
struct ErrorNewDeleteSizeMismatch : ErrorBase {
 | 
						|
  // ErrorNewDeleteSizeMismatch doesn't own the stack trace.
 | 
						|
  const BufferedStackTrace *free_stack;
 | 
						|
  HeapAddressDescription addr_description;
 | 
						|
  uptr delete_size;
 | 
						|
  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
 | 
						|
  // constructor
 | 
						|
  ErrorNewDeleteSizeMismatch() = default;
 | 
						|
  ErrorNewDeleteSizeMismatch(u32 tid, BufferedStackTrace *stack, uptr addr,
 | 
						|
                             uptr delete_size_)
 | 
						|
      : ErrorBase(tid), free_stack(stack), delete_size(delete_size_) {
 | 
						|
    GetHeapAddressInformation(addr, 1, &addr_description);
 | 
						|
    scariness.Clear();
 | 
						|
    scariness.Scare(10, "new-delete-type-mismatch");
 | 
						|
  }
 | 
						|
  void Print();
 | 
						|
};
 | 
						|
 | 
						|
struct ErrorFreeNotMalloced : ErrorBase {
 | 
						|
  // ErrorFreeNotMalloced doesn't own the stack trace.
 | 
						|
  const BufferedStackTrace *free_stack;
 | 
						|
  AddressDescription addr_description;
 | 
						|
  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
 | 
						|
  // constructor
 | 
						|
  ErrorFreeNotMalloced() = default;
 | 
						|
  ErrorFreeNotMalloced(u32 tid, BufferedStackTrace *stack, uptr addr)
 | 
						|
      : ErrorBase(tid),
 | 
						|
        free_stack(stack),
 | 
						|
        addr_description(addr, /*shouldLockThreadRegistry=*/false) {
 | 
						|
    scariness.Clear();
 | 
						|
    scariness.Scare(40, "bad-free");
 | 
						|
  }
 | 
						|
  void Print();
 | 
						|
};
 | 
						|
 | 
						|
struct ErrorAllocTypeMismatch : ErrorBase {
 | 
						|
  // ErrorAllocTypeMismatch doesn't own the stack trace.
 | 
						|
  const BufferedStackTrace *dealloc_stack;
 | 
						|
  HeapAddressDescription addr_description;
 | 
						|
  AllocType alloc_type, dealloc_type;
 | 
						|
  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
 | 
						|
  // constructor
 | 
						|
  ErrorAllocTypeMismatch() = default;
 | 
						|
  ErrorAllocTypeMismatch(u32 tid, BufferedStackTrace *stack, uptr addr,
 | 
						|
                         AllocType alloc_type_, AllocType dealloc_type_)
 | 
						|
      : ErrorBase(tid),
 | 
						|
        dealloc_stack(stack),
 | 
						|
        alloc_type(alloc_type_),
 | 
						|
        dealloc_type(dealloc_type_) {
 | 
						|
    GetHeapAddressInformation(addr, 1, &addr_description);
 | 
						|
    scariness.Clear();
 | 
						|
    scariness.Scare(10, "alloc-dealloc-mismatch");
 | 
						|
  };
 | 
						|
  void Print();
 | 
						|
};
 | 
						|
 | 
						|
struct ErrorMallocUsableSizeNotOwned : ErrorBase {
 | 
						|
  // ErrorMallocUsableSizeNotOwned doesn't own the stack trace.
 | 
						|
  const BufferedStackTrace *stack;
 | 
						|
  AddressDescription addr_description;
 | 
						|
  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
 | 
						|
  // constructor
 | 
						|
  ErrorMallocUsableSizeNotOwned() = default;
 | 
						|
  ErrorMallocUsableSizeNotOwned(u32 tid, BufferedStackTrace *stack_, uptr addr)
 | 
						|
      : ErrorBase(tid),
 | 
						|
        stack(stack_),
 | 
						|
        addr_description(addr, /*shouldLockThreadRegistry=*/false) {
 | 
						|
    scariness.Clear();
 | 
						|
    scariness.Scare(10, "bad-malloc_usable_size");
 | 
						|
  }
 | 
						|
  void Print();
 | 
						|
};
 | 
						|
 | 
						|
struct ErrorSanitizerGetAllocatedSizeNotOwned : ErrorBase {
 | 
						|
  // ErrorSanitizerGetAllocatedSizeNotOwned doesn't own the stack trace.
 | 
						|
  const BufferedStackTrace *stack;
 | 
						|
  AddressDescription addr_description;
 | 
						|
  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
 | 
						|
  // constructor
 | 
						|
  ErrorSanitizerGetAllocatedSizeNotOwned() = default;
 | 
						|
  ErrorSanitizerGetAllocatedSizeNotOwned(u32 tid, BufferedStackTrace *stack_,
 | 
						|
                                         uptr addr)
 | 
						|
      : ErrorBase(tid),
 | 
						|
        stack(stack_),
 | 
						|
        addr_description(addr, /*shouldLockThreadRegistry=*/false) {
 | 
						|
    scariness.Clear();
 | 
						|
    scariness.Scare(10, "bad-__sanitizer_get_allocated_size");
 | 
						|
  }
 | 
						|
  void Print();
 | 
						|
};
 | 
						|
 | 
						|
struct ErrorStringFunctionMemoryRangesOverlap : ErrorBase {
 | 
						|
  // ErrorStringFunctionMemoryRangesOverlap doesn't own the stack trace.
 | 
						|
  const BufferedStackTrace *stack;
 | 
						|
  uptr length1, length2;
 | 
						|
  AddressDescription addr1_description;
 | 
						|
  AddressDescription addr2_description;
 | 
						|
  const char *function;
 | 
						|
  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
 | 
						|
  // constructor
 | 
						|
  ErrorStringFunctionMemoryRangesOverlap() = default;
 | 
						|
  ErrorStringFunctionMemoryRangesOverlap(u32 tid, BufferedStackTrace *stack_,
 | 
						|
                                         uptr addr1, uptr length1_, uptr addr2,
 | 
						|
                                         uptr length2_, const char *function_)
 | 
						|
      : ErrorBase(tid),
 | 
						|
        stack(stack_),
 | 
						|
        length1(length1_),
 | 
						|
        length2(length2_),
 | 
						|
        addr1_description(addr1, length1, /*shouldLockThreadRegistry=*/false),
 | 
						|
        addr2_description(addr2, length2, /*shouldLockThreadRegistry=*/false),
 | 
						|
        function(function_) {
 | 
						|
    char bug_type[100];
 | 
						|
    internal_snprintf(bug_type, sizeof(bug_type), "%s-param-overlap", function);
 | 
						|
    scariness.Clear();
 | 
						|
    scariness.Scare(10, bug_type);
 | 
						|
  }
 | 
						|
  void Print();
 | 
						|
};
 | 
						|
 | 
						|
struct ErrorStringFunctionSizeOverflow : ErrorBase {
 | 
						|
  // ErrorStringFunctionSizeOverflow doesn't own the stack trace.
 | 
						|
  const BufferedStackTrace *stack;
 | 
						|
  AddressDescription addr_description;
 | 
						|
  uptr size;
 | 
						|
  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
 | 
						|
  // constructor
 | 
						|
  ErrorStringFunctionSizeOverflow() = default;
 | 
						|
  ErrorStringFunctionSizeOverflow(u32 tid, BufferedStackTrace *stack_,
 | 
						|
                                  uptr addr, uptr size_)
 | 
						|
      : ErrorBase(tid),
 | 
						|
        stack(stack_),
 | 
						|
        addr_description(addr, /*shouldLockThreadRegistry=*/false),
 | 
						|
        size(size_) {
 | 
						|
    scariness.Clear();
 | 
						|
    scariness.Scare(10, "negative-size-param");
 | 
						|
  }
 | 
						|
  void Print();
 | 
						|
};
 | 
						|
 | 
						|
struct ErrorBadParamsToAnnotateContiguousContainer : ErrorBase {
 | 
						|
  // ErrorBadParamsToAnnotateContiguousContainer doesn't own the stack trace.
 | 
						|
  const BufferedStackTrace *stack;
 | 
						|
  uptr beg, end, old_mid, new_mid;
 | 
						|
  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
 | 
						|
  // constructor
 | 
						|
  ErrorBadParamsToAnnotateContiguousContainer() = default;
 | 
						|
  // PS4: Do we want an AddressDescription for beg?
 | 
						|
  ErrorBadParamsToAnnotateContiguousContainer(u32 tid,
 | 
						|
                                              BufferedStackTrace *stack_,
 | 
						|
                                              uptr beg_, uptr end_,
 | 
						|
                                              uptr old_mid_, uptr new_mid_)
 | 
						|
      : ErrorBase(tid),
 | 
						|
        stack(stack_),
 | 
						|
        beg(beg_),
 | 
						|
        end(end_),
 | 
						|
        old_mid(old_mid_),
 | 
						|
        new_mid(new_mid_) {
 | 
						|
    scariness.Clear();
 | 
						|
    scariness.Scare(10, "bad-__sanitizer_annotate_contiguous_container");
 | 
						|
  }
 | 
						|
  void Print();
 | 
						|
};
 | 
						|
 | 
						|
struct ErrorODRViolation : ErrorBase {
 | 
						|
  __asan_global global1, global2;
 | 
						|
  u32 stack_id1, stack_id2;
 | 
						|
  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
 | 
						|
  // constructor
 | 
						|
  ErrorODRViolation() = default;
 | 
						|
  ErrorODRViolation(u32 tid, const __asan_global *g1, u32 stack_id1_,
 | 
						|
                    const __asan_global *g2, u32 stack_id2_)
 | 
						|
      : ErrorBase(tid),
 | 
						|
        global1(*g1),
 | 
						|
        global2(*g2),
 | 
						|
        stack_id1(stack_id1_),
 | 
						|
        stack_id2(stack_id2_) {
 | 
						|
    scariness.Clear();
 | 
						|
    scariness.Scare(10, "odr-violation");
 | 
						|
  }
 | 
						|
  void Print();
 | 
						|
};
 | 
						|
 | 
						|
struct ErrorInvalidPointerPair : ErrorBase {
 | 
						|
  uptr pc, bp, sp;
 | 
						|
  AddressDescription addr1_description;
 | 
						|
  AddressDescription addr2_description;
 | 
						|
  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
 | 
						|
  // constructor
 | 
						|
  ErrorInvalidPointerPair() = default;
 | 
						|
  ErrorInvalidPointerPair(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr p1,
 | 
						|
                          uptr p2)
 | 
						|
      : ErrorBase(tid),
 | 
						|
        pc(pc_),
 | 
						|
        bp(bp_),
 | 
						|
        sp(sp_),
 | 
						|
        addr1_description(p1, 1, /*shouldLockThreadRegistry=*/false),
 | 
						|
        addr2_description(p2, 1, /*shouldLockThreadRegistry=*/false)  {
 | 
						|
    scariness.Clear();
 | 
						|
    scariness.Scare(10, "invalid-pointer-pair");
 | 
						|
  }
 | 
						|
  void Print();
 | 
						|
};
 | 
						|
 | 
						|
struct ErrorGeneric : ErrorBase {
 | 
						|
  AddressDescription addr_description;
 | 
						|
  uptr pc, bp, sp;
 | 
						|
  uptr access_size;
 | 
						|
  const char *bug_descr;
 | 
						|
  bool is_write;
 | 
						|
  u8 shadow_val;
 | 
						|
  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
 | 
						|
  // constructor
 | 
						|
  ErrorGeneric() = default;
 | 
						|
  ErrorGeneric(u32 tid, uptr addr, uptr pc_, uptr bp_, uptr sp_, bool is_write_,
 | 
						|
               uptr access_size_);
 | 
						|
  void Print();
 | 
						|
};
 | 
						|
 | 
						|
// clang-format off
 | 
						|
#define ASAN_FOR_EACH_ERROR_KIND(macro)         \
 | 
						|
  macro(StackOverflow)                          \
 | 
						|
  macro(DeadlySignal)                           \
 | 
						|
  macro(DoubleFree)                             \
 | 
						|
  macro(NewDeleteSizeMismatch)                  \
 | 
						|
  macro(FreeNotMalloced)                        \
 | 
						|
  macro(AllocTypeMismatch)                      \
 | 
						|
  macro(MallocUsableSizeNotOwned)               \
 | 
						|
  macro(SanitizerGetAllocatedSizeNotOwned)      \
 | 
						|
  macro(StringFunctionMemoryRangesOverlap)      \
 | 
						|
  macro(StringFunctionSizeOverflow)             \
 | 
						|
  macro(BadParamsToAnnotateContiguousContainer) \
 | 
						|
  macro(ODRViolation)                           \
 | 
						|
  macro(InvalidPointerPair)                     \
 | 
						|
  macro(Generic)
 | 
						|
// clang-format on
 | 
						|
 | 
						|
#define ASAN_DEFINE_ERROR_KIND(name) kErrorKind##name,
 | 
						|
#define ASAN_ERROR_DESCRIPTION_MEMBER(name) Error##name name;
 | 
						|
#define ASAN_ERROR_DESCRIPTION_CONSTRUCTOR(name) \
 | 
						|
  ErrorDescription(Error##name const &e) : kind(kErrorKind##name), name(e) {}
 | 
						|
#define ASAN_ERROR_DESCRIPTION_PRINT(name) \
 | 
						|
  case kErrorKind##name:                   \
 | 
						|
    return name.Print();
 | 
						|
 | 
						|
enum ErrorKind {
 | 
						|
  kErrorKindInvalid = 0,
 | 
						|
  ASAN_FOR_EACH_ERROR_KIND(ASAN_DEFINE_ERROR_KIND)
 | 
						|
};
 | 
						|
 | 
						|
struct ErrorDescription {
 | 
						|
  ErrorKind kind;
 | 
						|
  // We're using a tagged union because it allows us to have a trivially
 | 
						|
  // copiable type and use the same structures as the public interface.
 | 
						|
  //
 | 
						|
  // We can add a wrapper around it to make it "more c++-like", but that would
 | 
						|
  // add a lot of code and the benefit wouldn't be that big.
 | 
						|
  union {
 | 
						|
    ErrorBase Base;
 | 
						|
    ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_MEMBER)
 | 
						|
  };
 | 
						|
 | 
						|
  ErrorDescription() { internal_memset(this, 0, sizeof(*this)); }
 | 
						|
  ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_CONSTRUCTOR)
 | 
						|
 | 
						|
  bool IsValid() { return kind != kErrorKindInvalid; }
 | 
						|
  void Print() {
 | 
						|
    switch (kind) {
 | 
						|
      ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_PRINT)
 | 
						|
      case kErrorKindInvalid:
 | 
						|
        CHECK(0);
 | 
						|
    }
 | 
						|
    CHECK(0);
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
#undef ASAN_FOR_EACH_ERROR_KIND
 | 
						|
#undef ASAN_DEFINE_ERROR_KIND
 | 
						|
#undef ASAN_ERROR_DESCRIPTION_MEMBER
 | 
						|
#undef ASAN_ERROR_DESCRIPTION_CONSTRUCTOR
 | 
						|
#undef ASAN_ERROR_DESCRIPTION_PRINT
 | 
						|
 | 
						|
}  // namespace __asan
 | 
						|
 | 
						|
#endif  // ASAN_ERRORS_H
 |