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