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