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