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