xref: /netbsd-src/external/gpl3/gcc.old/dist/libsanitizer/asan/asan_errors.h (revision 627f7eb200a4419d89b531d55fccd2ee3ffdcde0)
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 // (*) VS2013 does not implement unrestricted unions, so we need a trivial
22 // default constructor explicitly defined for each particular error.
23 
24 // None of the error classes own the stack traces mentioned in them.
25 
26 struct ErrorBase {
27   ScarinessScoreBase scariness;
28   u32 tid;
29 
30   ErrorBase() = default;  // (*)
ErrorBaseErrorBase31   explicit ErrorBase(u32 tid_) : tid(tid_) {}
ErrorBaseErrorBase32   ErrorBase(u32 tid_, int initial_score, const char *reason) : tid(tid_) {
33     scariness.Clear();
34     scariness.Scare(initial_score, reason);
35   }
36 };
37 
38 struct ErrorDeadlySignal : ErrorBase {
39   SignalContext signal;
40 
41   ErrorDeadlySignal() = default;  // (*)
ErrorDeadlySignalErrorDeadlySignal42   ErrorDeadlySignal(u32 tid, const SignalContext &sig)
43       : ErrorBase(tid),
44         signal(sig) {
45     scariness.Clear();
46     if (signal.IsStackOverflow()) {
47       scariness.Scare(10, "stack-overflow");
48     } else if (!signal.is_memory_access) {
49       scariness.Scare(10, "signal");
50     } else if (signal.addr < GetPageSizeCached()) {
51       scariness.Scare(10, "null-deref");
52     } else if (signal.addr == signal.pc) {
53       scariness.Scare(60, "wild-jump");
54     } else if (signal.write_flag == SignalContext::WRITE) {
55       scariness.Scare(30, "wild-addr-write");
56     } else if (signal.write_flag == SignalContext::READ) {
57       scariness.Scare(20, "wild-addr-read");
58     } else {
59       scariness.Scare(25, "wild-addr");
60     }
61   }
62   void Print();
63 };
64 
65 struct ErrorDoubleFree : ErrorBase {
66   const BufferedStackTrace *second_free_stack;
67   HeapAddressDescription addr_description;
68 
69   ErrorDoubleFree() = default;  // (*)
ErrorDoubleFreeErrorDoubleFree70   ErrorDoubleFree(u32 tid, BufferedStackTrace *stack, uptr addr)
71       : ErrorBase(tid, 42, "double-free"),
72         second_free_stack(stack) {
73     CHECK_GT(second_free_stack->size, 0);
74     GetHeapAddressInformation(addr, 1, &addr_description);
75   }
76   void Print();
77 };
78 
79 struct ErrorNewDeleteTypeMismatch : ErrorBase {
80   const BufferedStackTrace *free_stack;
81   HeapAddressDescription addr_description;
82   uptr delete_size;
83   uptr delete_alignment;
84 
85   ErrorNewDeleteTypeMismatch() = default;  // (*)
ErrorNewDeleteTypeMismatchErrorNewDeleteTypeMismatch86   ErrorNewDeleteTypeMismatch(u32 tid, BufferedStackTrace *stack, uptr addr,
87                              uptr delete_size_, uptr delete_alignment_)
88       : ErrorBase(tid, 10, "new-delete-type-mismatch"),
89         free_stack(stack),
90         delete_size(delete_size_),
91         delete_alignment(delete_alignment_) {
92     GetHeapAddressInformation(addr, 1, &addr_description);
93   }
94   void Print();
95 };
96 
97 struct ErrorFreeNotMalloced : ErrorBase {
98   const BufferedStackTrace *free_stack;
99   AddressDescription addr_description;
100 
101   ErrorFreeNotMalloced() = default;  // (*)
ErrorFreeNotMallocedErrorFreeNotMalloced102   ErrorFreeNotMalloced(u32 tid, BufferedStackTrace *stack, uptr addr)
103       : ErrorBase(tid, 40, "bad-free"),
104         free_stack(stack),
105         addr_description(addr, /*shouldLockThreadRegistry=*/false) {}
106   void Print();
107 };
108 
109 struct ErrorAllocTypeMismatch : ErrorBase {
110   const BufferedStackTrace *dealloc_stack;
111   AllocType alloc_type, dealloc_type;
112   AddressDescription addr_description;
113 
114   ErrorAllocTypeMismatch() = default;  // (*)
ErrorAllocTypeMismatchErrorAllocTypeMismatch115   ErrorAllocTypeMismatch(u32 tid, BufferedStackTrace *stack, uptr addr,
116                          AllocType alloc_type_, AllocType dealloc_type_)
117       : ErrorBase(tid, 10, "alloc-dealloc-mismatch"),
118         dealloc_stack(stack),
119         alloc_type(alloc_type_),
120         dealloc_type(dealloc_type_),
121         addr_description(addr, 1, false) {}
122   void Print();
123 };
124 
125 struct ErrorMallocUsableSizeNotOwned : ErrorBase {
126   const BufferedStackTrace *stack;
127   AddressDescription addr_description;
128 
129   ErrorMallocUsableSizeNotOwned() = default;  // (*)
ErrorMallocUsableSizeNotOwnedErrorMallocUsableSizeNotOwned130   ErrorMallocUsableSizeNotOwned(u32 tid, BufferedStackTrace *stack_, uptr addr)
131       : ErrorBase(tid, 10, "bad-malloc_usable_size"),
132         stack(stack_),
133         addr_description(addr, /*shouldLockThreadRegistry=*/false) {}
134   void Print();
135 };
136 
137 struct ErrorSanitizerGetAllocatedSizeNotOwned : ErrorBase {
138   const BufferedStackTrace *stack;
139   AddressDescription addr_description;
140 
141   ErrorSanitizerGetAllocatedSizeNotOwned() = default;  // (*)
ErrorSanitizerGetAllocatedSizeNotOwnedErrorSanitizerGetAllocatedSizeNotOwned142   ErrorSanitizerGetAllocatedSizeNotOwned(u32 tid, BufferedStackTrace *stack_,
143                                          uptr addr)
144       : ErrorBase(tid, 10, "bad-__sanitizer_get_allocated_size"),
145         stack(stack_),
146         addr_description(addr, /*shouldLockThreadRegistry=*/false) {}
147   void Print();
148 };
149 
150 struct ErrorCallocOverflow : ErrorBase {
151   const BufferedStackTrace *stack;
152   uptr count;
153   uptr size;
154 
155   ErrorCallocOverflow() = default;  // (*)
ErrorCallocOverflowErrorCallocOverflow156   ErrorCallocOverflow(u32 tid, BufferedStackTrace *stack_, uptr count_,
157                       uptr size_)
158       : ErrorBase(tid, 10, "calloc-overflow"),
159         stack(stack_),
160         count(count_),
161         size(size_) {}
162   void Print();
163 };
164 
165 struct ErrorPvallocOverflow : ErrorBase {
166   const BufferedStackTrace *stack;
167   uptr size;
168 
169   ErrorPvallocOverflow() = default;  // (*)
ErrorPvallocOverflowErrorPvallocOverflow170   ErrorPvallocOverflow(u32 tid, BufferedStackTrace *stack_, uptr size_)
171       : ErrorBase(tid, 10, "pvalloc-overflow"),
172         stack(stack_),
173         size(size_) {}
174   void Print();
175 };
176 
177 struct ErrorInvalidAllocationAlignment : ErrorBase {
178   const BufferedStackTrace *stack;
179   uptr alignment;
180 
181   ErrorInvalidAllocationAlignment() = default;  // (*)
ErrorInvalidAllocationAlignmentErrorInvalidAllocationAlignment182   ErrorInvalidAllocationAlignment(u32 tid, BufferedStackTrace *stack_,
183                                   uptr alignment_)
184       : ErrorBase(tid, 10, "invalid-allocation-alignment"),
185         stack(stack_),
186         alignment(alignment_) {}
187   void Print();
188 };
189 
190 struct ErrorInvalidAlignedAllocAlignment : ErrorBase {
191   const BufferedStackTrace *stack;
192   uptr size;
193   uptr alignment;
194 
195   ErrorInvalidAlignedAllocAlignment() = default;  // (*)
ErrorInvalidAlignedAllocAlignmentErrorInvalidAlignedAllocAlignment196   ErrorInvalidAlignedAllocAlignment(u32 tid, BufferedStackTrace *stack_,
197                                     uptr size_, uptr alignment_)
198       : ErrorBase(tid, 10, "invalid-aligned-alloc-alignment"),
199         stack(stack_),
200         size(size_),
201         alignment(alignment_) {}
202   void Print();
203 };
204 
205 struct ErrorInvalidPosixMemalignAlignment : ErrorBase {
206   const BufferedStackTrace *stack;
207   uptr alignment;
208 
209   ErrorInvalidPosixMemalignAlignment() = default;  // (*)
ErrorInvalidPosixMemalignAlignmentErrorInvalidPosixMemalignAlignment210   ErrorInvalidPosixMemalignAlignment(u32 tid, BufferedStackTrace *stack_,
211                                      uptr alignment_)
212       : ErrorBase(tid, 10, "invalid-posix-memalign-alignment"),
213         stack(stack_),
214         alignment(alignment_) {}
215   void Print();
216 };
217 
218 struct ErrorAllocationSizeTooBig : ErrorBase {
219   const BufferedStackTrace *stack;
220   uptr user_size;
221   uptr total_size;
222   uptr max_size;
223 
224   ErrorAllocationSizeTooBig() = default;  // (*)
ErrorAllocationSizeTooBigErrorAllocationSizeTooBig225   ErrorAllocationSizeTooBig(u32 tid, BufferedStackTrace *stack_,
226                             uptr user_size_, uptr total_size_, uptr max_size_)
227       : ErrorBase(tid, 10, "allocation-size-too-big"),
228         stack(stack_),
229         user_size(user_size_),
230         total_size(total_size_),
231         max_size(max_size_) {}
232   void Print();
233 };
234 
235 struct ErrorRssLimitExceeded : ErrorBase {
236   const BufferedStackTrace *stack;
237 
238   ErrorRssLimitExceeded() = default;  // (*)
ErrorRssLimitExceededErrorRssLimitExceeded239   ErrorRssLimitExceeded(u32 tid, BufferedStackTrace *stack_)
240       : ErrorBase(tid, 10, "rss-limit-exceeded"),
241         stack(stack_) {}
242   void Print();
243 };
244 
245 struct ErrorOutOfMemory : ErrorBase {
246   const BufferedStackTrace *stack;
247   uptr requested_size;
248 
249   ErrorOutOfMemory() = default;  // (*)
ErrorOutOfMemoryErrorOutOfMemory250   ErrorOutOfMemory(u32 tid, BufferedStackTrace *stack_, uptr requested_size_)
251       : ErrorBase(tid, 10, "out-of-memory"),
252         stack(stack_),
253         requested_size(requested_size_) {}
254   void Print();
255 };
256 
257 struct ErrorStringFunctionMemoryRangesOverlap : ErrorBase {
258   const BufferedStackTrace *stack;
259   uptr length1, length2;
260   AddressDescription addr1_description;
261   AddressDescription addr2_description;
262   const char *function;
263 
264   ErrorStringFunctionMemoryRangesOverlap() = default;  // (*)
ErrorStringFunctionMemoryRangesOverlapErrorStringFunctionMemoryRangesOverlap265   ErrorStringFunctionMemoryRangesOverlap(u32 tid, BufferedStackTrace *stack_,
266                                          uptr addr1, uptr length1_, uptr addr2,
267                                          uptr length2_, const char *function_)
268       : ErrorBase(tid),
269         stack(stack_),
270         length1(length1_),
271         length2(length2_),
272         addr1_description(addr1, length1, /*shouldLockThreadRegistry=*/false),
273         addr2_description(addr2, length2, /*shouldLockThreadRegistry=*/false),
274         function(function_) {
275     char bug_type[100];
276     internal_snprintf(bug_type, sizeof(bug_type), "%s-param-overlap", function);
277     scariness.Clear();
278     scariness.Scare(10, bug_type);
279   }
280   void Print();
281 };
282 
283 struct ErrorStringFunctionSizeOverflow : ErrorBase {
284   const BufferedStackTrace *stack;
285   AddressDescription addr_description;
286   uptr size;
287 
288   ErrorStringFunctionSizeOverflow() = default;  // (*)
ErrorStringFunctionSizeOverflowErrorStringFunctionSizeOverflow289   ErrorStringFunctionSizeOverflow(u32 tid, BufferedStackTrace *stack_,
290                                   uptr addr, uptr size_)
291       : ErrorBase(tid, 10, "negative-size-param"),
292         stack(stack_),
293         addr_description(addr, /*shouldLockThreadRegistry=*/false),
294         size(size_) {}
295   void Print();
296 };
297 
298 struct ErrorBadParamsToAnnotateContiguousContainer : ErrorBase {
299   const BufferedStackTrace *stack;
300   uptr beg, end, old_mid, new_mid;
301 
302   ErrorBadParamsToAnnotateContiguousContainer() = default;  // (*)
303   // PS4: Do we want an AddressDescription for beg?
ErrorBadParamsToAnnotateContiguousContainerErrorBadParamsToAnnotateContiguousContainer304   ErrorBadParamsToAnnotateContiguousContainer(u32 tid,
305                                               BufferedStackTrace *stack_,
306                                               uptr beg_, uptr end_,
307                                               uptr old_mid_, uptr new_mid_)
308       : ErrorBase(tid, 10, "bad-__sanitizer_annotate_contiguous_container"),
309         stack(stack_),
310         beg(beg_),
311         end(end_),
312         old_mid(old_mid_),
313         new_mid(new_mid_) {}
314   void Print();
315 };
316 
317 struct ErrorODRViolation : ErrorBase {
318   __asan_global global1, global2;
319   u32 stack_id1, stack_id2;
320 
321   ErrorODRViolation() = default;  // (*)
ErrorODRViolationErrorODRViolation322   ErrorODRViolation(u32 tid, const __asan_global *g1, u32 stack_id1_,
323                     const __asan_global *g2, u32 stack_id2_)
324       : ErrorBase(tid, 10, "odr-violation"),
325         global1(*g1),
326         global2(*g2),
327         stack_id1(stack_id1_),
328         stack_id2(stack_id2_) {}
329   void Print();
330 };
331 
332 struct ErrorInvalidPointerPair : ErrorBase {
333   uptr pc, bp, sp;
334   AddressDescription addr1_description;
335   AddressDescription addr2_description;
336 
337   ErrorInvalidPointerPair() = default;  // (*)
ErrorInvalidPointerPairErrorInvalidPointerPair338   ErrorInvalidPointerPair(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr p1,
339                           uptr p2)
340       : ErrorBase(tid, 10, "invalid-pointer-pair"),
341         pc(pc_),
342         bp(bp_),
343         sp(sp_),
344         addr1_description(p1, 1, /*shouldLockThreadRegistry=*/false),
345         addr2_description(p2, 1, /*shouldLockThreadRegistry=*/false) {}
346   void Print();
347 };
348 
349 struct ErrorGeneric : ErrorBase {
350   AddressDescription addr_description;
351   uptr pc, bp, sp;
352   uptr access_size;
353   const char *bug_descr;
354   bool is_write;
355   u8 shadow_val;
356 
357   ErrorGeneric() = default;  // (*)
358   ErrorGeneric(u32 tid, uptr addr, uptr pc_, uptr bp_, uptr sp_, bool is_write_,
359                uptr access_size_);
360   void Print();
361 };
362 
363 // clang-format off
364 #define ASAN_FOR_EACH_ERROR_KIND(macro)         \
365   macro(DeadlySignal)                           \
366   macro(DoubleFree)                             \
367   macro(NewDeleteTypeMismatch)                  \
368   macro(FreeNotMalloced)                        \
369   macro(AllocTypeMismatch)                      \
370   macro(MallocUsableSizeNotOwned)               \
371   macro(SanitizerGetAllocatedSizeNotOwned)      \
372   macro(CallocOverflow)                         \
373   macro(PvallocOverflow)                        \
374   macro(InvalidAllocationAlignment)             \
375   macro(InvalidAlignedAllocAlignment)           \
376   macro(InvalidPosixMemalignAlignment)          \
377   macro(AllocationSizeTooBig)                   \
378   macro(RssLimitExceeded)                       \
379   macro(OutOfMemory)                            \
380   macro(StringFunctionMemoryRangesOverlap)      \
381   macro(StringFunctionSizeOverflow)             \
382   macro(BadParamsToAnnotateContiguousContainer) \
383   macro(ODRViolation)                           \
384   macro(InvalidPointerPair)                     \
385   macro(Generic)
386 // clang-format on
387 
388 #define ASAN_DEFINE_ERROR_KIND(name) kErrorKind##name,
389 #define ASAN_ERROR_DESCRIPTION_MEMBER(name) Error##name name;
390 #define ASAN_ERROR_DESCRIPTION_CONSTRUCTOR(name) \
391   ErrorDescription(Error##name const &e) : kind(kErrorKind##name), name(e) {}
392 #define ASAN_ERROR_DESCRIPTION_PRINT(name) \
393   case kErrorKind##name:                   \
394     return name.Print();
395 
396 enum ErrorKind {
397   kErrorKindInvalid = 0,
398   ASAN_FOR_EACH_ERROR_KIND(ASAN_DEFINE_ERROR_KIND)
399 };
400 
401 struct ErrorDescription {
402   ErrorKind kind;
403   // We're using a tagged union because it allows us to have a trivially
404   // copiable type and use the same structures as the public interface.
405   //
406   // We can add a wrapper around it to make it "more c++-like", but that would
407   // add a lot of code and the benefit wouldn't be that big.
408   union {
409     ErrorBase Base;
410     ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_MEMBER)
411   };
412 
ErrorDescriptionErrorDescription413   ErrorDescription() { internal_memset(this, 0, sizeof(*this)); }
ErrorDescriptionErrorDescription414   explicit ErrorDescription(LinkerInitialized) {}
ASAN_FOR_EACH_ERROR_KINDErrorDescription415   ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_CONSTRUCTOR)
416 
417   bool IsValid() { return kind != kErrorKindInvalid; }
PrintErrorDescription418   void Print() {
419     switch (kind) {
420       ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_PRINT)
421       case kErrorKindInvalid:
422         CHECK(0);
423     }
424     CHECK(0);
425   }
426 };
427 
428 #undef ASAN_FOR_EACH_ERROR_KIND
429 #undef ASAN_DEFINE_ERROR_KIND
430 #undef ASAN_ERROR_DESCRIPTION_MEMBER
431 #undef ASAN_ERROR_DESCRIPTION_CONSTRUCTOR
432 #undef ASAN_ERROR_DESCRIPTION_PRINT
433 
434 }  // namespace __asan
435 
436 #endif  // ASAN_ERRORS_H
437