xref: /llvm-project/compiler-rt/lib/asan/asan_errors.h (revision a8b5f5e9d1d5f1f280f1ec2b1948b8e1bc05ef4b)
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   ScarinessScoreBase scariness;
27   u32 tid;
28 };
29 
30 struct ErrorStackOverflow : ErrorBase {
31   uptr addr, pc, bp, sp;
32   // ErrorStackOverflow never owns the context.
33   void *context;
34   // VS2013 doesn't implement unrestricted unions, so we need a trivial default
35   // constructor
36   ErrorStackOverflow() = default;
37   ErrorStackOverflow(u32 tid, const SignalContext &sig)
38       : ErrorBase(tid),
39         addr(sig.addr),
40         pc(sig.pc),
41         bp(sig.bp),
42         sp(sig.sp),
43         context(sig.context) {
44     scariness.Clear();
45     scariness.Scare(10, "stack-overflow");
46   }
47   void Print();
48 };
49 
50 struct ErrorDeadlySignal : ErrorBase {
51   uptr addr, pc, bp, sp;
52   // ErrorDeadlySignal never owns the context.
53   void *context;
54   int signo;
55   SignalContext::WriteFlag write_flag;
56   bool is_memory_access;
57   // VS2013 doesn't implement unrestricted unions, so we need a trivial default
58   // constructor
59   ErrorDeadlySignal() = default;
60   ErrorDeadlySignal(u32 tid, const SignalContext &sig, int signo_)
61       : ErrorBase(tid),
62         addr(sig.addr),
63         pc(sig.pc),
64         bp(sig.bp),
65         sp(sig.sp),
66         context(sig.context),
67         signo(signo_),
68         write_flag(sig.write_flag),
69         is_memory_access(sig.is_memory_access) {
70     scariness.Clear();
71     if (is_memory_access) {
72       if (addr < GetPageSizeCached()) {
73         scariness.Scare(10, "null-deref");
74       } else if (addr == pc) {
75         scariness.Scare(60, "wild-jump");
76       } else if (write_flag == SignalContext::WRITE) {
77         scariness.Scare(30, "wild-addr-write");
78       } else if (write_flag == SignalContext::READ) {
79         scariness.Scare(20, "wild-addr-read");
80       } else {
81         scariness.Scare(25, "wild-addr");
82       }
83     } else {
84       scariness.Scare(10, "signal");
85     }
86   }
87   void Print();
88 };
89 
90 struct ErrorDoubleFree : ErrorBase {
91   // ErrorDoubleFree doesn't own the stack trace.
92   const BufferedStackTrace *second_free_stack;
93   HeapAddressDescription addr_description;
94   // VS2013 doesn't implement unrestricted unions, so we need a trivial default
95   // constructor
96   ErrorDoubleFree() = default;
97   ErrorDoubleFree(u32 tid, BufferedStackTrace *stack, uptr addr)
98       : ErrorBase(tid), second_free_stack(stack) {
99     CHECK_GT(second_free_stack->size, 0);
100     GetHeapAddressInformation(addr, 1, &addr_description);
101     scariness.Clear();
102     scariness.Scare(42, "double-free");
103   }
104   void Print();
105 };
106 
107 struct ErrorNewDeleteSizeMismatch : ErrorBase {
108   // ErrorNewDeleteSizeMismatch doesn't own the stack trace.
109   const BufferedStackTrace *free_stack;
110   HeapAddressDescription addr_description;
111   uptr delete_size;
112   // VS2013 doesn't implement unrestricted unions, so we need a trivial default
113   // constructor
114   ErrorNewDeleteSizeMismatch() = default;
115   ErrorNewDeleteSizeMismatch(u32 tid, BufferedStackTrace *stack, uptr addr,
116                              uptr delete_size_)
117       : ErrorBase(tid), free_stack(stack), delete_size(delete_size_) {
118     GetHeapAddressInformation(addr, 1, &addr_description);
119     scariness.Clear();
120     scariness.Scare(10, "new-delete-type-mismatch");
121   }
122   void Print();
123 };
124 
125 struct ErrorFreeNotMalloced : ErrorBase {
126   // ErrorFreeNotMalloced doesn't own the stack trace.
127   const BufferedStackTrace *free_stack;
128   AddressDescription addr_description;
129   // VS2013 doesn't implement unrestricted unions, so we need a trivial default
130   // constructor
131   ErrorFreeNotMalloced() = default;
132   ErrorFreeNotMalloced(u32 tid, BufferedStackTrace *stack, uptr addr)
133       : ErrorBase(tid),
134         free_stack(stack),
135         addr_description(addr, /*shouldLockThreadRegistry=*/false) {
136     scariness.Clear();
137     scariness.Scare(40, "bad-free");
138   }
139   void Print();
140 };
141 
142 struct ErrorAllocTypeMismatch : ErrorBase {
143   // ErrorAllocTypeMismatch doesn't own the stack trace.
144   const BufferedStackTrace *dealloc_stack;
145   HeapAddressDescription addr_description;
146   AllocType alloc_type, dealloc_type;
147   // VS2013 doesn't implement unrestricted unions, so we need a trivial default
148   // constructor
149   ErrorAllocTypeMismatch() = default;
150   ErrorAllocTypeMismatch(u32 tid, BufferedStackTrace *stack, uptr addr,
151                          AllocType alloc_type_, AllocType dealloc_type_)
152       : ErrorBase(tid),
153         dealloc_stack(stack),
154         alloc_type(alloc_type_),
155         dealloc_type(dealloc_type_) {
156     GetHeapAddressInformation(addr, 1, &addr_description);
157     scariness.Clear();
158     scariness.Scare(10, "alloc-dealloc-mismatch");
159   };
160   void Print();
161 };
162 
163 struct ErrorMallocUsableSizeNotOwned : ErrorBase {
164   // ErrorMallocUsableSizeNotOwned doesn't own the stack trace.
165   const BufferedStackTrace *stack;
166   AddressDescription addr_description;
167   // VS2013 doesn't implement unrestricted unions, so we need a trivial default
168   // constructor
169   ErrorMallocUsableSizeNotOwned() = default;
170   ErrorMallocUsableSizeNotOwned(u32 tid, BufferedStackTrace *stack_, uptr addr)
171       : ErrorBase(tid),
172         stack(stack_),
173         addr_description(addr, /*shouldLockThreadRegistry=*/false) {
174     scariness.Clear();
175   }
176   void Print();
177 };
178 
179 struct ErrorSanitizerGetAllocatedSizeNotOwned : ErrorBase {
180   // ErrorSanitizerGetAllocatedSizeNotOwned doesn't own the stack trace.
181   const BufferedStackTrace *stack;
182   AddressDescription addr_description;
183   // VS2013 doesn't implement unrestricted unions, so we need a trivial default
184   // constructor
185   ErrorSanitizerGetAllocatedSizeNotOwned() = default;
186   ErrorSanitizerGetAllocatedSizeNotOwned(u32 tid, BufferedStackTrace *stack_,
187                                          uptr addr)
188       : ErrorBase(tid),
189         stack(stack_),
190         addr_description(addr, /*shouldLockThreadRegistry=*/false) {
191     scariness.Clear();
192   }
193   void Print();
194 };
195 
196 struct ErrorStringFunctionMemoryRangesOverlap : ErrorBase {
197   // ErrorStringFunctionMemoryRangesOverlap doesn't own the stack trace.
198   const BufferedStackTrace *stack;
199   uptr length1, length2;
200   AddressDescription addr1_description;
201   AddressDescription addr2_description;
202   const char *function;
203   // VS2013 doesn't implement unrestricted unions, so we need a trivial default
204   // constructor
205   ErrorStringFunctionMemoryRangesOverlap() = default;
206   ErrorStringFunctionMemoryRangesOverlap(u32 tid, BufferedStackTrace *stack_,
207                                          uptr addr1, uptr length1_, uptr addr2,
208                                          uptr length2_, const char *function_)
209       : ErrorBase(tid),
210         stack(stack_),
211         length1(length1_),
212         length2(length2_),
213         addr1_description(addr1, length1, /*shouldLockThreadRegistry=*/false),
214         addr2_description(addr2, length2, /*shouldLockThreadRegistry=*/false),
215         function(function_) {
216     char bug_type[100];
217     internal_snprintf(bug_type, sizeof(bug_type), "%s-param-overlap", function);
218     scariness.Clear();
219     scariness.Scare(10, bug_type);
220   }
221   void Print();
222 };
223 
224 struct ErrorStringFunctionSizeOverflow : ErrorBase {
225   // ErrorStringFunctionSizeOverflow doesn't own the stack trace.
226   const BufferedStackTrace *stack;
227   AddressDescription addr_description;
228   uptr size;
229   // VS2013 doesn't implement unrestricted unions, so we need a trivial default
230   // constructor
231   ErrorStringFunctionSizeOverflow() = default;
232   ErrorStringFunctionSizeOverflow(u32 tid, BufferedStackTrace *stack_,
233                                   uptr addr, uptr size_)
234       : ErrorBase(tid),
235         stack(stack_),
236         addr_description(addr, /*shouldLockThreadRegistry=*/false),
237         size(size_) {
238     scariness.Clear();
239     scariness.Scare(10, "negative-size-param");
240   }
241   void Print();
242 };
243 
244 struct ErrorBadParamsToAnnotateContiguousContainer : ErrorBase {
245   // ErrorBadParamsToAnnotateContiguousContainer doesn't own the stack trace.
246   const BufferedStackTrace *stack;
247   uptr beg, end, old_mid, new_mid;
248   // VS2013 doesn't implement unrestricted unions, so we need a trivial default
249   // constructor
250   ErrorBadParamsToAnnotateContiguousContainer() = default;
251   // PS4: Do we want an AddressDescription for beg?
252   ErrorBadParamsToAnnotateContiguousContainer(u32 tid,
253                                               BufferedStackTrace *stack_,
254                                               uptr beg_, uptr end_,
255                                               uptr old_mid_, uptr new_mid_)
256       : ErrorBase(tid),
257         stack(stack_),
258         beg(beg_),
259         end(end_),
260         old_mid(old_mid_),
261         new_mid(new_mid_) {}
262   void Print();
263 };
264 
265 struct ErrorODRViolation : ErrorBase {
266   __asan_global global1, global2;
267   u32 stack_id1, stack_id2;
268   // VS2013 doesn't implement unrestricted unions, so we need a trivial default
269   // constructor
270   ErrorODRViolation() = default;
271   ErrorODRViolation(u32 tid, const __asan_global *g1, u32 stack_id1_,
272                     const __asan_global *g2, u32 stack_id2_)
273       : ErrorBase(tid),
274         global1(*g1),
275         global2(*g2),
276         stack_id1(stack_id1_),
277         stack_id2(stack_id2_) {}
278   void Print();
279 };
280 
281 struct ErrorInvalidPointerPair : ErrorBase {
282   uptr pc, bp, sp;
283   AddressDescription addr1_description;
284   AddressDescription addr2_description;
285   // VS2013 doesn't implement unrestricted unions, so we need a trivial default
286   // constructor
287   ErrorInvalidPointerPair() = default;
288   ErrorInvalidPointerPair(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr p1,
289                           uptr p2)
290       : ErrorBase(tid),
291         pc(pc_),
292         bp(bp_),
293         sp(sp_),
294         addr1_description(p1, 1, /*shouldLockThreadRegistry=*/false),
295         addr2_description(p2, 1, /*shouldLockThreadRegistry=*/false) {}
296   void Print();
297 };
298 
299 struct ErrorGeneric : ErrorBase {
300   AddressDescription addr_description;
301   uptr pc, bp, sp;
302   uptr access_size;
303   const char *bug_descr;
304   bool is_write;
305   u8 shadow_val;
306   // VS2013 doesn't implement unrestricted unions, so we need a trivial default
307   // constructor
308   ErrorGeneric() = default;
309   ErrorGeneric(u32 tid, uptr addr, uptr pc_, uptr bp_, uptr sp_, bool is_write_,
310                uptr access_size_);
311   void Print();
312 };
313 
314 // clang-format off
315 #define ASAN_FOR_EACH_ERROR_KIND(macro)         \
316   macro(StackOverflow)                          \
317   macro(DeadlySignal)                           \
318   macro(DoubleFree)                             \
319   macro(NewDeleteSizeMismatch)                  \
320   macro(FreeNotMalloced)                        \
321   macro(AllocTypeMismatch)                      \
322   macro(MallocUsableSizeNotOwned)               \
323   macro(SanitizerGetAllocatedSizeNotOwned)      \
324   macro(StringFunctionMemoryRangesOverlap)      \
325   macro(StringFunctionSizeOverflow)             \
326   macro(BadParamsToAnnotateContiguousContainer) \
327   macro(ODRViolation)                           \
328   macro(InvalidPointerPair)                     \
329   macro(Generic)
330 // clang-format on
331 
332 #define ASAN_DEFINE_ERROR_KIND(name) kErrorKind##name,
333 #define ASAN_ERROR_DESCRIPTION_MEMBER(name) Error##name name;
334 #define ASAN_ERROR_DESCRIPTION_CONSTRUCTOR(name) \
335   ErrorDescription(Error##name const &e) : kind(kErrorKind##name), name(e) {}
336 #define ASAN_ERROR_DESCRIPTION_PRINT(name) \
337   case kErrorKind##name:                   \
338     return name.Print();
339 
340 enum ErrorKind {
341   kErrorKindInvalid = 0,
342   ASAN_FOR_EACH_ERROR_KIND(ASAN_DEFINE_ERROR_KIND)
343 };
344 
345 struct ErrorDescription {
346   ErrorKind kind;
347   // We're using a tagged union because it allows us to have a trivially
348   // copiable type and use the same structures as the public interface.
349   //
350   // We can add a wrapper around it to make it "more c++-like", but that would
351   // add a lot of code and the benefit wouldn't be that big.
352   union {
353     ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_MEMBER)
354   };
355 
356   ErrorDescription() { internal_memset(this, 0, sizeof(*this)); }
357   ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_CONSTRUCTOR)
358 
359   bool IsValid() { return kind != kErrorKindInvalid; }
360   void Print() {
361     switch (kind) {
362       ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_PRINT)
363       case kErrorKindInvalid:
364         CHECK(0);
365     }
366     CHECK(0);
367   }
368 };
369 
370 #undef ASAN_FOR_EACH_ERROR_KIND
371 #undef ASAN_DEFINE_ERROR_KIND
372 #undef ASAN_ERROR_DESCRIPTION_MEMBER
373 #undef ASAN_ERROR_DESCRIPTION_CONSTRUCTOR
374 #undef ASAN_ERROR_DESCRIPTION_PRINT
375 
376 }  // namespace __asan
377 
378 #endif  // ASAN_ERRORS_H
379