asan_errors.h revision 311697
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
21namespace __asan {
22
23struct ErrorBase {
24  ErrorBase() = default;
25  explicit ErrorBase(u32 tid_) : tid(tid_) {}
26  ScarinessScoreBase scariness;
27  u32 tid;
28};
29
30struct 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
50struct 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
90struct 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
107struct 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
125struct 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
142struct 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
163struct 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    scariness.Scare(10, "bad-malloc_usable_size");
176  }
177  void Print();
178};
179
180struct ErrorSanitizerGetAllocatedSizeNotOwned : ErrorBase {
181  // ErrorSanitizerGetAllocatedSizeNotOwned doesn't own the stack trace.
182  const BufferedStackTrace *stack;
183  AddressDescription addr_description;
184  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
185  // constructor
186  ErrorSanitizerGetAllocatedSizeNotOwned() = default;
187  ErrorSanitizerGetAllocatedSizeNotOwned(u32 tid, BufferedStackTrace *stack_,
188                                         uptr addr)
189      : ErrorBase(tid),
190        stack(stack_),
191        addr_description(addr, /*shouldLockThreadRegistry=*/false) {
192    scariness.Clear();
193    scariness.Scare(10, "bad-__sanitizer_get_allocated_size");
194  }
195  void Print();
196};
197
198struct ErrorStringFunctionMemoryRangesOverlap : ErrorBase {
199  // ErrorStringFunctionMemoryRangesOverlap doesn't own the stack trace.
200  const BufferedStackTrace *stack;
201  uptr length1, length2;
202  AddressDescription addr1_description;
203  AddressDescription addr2_description;
204  const char *function;
205  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
206  // constructor
207  ErrorStringFunctionMemoryRangesOverlap() = default;
208  ErrorStringFunctionMemoryRangesOverlap(u32 tid, BufferedStackTrace *stack_,
209                                         uptr addr1, uptr length1_, uptr addr2,
210                                         uptr length2_, const char *function_)
211      : ErrorBase(tid),
212        stack(stack_),
213        length1(length1_),
214        length2(length2_),
215        addr1_description(addr1, length1, /*shouldLockThreadRegistry=*/false),
216        addr2_description(addr2, length2, /*shouldLockThreadRegistry=*/false),
217        function(function_) {
218    char bug_type[100];
219    internal_snprintf(bug_type, sizeof(bug_type), "%s-param-overlap", function);
220    scariness.Clear();
221    scariness.Scare(10, bug_type);
222  }
223  void Print();
224};
225
226struct ErrorStringFunctionSizeOverflow : ErrorBase {
227  // ErrorStringFunctionSizeOverflow doesn't own the stack trace.
228  const BufferedStackTrace *stack;
229  AddressDescription addr_description;
230  uptr size;
231  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
232  // constructor
233  ErrorStringFunctionSizeOverflow() = default;
234  ErrorStringFunctionSizeOverflow(u32 tid, BufferedStackTrace *stack_,
235                                  uptr addr, uptr size_)
236      : ErrorBase(tid),
237        stack(stack_),
238        addr_description(addr, /*shouldLockThreadRegistry=*/false),
239        size(size_) {
240    scariness.Clear();
241    scariness.Scare(10, "negative-size-param");
242  }
243  void Print();
244};
245
246struct ErrorBadParamsToAnnotateContiguousContainer : ErrorBase {
247  // ErrorBadParamsToAnnotateContiguousContainer doesn't own the stack trace.
248  const BufferedStackTrace *stack;
249  uptr beg, end, old_mid, new_mid;
250  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
251  // constructor
252  ErrorBadParamsToAnnotateContiguousContainer() = default;
253  // PS4: Do we want an AddressDescription for beg?
254  ErrorBadParamsToAnnotateContiguousContainer(u32 tid,
255                                              BufferedStackTrace *stack_,
256                                              uptr beg_, uptr end_,
257                                              uptr old_mid_, uptr new_mid_)
258      : ErrorBase(tid),
259        stack(stack_),
260        beg(beg_),
261        end(end_),
262        old_mid(old_mid_),
263        new_mid(new_mid_) {
264    scariness.Clear();
265    scariness.Scare(10, "bad-__sanitizer_annotate_contiguous_container");
266  }
267  void Print();
268};
269
270struct ErrorODRViolation : ErrorBase {
271  __asan_global global1, global2;
272  u32 stack_id1, stack_id2;
273  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
274  // constructor
275  ErrorODRViolation() = default;
276  ErrorODRViolation(u32 tid, const __asan_global *g1, u32 stack_id1_,
277                    const __asan_global *g2, u32 stack_id2_)
278      : ErrorBase(tid),
279        global1(*g1),
280        global2(*g2),
281        stack_id1(stack_id1_),
282        stack_id2(stack_id2_) {
283    scariness.Clear();
284    scariness.Scare(10, "odr-violation");
285  }
286  void Print();
287};
288
289struct ErrorInvalidPointerPair : ErrorBase {
290  uptr pc, bp, sp;
291  AddressDescription addr1_description;
292  AddressDescription addr2_description;
293  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
294  // constructor
295  ErrorInvalidPointerPair() = default;
296  ErrorInvalidPointerPair(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr p1,
297                          uptr p2)
298      : ErrorBase(tid),
299        pc(pc_),
300        bp(bp_),
301        sp(sp_),
302        addr1_description(p1, 1, /*shouldLockThreadRegistry=*/false),
303        addr2_description(p2, 1, /*shouldLockThreadRegistry=*/false)  {
304    scariness.Clear();
305    scariness.Scare(10, "invalid-pointer-pair");
306  }
307  void Print();
308};
309
310struct ErrorGeneric : ErrorBase {
311  AddressDescription addr_description;
312  uptr pc, bp, sp;
313  uptr access_size;
314  const char *bug_descr;
315  bool is_write;
316  u8 shadow_val;
317  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
318  // constructor
319  ErrorGeneric() = default;
320  ErrorGeneric(u32 tid, uptr addr, uptr pc_, uptr bp_, uptr sp_, bool is_write_,
321               uptr access_size_);
322  void Print();
323};
324
325// clang-format off
326#define ASAN_FOR_EACH_ERROR_KIND(macro)         \
327  macro(StackOverflow)                          \
328  macro(DeadlySignal)                           \
329  macro(DoubleFree)                             \
330  macro(NewDeleteSizeMismatch)                  \
331  macro(FreeNotMalloced)                        \
332  macro(AllocTypeMismatch)                      \
333  macro(MallocUsableSizeNotOwned)               \
334  macro(SanitizerGetAllocatedSizeNotOwned)      \
335  macro(StringFunctionMemoryRangesOverlap)      \
336  macro(StringFunctionSizeOverflow)             \
337  macro(BadParamsToAnnotateContiguousContainer) \
338  macro(ODRViolation)                           \
339  macro(InvalidPointerPair)                     \
340  macro(Generic)
341// clang-format on
342
343#define ASAN_DEFINE_ERROR_KIND(name) kErrorKind##name,
344#define ASAN_ERROR_DESCRIPTION_MEMBER(name) Error##name name;
345#define ASAN_ERROR_DESCRIPTION_CONSTRUCTOR(name) \
346  ErrorDescription(Error##name const &e) : kind(kErrorKind##name), name(e) {}
347#define ASAN_ERROR_DESCRIPTION_PRINT(name) \
348  case kErrorKind##name:                   \
349    return name.Print();
350
351enum ErrorKind {
352  kErrorKindInvalid = 0,
353  ASAN_FOR_EACH_ERROR_KIND(ASAN_DEFINE_ERROR_KIND)
354};
355
356struct ErrorDescription {
357  ErrorKind kind;
358  // We're using a tagged union because it allows us to have a trivially
359  // copiable type and use the same structures as the public interface.
360  //
361  // We can add a wrapper around it to make it "more c++-like", but that would
362  // add a lot of code and the benefit wouldn't be that big.
363  union {
364    ErrorBase Base;
365    ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_MEMBER)
366  };
367
368  ErrorDescription() { internal_memset(this, 0, sizeof(*this)); }
369  ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_CONSTRUCTOR)
370
371  bool IsValid() { return kind != kErrorKindInvalid; }
372  void Print() {
373    switch (kind) {
374      ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_PRINT)
375      case kErrorKindInvalid:
376        CHECK(0);
377    }
378    CHECK(0);
379  }
380};
381
382#undef ASAN_FOR_EACH_ERROR_KIND
383#undef ASAN_DEFINE_ERROR_KIND
384#undef ASAN_ERROR_DESCRIPTION_MEMBER
385#undef ASAN_ERROR_DESCRIPTION_CONSTRUCTOR
386#undef ASAN_ERROR_DESCRIPTION_PRINT
387
388}  // namespace __asan
389
390#endif  // ASAN_ERRORS_H
391