asan_errors.h revision 344779
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  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
127struct 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
139struct 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
152struct 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
167struct 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
179struct 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
192struct 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
207struct 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
220struct 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
237struct 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
247struct 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
259struct 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
285struct 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
300struct 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
319struct 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
334struct 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
351struct 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
398enum ErrorKind {
399  kErrorKindInvalid = 0,
400  ASAN_FOR_EACH_ERROR_KIND(ASAN_DEFINE_ERROR_KIND)
401};
402
403struct 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
439