asan_errors.h revision 341825
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
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
28struct 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
40struct 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
67struct 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
81struct 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
99struct 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
111struct ErrorAllocTypeMismatch : ErrorBase {
112  const BufferedStackTrace *dealloc_stack;
113  HeapAddressDescription addr_description;
114  AllocType alloc_type, dealloc_type;
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    GetHeapAddressInformation(addr, 1, &addr_description);
124  };
125  void Print();
126};
127
128struct ErrorMallocUsableSizeNotOwned : ErrorBase {
129  const BufferedStackTrace *stack;
130  AddressDescription addr_description;
131
132  ErrorMallocUsableSizeNotOwned() = default;  // (*)
133  ErrorMallocUsableSizeNotOwned(u32 tid, BufferedStackTrace *stack_, uptr addr)
134      : ErrorBase(tid, 10, "bad-malloc_usable_size"),
135        stack(stack_),
136        addr_description(addr, /*shouldLockThreadRegistry=*/false) {}
137  void Print();
138};
139
140struct ErrorSanitizerGetAllocatedSizeNotOwned : ErrorBase {
141  const BufferedStackTrace *stack;
142  AddressDescription addr_description;
143
144  ErrorSanitizerGetAllocatedSizeNotOwned() = default;  // (*)
145  ErrorSanitizerGetAllocatedSizeNotOwned(u32 tid, BufferedStackTrace *stack_,
146                                         uptr addr)
147      : ErrorBase(tid, 10, "bad-__sanitizer_get_allocated_size"),
148        stack(stack_),
149        addr_description(addr, /*shouldLockThreadRegistry=*/false) {}
150  void Print();
151};
152
153struct ErrorCallocOverflow : ErrorBase {
154  const BufferedStackTrace *stack;
155  uptr count;
156  uptr size;
157
158  ErrorCallocOverflow() = default;  // (*)
159  ErrorCallocOverflow(u32 tid, BufferedStackTrace *stack_, uptr count_,
160                      uptr size_)
161      : ErrorBase(tid, 10, "calloc-overflow"),
162        stack(stack_),
163        count(count_),
164        size(size_) {}
165  void Print();
166};
167
168struct ErrorPvallocOverflow : ErrorBase {
169  const BufferedStackTrace *stack;
170  uptr size;
171
172  ErrorPvallocOverflow() = default;  // (*)
173  ErrorPvallocOverflow(u32 tid, BufferedStackTrace *stack_, uptr size_)
174      : ErrorBase(tid, 10, "pvalloc-overflow"),
175        stack(stack_),
176        size(size_) {}
177  void Print();
178};
179
180struct ErrorInvalidAllocationAlignment : ErrorBase {
181  const BufferedStackTrace *stack;
182  uptr alignment;
183
184  ErrorInvalidAllocationAlignment() = default;  // (*)
185  ErrorInvalidAllocationAlignment(u32 tid, BufferedStackTrace *stack_,
186                                  uptr alignment_)
187      : ErrorBase(tid, 10, "invalid-allocation-alignment"),
188        stack(stack_),
189        alignment(alignment_) {}
190  void Print();
191};
192
193struct ErrorInvalidAlignedAllocAlignment : ErrorBase {
194  const BufferedStackTrace *stack;
195  uptr size;
196  uptr alignment;
197
198  ErrorInvalidAlignedAllocAlignment() = default;  // (*)
199  ErrorInvalidAlignedAllocAlignment(u32 tid, BufferedStackTrace *stack_,
200                                    uptr size_, uptr alignment_)
201      : ErrorBase(tid, 10, "invalid-aligned-alloc-alignment"),
202        stack(stack_),
203        size(size_),
204        alignment(alignment_) {}
205  void Print();
206};
207
208struct ErrorInvalidPosixMemalignAlignment : ErrorBase {
209  const BufferedStackTrace *stack;
210  uptr alignment;
211
212  ErrorInvalidPosixMemalignAlignment() = default;  // (*)
213  ErrorInvalidPosixMemalignAlignment(u32 tid, BufferedStackTrace *stack_,
214                                     uptr alignment_)
215      : ErrorBase(tid, 10, "invalid-posix-memalign-alignment"),
216        stack(stack_),
217        alignment(alignment_) {}
218  void Print();
219};
220
221struct ErrorAllocationSizeTooBig : ErrorBase {
222  const BufferedStackTrace *stack;
223  uptr user_size;
224  uptr total_size;
225  uptr max_size;
226
227  ErrorAllocationSizeTooBig() = default;  // (*)
228  ErrorAllocationSizeTooBig(u32 tid, BufferedStackTrace *stack_,
229                            uptr user_size_, uptr total_size_, uptr max_size_)
230      : ErrorBase(tid, 10, "allocation-size-too-big"),
231        stack(stack_),
232        user_size(user_size_),
233        total_size(total_size_),
234        max_size(max_size_) {}
235  void Print();
236};
237
238struct ErrorRssLimitExceeded : ErrorBase {
239  const BufferedStackTrace *stack;
240
241  ErrorRssLimitExceeded() = default;  // (*)
242  ErrorRssLimitExceeded(u32 tid, BufferedStackTrace *stack_)
243      : ErrorBase(tid, 10, "rss-limit-exceeded"),
244        stack(stack_) {}
245  void Print();
246};
247
248struct ErrorOutOfMemory : ErrorBase {
249  const BufferedStackTrace *stack;
250  uptr requested_size;
251
252  ErrorOutOfMemory() = default;  // (*)
253  ErrorOutOfMemory(u32 tid, BufferedStackTrace *stack_, uptr requested_size_)
254      : ErrorBase(tid, 10, "out-of-memory"),
255        stack(stack_),
256        requested_size(requested_size_) {}
257  void Print();
258};
259
260struct ErrorStringFunctionMemoryRangesOverlap : ErrorBase {
261  const BufferedStackTrace *stack;
262  uptr length1, length2;
263  AddressDescription addr1_description;
264  AddressDescription addr2_description;
265  const char *function;
266
267  ErrorStringFunctionMemoryRangesOverlap() = default;  // (*)
268  ErrorStringFunctionMemoryRangesOverlap(u32 tid, BufferedStackTrace *stack_,
269                                         uptr addr1, uptr length1_, uptr addr2,
270                                         uptr length2_, const char *function_)
271      : ErrorBase(tid),
272        stack(stack_),
273        length1(length1_),
274        length2(length2_),
275        addr1_description(addr1, length1, /*shouldLockThreadRegistry=*/false),
276        addr2_description(addr2, length2, /*shouldLockThreadRegistry=*/false),
277        function(function_) {
278    char bug_type[100];
279    internal_snprintf(bug_type, sizeof(bug_type), "%s-param-overlap", function);
280    scariness.Clear();
281    scariness.Scare(10, bug_type);
282  }
283  void Print();
284};
285
286struct ErrorStringFunctionSizeOverflow : ErrorBase {
287  const BufferedStackTrace *stack;
288  AddressDescription addr_description;
289  uptr size;
290
291  ErrorStringFunctionSizeOverflow() = default;  // (*)
292  ErrorStringFunctionSizeOverflow(u32 tid, BufferedStackTrace *stack_,
293                                  uptr addr, uptr size_)
294      : ErrorBase(tid, 10, "negative-size-param"),
295        stack(stack_),
296        addr_description(addr, /*shouldLockThreadRegistry=*/false),
297        size(size_) {}
298  void Print();
299};
300
301struct ErrorBadParamsToAnnotateContiguousContainer : ErrorBase {
302  const BufferedStackTrace *stack;
303  uptr beg, end, old_mid, new_mid;
304
305  ErrorBadParamsToAnnotateContiguousContainer() = default;  // (*)
306  // PS4: Do we want an AddressDescription for beg?
307  ErrorBadParamsToAnnotateContiguousContainer(u32 tid,
308                                              BufferedStackTrace *stack_,
309                                              uptr beg_, uptr end_,
310                                              uptr old_mid_, uptr new_mid_)
311      : ErrorBase(tid, 10, "bad-__sanitizer_annotate_contiguous_container"),
312        stack(stack_),
313        beg(beg_),
314        end(end_),
315        old_mid(old_mid_),
316        new_mid(new_mid_) {}
317  void Print();
318};
319
320struct ErrorODRViolation : ErrorBase {
321  __asan_global global1, global2;
322  u32 stack_id1, stack_id2;
323
324  ErrorODRViolation() = default;  // (*)
325  ErrorODRViolation(u32 tid, const __asan_global *g1, u32 stack_id1_,
326                    const __asan_global *g2, u32 stack_id2_)
327      : ErrorBase(tid, 10, "odr-violation"),
328        global1(*g1),
329        global2(*g2),
330        stack_id1(stack_id1_),
331        stack_id2(stack_id2_) {}
332  void Print();
333};
334
335struct ErrorInvalidPointerPair : ErrorBase {
336  uptr pc, bp, sp;
337  AddressDescription addr1_description;
338  AddressDescription addr2_description;
339
340  ErrorInvalidPointerPair() = default;  // (*)
341  ErrorInvalidPointerPair(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr p1,
342                          uptr p2)
343      : ErrorBase(tid, 10, "invalid-pointer-pair"),
344        pc(pc_),
345        bp(bp_),
346        sp(sp_),
347        addr1_description(p1, 1, /*shouldLockThreadRegistry=*/false),
348        addr2_description(p2, 1, /*shouldLockThreadRegistry=*/false) {}
349  void Print();
350};
351
352struct ErrorGeneric : ErrorBase {
353  AddressDescription addr_description;
354  uptr pc, bp, sp;
355  uptr access_size;
356  const char *bug_descr;
357  bool is_write;
358  u8 shadow_val;
359
360  ErrorGeneric() = default;  // (*)
361  ErrorGeneric(u32 tid, uptr addr, uptr pc_, uptr bp_, uptr sp_, bool is_write_,
362               uptr access_size_);
363  void Print();
364};
365
366// clang-format off
367#define ASAN_FOR_EACH_ERROR_KIND(macro)         \
368  macro(DeadlySignal)                           \
369  macro(DoubleFree)                             \
370  macro(NewDeleteTypeMismatch)                  \
371  macro(FreeNotMalloced)                        \
372  macro(AllocTypeMismatch)                      \
373  macro(MallocUsableSizeNotOwned)               \
374  macro(SanitizerGetAllocatedSizeNotOwned)      \
375  macro(CallocOverflow)                         \
376  macro(PvallocOverflow)                        \
377  macro(InvalidAllocationAlignment)             \
378  macro(InvalidAlignedAllocAlignment)           \
379  macro(InvalidPosixMemalignAlignment)          \
380  macro(AllocationSizeTooBig)                   \
381  macro(RssLimitExceeded)                       \
382  macro(OutOfMemory)                            \
383  macro(StringFunctionMemoryRangesOverlap)      \
384  macro(StringFunctionSizeOverflow)             \
385  macro(BadParamsToAnnotateContiguousContainer) \
386  macro(ODRViolation)                           \
387  macro(InvalidPointerPair)                     \
388  macro(Generic)
389// clang-format on
390
391#define ASAN_DEFINE_ERROR_KIND(name) kErrorKind##name,
392#define ASAN_ERROR_DESCRIPTION_MEMBER(name) Error##name name;
393#define ASAN_ERROR_DESCRIPTION_CONSTRUCTOR(name) \
394  ErrorDescription(Error##name const &e) : kind(kErrorKind##name), name(e) {}
395#define ASAN_ERROR_DESCRIPTION_PRINT(name) \
396  case kErrorKind##name:                   \
397    return name.Print();
398
399enum ErrorKind {
400  kErrorKindInvalid = 0,
401  ASAN_FOR_EACH_ERROR_KIND(ASAN_DEFINE_ERROR_KIND)
402};
403
404struct ErrorDescription {
405  ErrorKind kind;
406  // We're using a tagged union because it allows us to have a trivially
407  // copiable type and use the same structures as the public interface.
408  //
409  // We can add a wrapper around it to make it "more c++-like", but that would
410  // add a lot of code and the benefit wouldn't be that big.
411  union {
412    ErrorBase Base;
413    ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_MEMBER)
414  };
415
416  ErrorDescription() { internal_memset(this, 0, sizeof(*this)); }
417  explicit ErrorDescription(LinkerInitialized) {}
418  ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_CONSTRUCTOR)
419
420  bool IsValid() { return kind != kErrorKindInvalid; }
421  void Print() {
422    switch (kind) {
423      ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_PRINT)
424      case kErrorKindInvalid:
425        CHECK(0);
426    }
427    CHECK(0);
428  }
429};
430
431#undef ASAN_FOR_EACH_ERROR_KIND
432#undef ASAN_DEFINE_ERROR_KIND
433#undef ASAN_ERROR_DESCRIPTION_MEMBER
434#undef ASAN_ERROR_DESCRIPTION_CONSTRUCTOR
435#undef ASAN_ERROR_DESCRIPTION_PRINT
436
437}  // namespace __asan
438
439#endif  // ASAN_ERRORS_H
440