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