10b57cec5SDimitry Andric //===-- asan_errors.h -------------------------------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file is a part of AddressSanitizer, an address sanity checker.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric // ASan-private header for error structures.
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric #ifndef ASAN_ERRORS_H
140b57cec5SDimitry Andric #define ASAN_ERRORS_H
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #include "asan_descriptions.h"
170b57cec5SDimitry Andric #include "asan_scariness_score.h"
180b57cec5SDimitry Andric #include "sanitizer_common/sanitizer_common.h"
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric namespace __asan {
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric // (*) VS2013 does not implement unrestricted unions, so we need a trivial
230b57cec5SDimitry Andric // default constructor explicitly defined for each particular error.
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric // None of the error classes own the stack traces mentioned in them.
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric struct ErrorBase {
280b57cec5SDimitry Andric   ScarinessScoreBase scariness;
290b57cec5SDimitry Andric   u32 tid;
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric   ErrorBase() = default;  // (*)
ErrorBaseErrorBase320b57cec5SDimitry Andric   explicit ErrorBase(u32 tid_) : tid(tid_) {}
ErrorBaseErrorBase330b57cec5SDimitry Andric   ErrorBase(u32 tid_, int initial_score, const char *reason) : tid(tid_) {
340b57cec5SDimitry Andric     scariness.Clear();
350b57cec5SDimitry Andric     scariness.Scare(initial_score, reason);
360b57cec5SDimitry Andric   }
370b57cec5SDimitry Andric };
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric struct ErrorDeadlySignal : ErrorBase {
400b57cec5SDimitry Andric   SignalContext signal;
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric   ErrorDeadlySignal() = default;  // (*)
ErrorDeadlySignalErrorDeadlySignal430b57cec5SDimitry Andric   ErrorDeadlySignal(u32 tid, const SignalContext &sig)
440b57cec5SDimitry Andric       : ErrorBase(tid),
450b57cec5SDimitry Andric         signal(sig) {
460b57cec5SDimitry Andric     scariness.Clear();
470b57cec5SDimitry Andric     if (signal.IsStackOverflow()) {
480b57cec5SDimitry Andric       scariness.Scare(10, "stack-overflow");
490b57cec5SDimitry Andric     } else if (!signal.is_memory_access) {
500b57cec5SDimitry Andric       scariness.Scare(10, "signal");
5168d75effSDimitry Andric     } else if (signal.is_true_faulting_addr &&
5268d75effSDimitry Andric                signal.addr < GetPageSizeCached()) {
530b57cec5SDimitry Andric       scariness.Scare(10, "null-deref");
540b57cec5SDimitry Andric     } else if (signal.addr == signal.pc) {
550b57cec5SDimitry Andric       scariness.Scare(60, "wild-jump");
56d56accc7SDimitry Andric     } else if (signal.write_flag == SignalContext::Write) {
570b57cec5SDimitry Andric       scariness.Scare(30, "wild-addr-write");
58d56accc7SDimitry Andric     } else if (signal.write_flag == SignalContext::Read) {
590b57cec5SDimitry Andric       scariness.Scare(20, "wild-addr-read");
600b57cec5SDimitry Andric     } else {
610b57cec5SDimitry Andric       scariness.Scare(25, "wild-addr");
620b57cec5SDimitry Andric     }
630b57cec5SDimitry Andric   }
640b57cec5SDimitry Andric   void Print();
650b57cec5SDimitry Andric };
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric struct ErrorDoubleFree : ErrorBase {
680b57cec5SDimitry Andric   const BufferedStackTrace *second_free_stack;
690b57cec5SDimitry Andric   HeapAddressDescription addr_description;
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric   ErrorDoubleFree() = default;  // (*)
ErrorDoubleFreeErrorDoubleFree720b57cec5SDimitry Andric   ErrorDoubleFree(u32 tid, BufferedStackTrace *stack, uptr addr)
730b57cec5SDimitry Andric       : ErrorBase(tid, 42, "double-free"),
740b57cec5SDimitry Andric         second_free_stack(stack) {
750b57cec5SDimitry Andric     CHECK_GT(second_free_stack->size, 0);
760b57cec5SDimitry Andric     GetHeapAddressInformation(addr, 1, &addr_description);
770b57cec5SDimitry Andric   }
780b57cec5SDimitry Andric   void Print();
790b57cec5SDimitry Andric };
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric struct ErrorNewDeleteTypeMismatch : ErrorBase {
820b57cec5SDimitry Andric   const BufferedStackTrace *free_stack;
830b57cec5SDimitry Andric   HeapAddressDescription addr_description;
840b57cec5SDimitry Andric   uptr delete_size;
850b57cec5SDimitry Andric   uptr delete_alignment;
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric   ErrorNewDeleteTypeMismatch() = default;  // (*)
ErrorNewDeleteTypeMismatchErrorNewDeleteTypeMismatch880b57cec5SDimitry Andric   ErrorNewDeleteTypeMismatch(u32 tid, BufferedStackTrace *stack, uptr addr,
890b57cec5SDimitry Andric                              uptr delete_size_, uptr delete_alignment_)
900b57cec5SDimitry Andric       : ErrorBase(tid, 10, "new-delete-type-mismatch"),
910b57cec5SDimitry Andric         free_stack(stack),
920b57cec5SDimitry Andric         delete_size(delete_size_),
930b57cec5SDimitry Andric         delete_alignment(delete_alignment_) {
940b57cec5SDimitry Andric     GetHeapAddressInformation(addr, 1, &addr_description);
950b57cec5SDimitry Andric   }
960b57cec5SDimitry Andric   void Print();
970b57cec5SDimitry Andric };
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric struct ErrorFreeNotMalloced : ErrorBase {
1000b57cec5SDimitry Andric   const BufferedStackTrace *free_stack;
1010b57cec5SDimitry Andric   AddressDescription addr_description;
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric   ErrorFreeNotMalloced() = default;  // (*)
ErrorFreeNotMallocedErrorFreeNotMalloced1040b57cec5SDimitry Andric   ErrorFreeNotMalloced(u32 tid, BufferedStackTrace *stack, uptr addr)
1050b57cec5SDimitry Andric       : ErrorBase(tid, 40, "bad-free"),
1060b57cec5SDimitry Andric         free_stack(stack),
1070b57cec5SDimitry Andric         addr_description(addr, /*shouldLockThreadRegistry=*/false) {}
1080b57cec5SDimitry Andric   void Print();
1090b57cec5SDimitry Andric };
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric struct ErrorAllocTypeMismatch : ErrorBase {
1120b57cec5SDimitry Andric   const BufferedStackTrace *dealloc_stack;
1130b57cec5SDimitry Andric   AllocType alloc_type, dealloc_type;
1140b57cec5SDimitry Andric   AddressDescription addr_description;
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric   ErrorAllocTypeMismatch() = default;  // (*)
ErrorAllocTypeMismatchErrorAllocTypeMismatch1170b57cec5SDimitry Andric   ErrorAllocTypeMismatch(u32 tid, BufferedStackTrace *stack, uptr addr,
1180b57cec5SDimitry Andric                          AllocType alloc_type_, AllocType dealloc_type_)
1190b57cec5SDimitry Andric       : ErrorBase(tid, 10, "alloc-dealloc-mismatch"),
1200b57cec5SDimitry Andric         dealloc_stack(stack),
1210b57cec5SDimitry Andric         alloc_type(alloc_type_),
1220b57cec5SDimitry Andric         dealloc_type(dealloc_type_),
1230b57cec5SDimitry Andric         addr_description(addr, 1, false) {}
1240b57cec5SDimitry Andric   void Print();
1250b57cec5SDimitry Andric };
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric struct ErrorMallocUsableSizeNotOwned : ErrorBase {
1280b57cec5SDimitry Andric   const BufferedStackTrace *stack;
1290b57cec5SDimitry Andric   AddressDescription addr_description;
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric   ErrorMallocUsableSizeNotOwned() = default;  // (*)
ErrorMallocUsableSizeNotOwnedErrorMallocUsableSizeNotOwned1320b57cec5SDimitry Andric   ErrorMallocUsableSizeNotOwned(u32 tid, BufferedStackTrace *stack_, uptr addr)
1330b57cec5SDimitry Andric       : ErrorBase(tid, 10, "bad-malloc_usable_size"),
1340b57cec5SDimitry Andric         stack(stack_),
1350b57cec5SDimitry Andric         addr_description(addr, /*shouldLockThreadRegistry=*/false) {}
1360b57cec5SDimitry Andric   void Print();
1370b57cec5SDimitry Andric };
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric struct ErrorSanitizerGetAllocatedSizeNotOwned : ErrorBase {
1400b57cec5SDimitry Andric   const BufferedStackTrace *stack;
1410b57cec5SDimitry Andric   AddressDescription addr_description;
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric   ErrorSanitizerGetAllocatedSizeNotOwned() = default;  // (*)
ErrorSanitizerGetAllocatedSizeNotOwnedErrorSanitizerGetAllocatedSizeNotOwned1440b57cec5SDimitry Andric   ErrorSanitizerGetAllocatedSizeNotOwned(u32 tid, BufferedStackTrace *stack_,
1450b57cec5SDimitry Andric                                          uptr addr)
1460b57cec5SDimitry Andric       : ErrorBase(tid, 10, "bad-__sanitizer_get_allocated_size"),
1470b57cec5SDimitry Andric         stack(stack_),
1480b57cec5SDimitry Andric         addr_description(addr, /*shouldLockThreadRegistry=*/false) {}
1490b57cec5SDimitry Andric   void Print();
1500b57cec5SDimitry Andric };
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric struct ErrorCallocOverflow : ErrorBase {
1530b57cec5SDimitry Andric   const BufferedStackTrace *stack;
1540b57cec5SDimitry Andric   uptr count;
1550b57cec5SDimitry Andric   uptr size;
1560b57cec5SDimitry Andric 
1570b57cec5SDimitry Andric   ErrorCallocOverflow() = default;  // (*)
ErrorCallocOverflowErrorCallocOverflow1580b57cec5SDimitry Andric   ErrorCallocOverflow(u32 tid, BufferedStackTrace *stack_, uptr count_,
1590b57cec5SDimitry Andric                       uptr size_)
1600b57cec5SDimitry Andric       : ErrorBase(tid, 10, "calloc-overflow"),
1610b57cec5SDimitry Andric         stack(stack_),
1620b57cec5SDimitry Andric         count(count_),
1630b57cec5SDimitry Andric         size(size_) {}
1640b57cec5SDimitry Andric   void Print();
1650b57cec5SDimitry Andric };
1660b57cec5SDimitry Andric 
1670b57cec5SDimitry Andric struct ErrorReallocArrayOverflow : ErrorBase {
1680b57cec5SDimitry Andric   const BufferedStackTrace *stack;
1690b57cec5SDimitry Andric   uptr count;
1700b57cec5SDimitry Andric   uptr size;
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric   ErrorReallocArrayOverflow() = default;  // (*)
ErrorReallocArrayOverflowErrorReallocArrayOverflow1730b57cec5SDimitry Andric   ErrorReallocArrayOverflow(u32 tid, BufferedStackTrace *stack_, uptr count_,
1740b57cec5SDimitry Andric                             uptr size_)
1750b57cec5SDimitry Andric       : ErrorBase(tid, 10, "reallocarray-overflow"),
1760b57cec5SDimitry Andric         stack(stack_),
1770b57cec5SDimitry Andric         count(count_),
1780b57cec5SDimitry Andric         size(size_) {}
1790b57cec5SDimitry Andric   void Print();
1800b57cec5SDimitry Andric };
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric struct ErrorPvallocOverflow : ErrorBase {
1830b57cec5SDimitry Andric   const BufferedStackTrace *stack;
1840b57cec5SDimitry Andric   uptr size;
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric   ErrorPvallocOverflow() = default;  // (*)
ErrorPvallocOverflowErrorPvallocOverflow1870b57cec5SDimitry Andric   ErrorPvallocOverflow(u32 tid, BufferedStackTrace *stack_, uptr size_)
1880b57cec5SDimitry Andric       : ErrorBase(tid, 10, "pvalloc-overflow"),
1890b57cec5SDimitry Andric         stack(stack_),
1900b57cec5SDimitry Andric         size(size_) {}
1910b57cec5SDimitry Andric   void Print();
1920b57cec5SDimitry Andric };
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric struct ErrorInvalidAllocationAlignment : ErrorBase {
1950b57cec5SDimitry Andric   const BufferedStackTrace *stack;
1960b57cec5SDimitry Andric   uptr alignment;
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric   ErrorInvalidAllocationAlignment() = default;  // (*)
ErrorInvalidAllocationAlignmentErrorInvalidAllocationAlignment1990b57cec5SDimitry Andric   ErrorInvalidAllocationAlignment(u32 tid, BufferedStackTrace *stack_,
2000b57cec5SDimitry Andric                                   uptr alignment_)
2010b57cec5SDimitry Andric       : ErrorBase(tid, 10, "invalid-allocation-alignment"),
2020b57cec5SDimitry Andric         stack(stack_),
2030b57cec5SDimitry Andric         alignment(alignment_) {}
2040b57cec5SDimitry Andric   void Print();
2050b57cec5SDimitry Andric };
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric struct ErrorInvalidAlignedAllocAlignment : ErrorBase {
2080b57cec5SDimitry Andric   const BufferedStackTrace *stack;
2090b57cec5SDimitry Andric   uptr size;
2100b57cec5SDimitry Andric   uptr alignment;
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric   ErrorInvalidAlignedAllocAlignment() = default;  // (*)
ErrorInvalidAlignedAllocAlignmentErrorInvalidAlignedAllocAlignment2130b57cec5SDimitry Andric   ErrorInvalidAlignedAllocAlignment(u32 tid, BufferedStackTrace *stack_,
2140b57cec5SDimitry Andric                                     uptr size_, uptr alignment_)
2150b57cec5SDimitry Andric       : ErrorBase(tid, 10, "invalid-aligned-alloc-alignment"),
2160b57cec5SDimitry Andric         stack(stack_),
2170b57cec5SDimitry Andric         size(size_),
2180b57cec5SDimitry Andric         alignment(alignment_) {}
2190b57cec5SDimitry Andric   void Print();
2200b57cec5SDimitry Andric };
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric struct ErrorInvalidPosixMemalignAlignment : ErrorBase {
2230b57cec5SDimitry Andric   const BufferedStackTrace *stack;
2240b57cec5SDimitry Andric   uptr alignment;
2250b57cec5SDimitry Andric 
2260b57cec5SDimitry Andric   ErrorInvalidPosixMemalignAlignment() = default;  // (*)
ErrorInvalidPosixMemalignAlignmentErrorInvalidPosixMemalignAlignment2270b57cec5SDimitry Andric   ErrorInvalidPosixMemalignAlignment(u32 tid, BufferedStackTrace *stack_,
2280b57cec5SDimitry Andric                                      uptr alignment_)
2290b57cec5SDimitry Andric       : ErrorBase(tid, 10, "invalid-posix-memalign-alignment"),
2300b57cec5SDimitry Andric         stack(stack_),
2310b57cec5SDimitry Andric         alignment(alignment_) {}
2320b57cec5SDimitry Andric   void Print();
2330b57cec5SDimitry Andric };
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric struct ErrorAllocationSizeTooBig : ErrorBase {
2360b57cec5SDimitry Andric   const BufferedStackTrace *stack;
2370b57cec5SDimitry Andric   uptr user_size;
2380b57cec5SDimitry Andric   uptr total_size;
2390b57cec5SDimitry Andric   uptr max_size;
2400b57cec5SDimitry Andric 
2410b57cec5SDimitry Andric   ErrorAllocationSizeTooBig() = default;  // (*)
ErrorAllocationSizeTooBigErrorAllocationSizeTooBig2420b57cec5SDimitry Andric   ErrorAllocationSizeTooBig(u32 tid, BufferedStackTrace *stack_,
2430b57cec5SDimitry Andric                             uptr user_size_, uptr total_size_, uptr max_size_)
2440b57cec5SDimitry Andric       : ErrorBase(tid, 10, "allocation-size-too-big"),
2450b57cec5SDimitry Andric         stack(stack_),
2460b57cec5SDimitry Andric         user_size(user_size_),
2470b57cec5SDimitry Andric         total_size(total_size_),
2480b57cec5SDimitry Andric         max_size(max_size_) {}
2490b57cec5SDimitry Andric   void Print();
2500b57cec5SDimitry Andric };
2510b57cec5SDimitry Andric 
2520b57cec5SDimitry Andric struct ErrorRssLimitExceeded : ErrorBase {
2530b57cec5SDimitry Andric   const BufferedStackTrace *stack;
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric   ErrorRssLimitExceeded() = default;  // (*)
ErrorRssLimitExceededErrorRssLimitExceeded2560b57cec5SDimitry Andric   ErrorRssLimitExceeded(u32 tid, BufferedStackTrace *stack_)
2570b57cec5SDimitry Andric       : ErrorBase(tid, 10, "rss-limit-exceeded"),
2580b57cec5SDimitry Andric         stack(stack_) {}
2590b57cec5SDimitry Andric   void Print();
2600b57cec5SDimitry Andric };
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric struct ErrorOutOfMemory : ErrorBase {
2630b57cec5SDimitry Andric   const BufferedStackTrace *stack;
2640b57cec5SDimitry Andric   uptr requested_size;
2650b57cec5SDimitry Andric 
2660b57cec5SDimitry Andric   ErrorOutOfMemory() = default;  // (*)
ErrorOutOfMemoryErrorOutOfMemory2670b57cec5SDimitry Andric   ErrorOutOfMemory(u32 tid, BufferedStackTrace *stack_, uptr requested_size_)
2680b57cec5SDimitry Andric       : ErrorBase(tid, 10, "out-of-memory"),
2690b57cec5SDimitry Andric         stack(stack_),
2700b57cec5SDimitry Andric         requested_size(requested_size_) {}
2710b57cec5SDimitry Andric   void Print();
2720b57cec5SDimitry Andric };
2730b57cec5SDimitry Andric 
2740b57cec5SDimitry Andric struct ErrorStringFunctionMemoryRangesOverlap : ErrorBase {
2750b57cec5SDimitry Andric   const BufferedStackTrace *stack;
2760b57cec5SDimitry Andric   uptr length1, length2;
2770b57cec5SDimitry Andric   AddressDescription addr1_description;
2780b57cec5SDimitry Andric   AddressDescription addr2_description;
2790b57cec5SDimitry Andric   const char *function;
2800b57cec5SDimitry Andric 
2810b57cec5SDimitry Andric   ErrorStringFunctionMemoryRangesOverlap() = default;  // (*)
ErrorStringFunctionMemoryRangesOverlapErrorStringFunctionMemoryRangesOverlap2820b57cec5SDimitry Andric   ErrorStringFunctionMemoryRangesOverlap(u32 tid, BufferedStackTrace *stack_,
2830b57cec5SDimitry Andric                                          uptr addr1, uptr length1_, uptr addr2,
2840b57cec5SDimitry Andric                                          uptr length2_, const char *function_)
2850b57cec5SDimitry Andric       : ErrorBase(tid),
2860b57cec5SDimitry Andric         stack(stack_),
2870b57cec5SDimitry Andric         length1(length1_),
2880b57cec5SDimitry Andric         length2(length2_),
2890b57cec5SDimitry Andric         addr1_description(addr1, length1, /*shouldLockThreadRegistry=*/false),
2900b57cec5SDimitry Andric         addr2_description(addr2, length2, /*shouldLockThreadRegistry=*/false),
2910b57cec5SDimitry Andric         function(function_) {
2920b57cec5SDimitry Andric     char bug_type[100];
2930b57cec5SDimitry Andric     internal_snprintf(bug_type, sizeof(bug_type), "%s-param-overlap", function);
2940b57cec5SDimitry Andric     scariness.Clear();
2950b57cec5SDimitry Andric     scariness.Scare(10, bug_type);
2960b57cec5SDimitry Andric   }
2970b57cec5SDimitry Andric   void Print();
2980b57cec5SDimitry Andric };
2990b57cec5SDimitry Andric 
3000b57cec5SDimitry Andric struct ErrorStringFunctionSizeOverflow : ErrorBase {
3010b57cec5SDimitry Andric   const BufferedStackTrace *stack;
3020b57cec5SDimitry Andric   AddressDescription addr_description;
3030b57cec5SDimitry Andric   uptr size;
3040b57cec5SDimitry Andric 
3050b57cec5SDimitry Andric   ErrorStringFunctionSizeOverflow() = default;  // (*)
ErrorStringFunctionSizeOverflowErrorStringFunctionSizeOverflow3060b57cec5SDimitry Andric   ErrorStringFunctionSizeOverflow(u32 tid, BufferedStackTrace *stack_,
3070b57cec5SDimitry Andric                                   uptr addr, uptr size_)
3080b57cec5SDimitry Andric       : ErrorBase(tid, 10, "negative-size-param"),
3090b57cec5SDimitry Andric         stack(stack_),
3100b57cec5SDimitry Andric         addr_description(addr, /*shouldLockThreadRegistry=*/false),
3110b57cec5SDimitry Andric         size(size_) {}
3120b57cec5SDimitry Andric   void Print();
3130b57cec5SDimitry Andric };
3140b57cec5SDimitry Andric 
3150b57cec5SDimitry Andric struct ErrorBadParamsToAnnotateContiguousContainer : ErrorBase {
3160b57cec5SDimitry Andric   const BufferedStackTrace *stack;
3170b57cec5SDimitry Andric   uptr beg, end, old_mid, new_mid;
3180b57cec5SDimitry Andric 
3190b57cec5SDimitry Andric   ErrorBadParamsToAnnotateContiguousContainer() = default;  // (*)
3200b57cec5SDimitry Andric   // PS4: Do we want an AddressDescription for beg?
ErrorBadParamsToAnnotateContiguousContainerErrorBadParamsToAnnotateContiguousContainer3210b57cec5SDimitry Andric   ErrorBadParamsToAnnotateContiguousContainer(u32 tid,
3220b57cec5SDimitry Andric                                               BufferedStackTrace *stack_,
3230b57cec5SDimitry Andric                                               uptr beg_, uptr end_,
3240b57cec5SDimitry Andric                                               uptr old_mid_, uptr new_mid_)
3250b57cec5SDimitry Andric       : ErrorBase(tid, 10, "bad-__sanitizer_annotate_contiguous_container"),
3260b57cec5SDimitry Andric         stack(stack_),
3270b57cec5SDimitry Andric         beg(beg_),
3280b57cec5SDimitry Andric         end(end_),
3290b57cec5SDimitry Andric         old_mid(old_mid_),
3300b57cec5SDimitry Andric         new_mid(new_mid_) {}
3310b57cec5SDimitry Andric   void Print();
3320b57cec5SDimitry Andric };
3330b57cec5SDimitry Andric 
334bdd1243dSDimitry Andric struct ErrorBadParamsToAnnotateDoubleEndedContiguousContainer : ErrorBase {
335bdd1243dSDimitry Andric   const BufferedStackTrace *stack;
336bdd1243dSDimitry Andric   uptr storage_beg, storage_end, old_container_beg, old_container_end,
337bdd1243dSDimitry Andric       new_container_beg, new_container_end;
338bdd1243dSDimitry Andric 
339bdd1243dSDimitry Andric   ErrorBadParamsToAnnotateDoubleEndedContiguousContainer() = default;  // (*)
ErrorBadParamsToAnnotateDoubleEndedContiguousContainerErrorBadParamsToAnnotateDoubleEndedContiguousContainer340bdd1243dSDimitry Andric   ErrorBadParamsToAnnotateDoubleEndedContiguousContainer(
341bdd1243dSDimitry Andric       u32 tid, BufferedStackTrace *stack_, uptr storage_beg_, uptr storage_end_,
342bdd1243dSDimitry Andric       uptr old_container_beg_, uptr old_container_end_, uptr new_container_beg_,
343bdd1243dSDimitry Andric       uptr new_container_end_)
344bdd1243dSDimitry Andric       : ErrorBase(tid, 10,
345bdd1243dSDimitry Andric                   "bad-__sanitizer_annotate_double_ended_contiguous_container"),
346bdd1243dSDimitry Andric         stack(stack_),
347bdd1243dSDimitry Andric         storage_beg(storage_beg_),
348bdd1243dSDimitry Andric         storage_end(storage_end_),
349bdd1243dSDimitry Andric         old_container_beg(old_container_beg_),
350bdd1243dSDimitry Andric         old_container_end(old_container_end_),
351bdd1243dSDimitry Andric         new_container_beg(new_container_beg_),
352bdd1243dSDimitry Andric         new_container_end(new_container_end_) {}
353bdd1243dSDimitry Andric   void Print();
354bdd1243dSDimitry Andric };
355bdd1243dSDimitry Andric 
3560b57cec5SDimitry Andric struct ErrorODRViolation : ErrorBase {
3570b57cec5SDimitry Andric   __asan_global global1, global2;
3580b57cec5SDimitry Andric   u32 stack_id1, stack_id2;
3590b57cec5SDimitry Andric 
3600b57cec5SDimitry Andric   ErrorODRViolation() = default;  // (*)
ErrorODRViolationErrorODRViolation3610b57cec5SDimitry Andric   ErrorODRViolation(u32 tid, const __asan_global *g1, u32 stack_id1_,
3620b57cec5SDimitry Andric                     const __asan_global *g2, u32 stack_id2_)
3630b57cec5SDimitry Andric       : ErrorBase(tid, 10, "odr-violation"),
3640b57cec5SDimitry Andric         global1(*g1),
3650b57cec5SDimitry Andric         global2(*g2),
3660b57cec5SDimitry Andric         stack_id1(stack_id1_),
3670b57cec5SDimitry Andric         stack_id2(stack_id2_) {}
3680b57cec5SDimitry Andric   void Print();
3690b57cec5SDimitry Andric };
3700b57cec5SDimitry Andric 
3710b57cec5SDimitry Andric struct ErrorInvalidPointerPair : ErrorBase {
3720b57cec5SDimitry Andric   uptr pc, bp, sp;
3730b57cec5SDimitry Andric   AddressDescription addr1_description;
3740b57cec5SDimitry Andric   AddressDescription addr2_description;
3750b57cec5SDimitry Andric 
3760b57cec5SDimitry Andric   ErrorInvalidPointerPair() = default;  // (*)
ErrorInvalidPointerPairErrorInvalidPointerPair3770b57cec5SDimitry Andric   ErrorInvalidPointerPair(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr p1,
3780b57cec5SDimitry Andric                           uptr p2)
3790b57cec5SDimitry Andric       : ErrorBase(tid, 10, "invalid-pointer-pair"),
3800b57cec5SDimitry Andric         pc(pc_),
3810b57cec5SDimitry Andric         bp(bp_),
3820b57cec5SDimitry Andric         sp(sp_),
3830b57cec5SDimitry Andric         addr1_description(p1, 1, /*shouldLockThreadRegistry=*/false),
3840b57cec5SDimitry Andric         addr2_description(p2, 1, /*shouldLockThreadRegistry=*/false) {}
3850b57cec5SDimitry Andric   void Print();
3860b57cec5SDimitry Andric };
3870b57cec5SDimitry Andric 
3880b57cec5SDimitry Andric struct ErrorGeneric : ErrorBase {
3890b57cec5SDimitry Andric   AddressDescription addr_description;
3900b57cec5SDimitry Andric   uptr pc, bp, sp;
3910b57cec5SDimitry Andric   uptr access_size;
3920b57cec5SDimitry Andric   const char *bug_descr;
3930b57cec5SDimitry Andric   bool is_write;
3940b57cec5SDimitry Andric   u8 shadow_val;
3950b57cec5SDimitry Andric 
3960b57cec5SDimitry Andric   ErrorGeneric() = default;  // (*)
39781ad6265SDimitry Andric   ErrorGeneric(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr addr, bool is_write_,
3980b57cec5SDimitry Andric                uptr access_size_);
3990b57cec5SDimitry Andric   void Print();
4000b57cec5SDimitry Andric };
4010b57cec5SDimitry Andric 
4020b57cec5SDimitry Andric // clang-format off
4030b57cec5SDimitry Andric #define ASAN_FOR_EACH_ERROR_KIND(macro)                    \
4040b57cec5SDimitry Andric   macro(DeadlySignal)                                      \
4050b57cec5SDimitry Andric   macro(DoubleFree)                                        \
4060b57cec5SDimitry Andric   macro(NewDeleteTypeMismatch)                             \
4070b57cec5SDimitry Andric   macro(FreeNotMalloced)                                   \
4080b57cec5SDimitry Andric   macro(AllocTypeMismatch)                                 \
4090b57cec5SDimitry Andric   macro(MallocUsableSizeNotOwned)                          \
4100b57cec5SDimitry Andric   macro(SanitizerGetAllocatedSizeNotOwned)                 \
4110b57cec5SDimitry Andric   macro(CallocOverflow)                                    \
4120b57cec5SDimitry Andric   macro(ReallocArrayOverflow)                              \
4130b57cec5SDimitry Andric   macro(PvallocOverflow)                                   \
4140b57cec5SDimitry Andric   macro(InvalidAllocationAlignment)                        \
4150b57cec5SDimitry Andric   macro(InvalidAlignedAllocAlignment)                      \
4160b57cec5SDimitry Andric   macro(InvalidPosixMemalignAlignment)                     \
4170b57cec5SDimitry Andric   macro(AllocationSizeTooBig)                              \
4180b57cec5SDimitry Andric   macro(RssLimitExceeded)                                  \
4190b57cec5SDimitry Andric   macro(OutOfMemory)                                       \
4200b57cec5SDimitry Andric   macro(StringFunctionMemoryRangesOverlap)                 \
4210b57cec5SDimitry Andric   macro(StringFunctionSizeOverflow)                        \
4220b57cec5SDimitry Andric   macro(BadParamsToAnnotateContiguousContainer)            \
423bdd1243dSDimitry Andric   macro(BadParamsToAnnotateDoubleEndedContiguousContainer) \
4240b57cec5SDimitry Andric   macro(ODRViolation)                                      \
4250b57cec5SDimitry Andric   macro(InvalidPointerPair)                                \
4260b57cec5SDimitry Andric   macro(Generic)
4270b57cec5SDimitry Andric // clang-format on
4280b57cec5SDimitry Andric 
4290b57cec5SDimitry Andric #define ASAN_DEFINE_ERROR_KIND(name) kErrorKind##name,
4300b57cec5SDimitry Andric #define ASAN_ERROR_DESCRIPTION_MEMBER(name) Error##name name;
4310b57cec5SDimitry Andric #define ASAN_ERROR_DESCRIPTION_CONSTRUCTOR(name)                    \
4320b57cec5SDimitry Andric   ErrorDescription(Error##name const &e) : kind(kErrorKind##name) { \
4330b57cec5SDimitry Andric     internal_memcpy(&name, &e, sizeof(name));                       \
4340b57cec5SDimitry Andric   }
4350b57cec5SDimitry Andric #define ASAN_ERROR_DESCRIPTION_PRINT(name) \
4360b57cec5SDimitry Andric   case kErrorKind##name:                   \
4370b57cec5SDimitry Andric     return name.Print();
4380b57cec5SDimitry Andric 
4390b57cec5SDimitry Andric enum ErrorKind {
4400b57cec5SDimitry Andric   kErrorKindInvalid = 0,
4410b57cec5SDimitry Andric   ASAN_FOR_EACH_ERROR_KIND(ASAN_DEFINE_ERROR_KIND)
4420b57cec5SDimitry Andric };
4430b57cec5SDimitry Andric 
4440b57cec5SDimitry Andric struct ErrorDescription {
4450b57cec5SDimitry Andric   ErrorKind kind;
4460b57cec5SDimitry Andric   // We're using a tagged union because it allows us to have a trivially
4470b57cec5SDimitry Andric   // copiable type and use the same structures as the public interface.
4480b57cec5SDimitry Andric   //
4490b57cec5SDimitry Andric   // We can add a wrapper around it to make it "more c++-like", but that would
4500b57cec5SDimitry Andric   // add a lot of code and the benefit wouldn't be that big.
4510b57cec5SDimitry Andric   union {
4520b57cec5SDimitry Andric     ErrorBase Base;
4530b57cec5SDimitry Andric     ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_MEMBER)
4540b57cec5SDimitry Andric   };
4550b57cec5SDimitry Andric 
ErrorDescriptionErrorDescription4560b57cec5SDimitry Andric   ErrorDescription() { internal_memset(this, 0, sizeof(*this)); }
ErrorDescriptionErrorDescription4570b57cec5SDimitry Andric   explicit ErrorDescription(LinkerInitialized) {}
ASAN_FOR_EACH_ERROR_KINDErrorDescription4580b57cec5SDimitry Andric   ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_CONSTRUCTOR)
4590b57cec5SDimitry Andric 
4600b57cec5SDimitry Andric   bool IsValid() { return kind != kErrorKindInvalid; }
PrintErrorDescription4610b57cec5SDimitry Andric   void Print() {
4620b57cec5SDimitry Andric     switch (kind) {
4630b57cec5SDimitry Andric       ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_PRINT)
4640b57cec5SDimitry Andric       case kErrorKindInvalid:
4650b57cec5SDimitry Andric         CHECK(0);
4660b57cec5SDimitry Andric     }
4670b57cec5SDimitry Andric     CHECK(0);
4680b57cec5SDimitry Andric   }
4690b57cec5SDimitry Andric };
4700b57cec5SDimitry Andric 
4710b57cec5SDimitry Andric #undef ASAN_FOR_EACH_ERROR_KIND
4720b57cec5SDimitry Andric #undef ASAN_DEFINE_ERROR_KIND
4730b57cec5SDimitry Andric #undef ASAN_ERROR_DESCRIPTION_MEMBER
4740b57cec5SDimitry Andric #undef ASAN_ERROR_DESCRIPTION_CONSTRUCTOR
4750b57cec5SDimitry Andric #undef ASAN_ERROR_DESCRIPTION_PRINT
4760b57cec5SDimitry Andric 
4770b57cec5SDimitry Andric }  // namespace __asan
4780b57cec5SDimitry Andric 
4790b57cec5SDimitry Andric #endif  // ASAN_ERRORS_H
480