1120586Sbms//===-- asan_errors.h -------------------------------------------*- C++ -*-===//
2120586Sbms//
3120586Sbms// This file is distributed under the University of Illinois Open Source
4120586Sbms// License. See LICENSE.TXT for details.
5120586Sbms//
6120586Sbms//===----------------------------------------------------------------------===//
7120586Sbms//
8120586Sbms// This file is a part of AddressSanitizer, an address sanity checker.
9120586Sbms//
10120586Sbms// ASan-private header for error structures.
11120586Sbms//===----------------------------------------------------------------------===//
12120586Sbms#ifndef ASAN_ERRORS_H
13120586Sbms#define ASAN_ERRORS_H
14120586Sbms
15120586Sbms#include "asan_descriptions.h"
16120586Sbms#include "asan_scariness_score.h"
17120586Sbms#include "sanitizer_common/sanitizer_common.h"
18120586Sbms
19120586Sbmsnamespace __asan {
20120586Sbms
21120586Sbms// (*) VS2013 does not implement unrestricted unions, so we need a trivial
22120586Sbms// default constructor explicitly defined for each particular error.
23120586Sbms
24120586Sbms// None of the error classes own the stack traces mentioned in them.
25120586Sbms
26120586Sbmsstruct ErrorBase {
27120586Sbms  ScarinessScoreBase scariness;
28255495Sjhb  u32 tid;
29131680Sru
30131681Sru  ErrorBase() = default;  // (*)
31120586Sbms  explicit ErrorBase(u32 tid_) : tid(tid_) {}
32120586Sbms  ErrorBase(u32 tid_, int initial_score, const char *reason) : tid(tid_) {
33120586Sbms    scariness.Clear();
34120586Sbms    scariness.Scare(initial_score, reason);
35120586Sbms  }
36120586Sbms};
37120586Sbms
38120586Sbmsstruct ErrorDeadlySignal : ErrorBase {
39131680Sru  SignalContext signal;
40131680Sru
41255495Sjhb  ErrorDeadlySignal() = default;  // (*)
42255495Sjhb  ErrorDeadlySignal(u32 tid, const SignalContext &sig)
43131680Sru      : ErrorBase(tid),
44120586Sbms        signal(sig) {
45120586Sbms    scariness.Clear();
46120586Sbms    if (signal.IsStackOverflow()) {
47120586Sbms      scariness.Scare(10, "stack-overflow");
48120586Sbms    } else if (!signal.is_memory_access) {
49120586Sbms      scariness.Scare(10, "signal");
50255495Sjhb    } else if (signal.addr < GetPageSizeCached()) {
51255495Sjhb      scariness.Scare(10, "null-deref");
52255495Sjhb    } else if (signal.addr == signal.pc) {
53255495Sjhb      scariness.Scare(60, "wild-jump");
54255495Sjhb    } else if (signal.write_flag == SignalContext::WRITE) {
55255495Sjhb      scariness.Scare(30, "wild-addr-write");
56255495Sjhb    } else if (signal.write_flag == SignalContext::READ) {
57120586Sbms      scariness.Scare(20, "wild-addr-read");
58120586Sbms    } else {
59120586Sbms      scariness.Scare(25, "wild-addr");
60120586Sbms    }
61120586Sbms  }
62120586Sbms  void Print();
63120586Sbms};
64120586Sbms
65120586Sbmsstruct ErrorDoubleFree : ErrorBase {
66120586Sbms  const BufferedStackTrace *second_free_stack;
67120586Sbms  HeapAddressDescription addr_description;
68120586Sbms
69120586Sbms  ErrorDoubleFree() = default;  // (*)
70131680Sru  ErrorDoubleFree(u32 tid, BufferedStackTrace *stack, uptr addr)
71131680Sru      : ErrorBase(tid, 42, "double-free"),
72131680Sru        second_free_stack(stack) {
73120586Sbms    CHECK_GT(second_free_stack->size, 0);
74120586Sbms    GetHeapAddressInformation(addr, 1, &addr_description);
75120586Sbms  }
76255495Sjhb  void Print();
77255495Sjhb};
78255495Sjhb
79255495Sjhbstruct ErrorNewDeleteTypeMismatch : ErrorBase {
80255495Sjhb  const BufferedStackTrace *free_stack;
81255495Sjhb  HeapAddressDescription addr_description;
82255495Sjhb  uptr delete_size;
83255495Sjhb  uptr delete_alignment;
84120586Sbms
85255495Sjhb  ErrorNewDeleteTypeMismatch() = default;  // (*)
86255495Sjhb  ErrorNewDeleteTypeMismatch(u32 tid, BufferedStackTrace *stack, uptr addr,
87255495Sjhb                             uptr delete_size_, uptr delete_alignment_)
88255495Sjhb      : ErrorBase(tid, 10, "new-delete-type-mismatch"),
89120586Sbms        free_stack(stack),
90255495Sjhb        delete_size(delete_size_),
91255495Sjhb        delete_alignment(delete_alignment_) {
92255495Sjhb    GetHeapAddressInformation(addr, 1, &addr_description);
93255495Sjhb  }
94255525Sjoel  void Print();
95255495Sjhb};
96255495Sjhb
97255495Sjhbstruct ErrorFreeNotMalloced : ErrorBase {
98255495Sjhb  const BufferedStackTrace *free_stack;
99255495Sjhb  AddressDescription addr_description;
100255495Sjhb
101255495Sjhb  ErrorFreeNotMalloced() = default;  // (*)
102255495Sjhb  ErrorFreeNotMalloced(u32 tid, BufferedStackTrace *stack, uptr addr)
103255495Sjhb      : ErrorBase(tid, 40, "bad-free"),
104255495Sjhb        free_stack(stack),
105255495Sjhb        addr_description(addr, /*shouldLockThreadRegistry=*/false) {}
106178928Salc  void Print();
107255495Sjhb};
108255495Sjhb
109255495Sjhbstruct ErrorAllocTypeMismatch : ErrorBase {
110255495Sjhb  const BufferedStackTrace *dealloc_stack;
111255495Sjhb  AllocType alloc_type, dealloc_type;
112255495Sjhb  AddressDescription addr_description;
113255495Sjhb
114255495Sjhb  ErrorAllocTypeMismatch() = default;  // (*)
115178928Salc  ErrorAllocTypeMismatch(u32 tid, BufferedStackTrace *stack, uptr addr,
116255495Sjhb                         AllocType alloc_type_, AllocType dealloc_type_)
117255495Sjhb      : ErrorBase(tid, 10, "alloc-dealloc-mismatch"),
118255495Sjhb        dealloc_stack(stack),
119255495Sjhb        alloc_type(alloc_type_),
120255495Sjhb        dealloc_type(dealloc_type_),
121255495Sjhb        addr_description(addr, 1, false) {}
122255495Sjhb  void Print();
123255495Sjhb};
124255495Sjhb
125255495Sjhbstruct ErrorMallocUsableSizeNotOwned : ErrorBase {
126120586Sbms  const BufferedStackTrace *stack;
127120586Sbms  AddressDescription addr_description;
128120586Sbms
129120586Sbms  ErrorMallocUsableSizeNotOwned() = default;  // (*)
130120586Sbms  ErrorMallocUsableSizeNotOwned(u32 tid, BufferedStackTrace *stack_, uptr addr)
131120586Sbms      : ErrorBase(tid, 10, "bad-malloc_usable_size"),
132120586Sbms        stack(stack_),
133120586Sbms        addr_description(addr, /*shouldLockThreadRegistry=*/false) {}
134120586Sbms  void Print();
135120586Sbms};
136120586Sbms
137120586Sbmsstruct ErrorSanitizerGetAllocatedSizeNotOwned : ErrorBase {
138131680Sru  const BufferedStackTrace *stack;
139120586Sbms  AddressDescription addr_description;
140120586Sbms
141178928Salc  ErrorSanitizerGetAllocatedSizeNotOwned() = default;  // (*)
142178928Salc  ErrorSanitizerGetAllocatedSizeNotOwned(u32 tid, BufferedStackTrace *stack_,
143178928Salc                                         uptr addr)
144178928Salc      : ErrorBase(tid, 10, "bad-__sanitizer_get_allocated_size"),
145178928Salc        stack(stack_),
146178928Salc        addr_description(addr, /*shouldLockThreadRegistry=*/false) {}
147178928Salc  void Print();
148178928Salc};
149120586Sbms
150120586Sbmsstruct ErrorCallocOverflow : ErrorBase {
151120586Sbms  const BufferedStackTrace *stack;
152120586Sbms  uptr count;
153120586Sbms  uptr size;
154120586Sbms
155120586Sbms  ErrorCallocOverflow() = default;  // (*)
156120586Sbms  ErrorCallocOverflow(u32 tid, BufferedStackTrace *stack_, uptr count_,
157120586Sbms                      uptr size_)
158120586Sbms      : ErrorBase(tid, 10, "calloc-overflow"),
159120586Sbms        stack(stack_),
160147647Shmp        count(count_),
161120586Sbms        size(size_) {}
162  void Print();
163};
164
165struct ErrorPvallocOverflow : ErrorBase {
166  const BufferedStackTrace *stack;
167  uptr size;
168
169  ErrorPvallocOverflow() = default;  // (*)
170  ErrorPvallocOverflow(u32 tid, BufferedStackTrace *stack_, uptr size_)
171      : ErrorBase(tid, 10, "pvalloc-overflow"),
172        stack(stack_),
173        size(size_) {}
174  void Print();
175};
176
177struct ErrorInvalidAllocationAlignment : ErrorBase {
178  const BufferedStackTrace *stack;
179  uptr alignment;
180
181  ErrorInvalidAllocationAlignment() = default;  // (*)
182  ErrorInvalidAllocationAlignment(u32 tid, BufferedStackTrace *stack_,
183                                  uptr alignment_)
184      : ErrorBase(tid, 10, "invalid-allocation-alignment"),
185        stack(stack_),
186        alignment(alignment_) {}
187  void Print();
188};
189
190struct ErrorInvalidAlignedAllocAlignment : ErrorBase {
191  const BufferedStackTrace *stack;
192  uptr size;
193  uptr alignment;
194
195  ErrorInvalidAlignedAllocAlignment() = default;  // (*)
196  ErrorInvalidAlignedAllocAlignment(u32 tid, BufferedStackTrace *stack_,
197                                    uptr size_, uptr alignment_)
198      : ErrorBase(tid, 10, "invalid-aligned-alloc-alignment"),
199        stack(stack_),
200        size(size_),
201        alignment(alignment_) {}
202  void Print();
203};
204
205struct ErrorInvalidPosixMemalignAlignment : ErrorBase {
206  const BufferedStackTrace *stack;
207  uptr alignment;
208
209  ErrorInvalidPosixMemalignAlignment() = default;  // (*)
210  ErrorInvalidPosixMemalignAlignment(u32 tid, BufferedStackTrace *stack_,
211                                     uptr alignment_)
212      : ErrorBase(tid, 10, "invalid-posix-memalign-alignment"),
213        stack(stack_),
214        alignment(alignment_) {}
215  void Print();
216};
217
218struct ErrorAllocationSizeTooBig : ErrorBase {
219  const BufferedStackTrace *stack;
220  uptr user_size;
221  uptr total_size;
222  uptr max_size;
223
224  ErrorAllocationSizeTooBig() = default;  // (*)
225  ErrorAllocationSizeTooBig(u32 tid, BufferedStackTrace *stack_,
226                            uptr user_size_, uptr total_size_, uptr max_size_)
227      : ErrorBase(tid, 10, "allocation-size-too-big"),
228        stack(stack_),
229        user_size(user_size_),
230        total_size(total_size_),
231        max_size(max_size_) {}
232  void Print();
233};
234
235struct ErrorRssLimitExceeded : ErrorBase {
236  const BufferedStackTrace *stack;
237
238  ErrorRssLimitExceeded() = default;  // (*)
239  ErrorRssLimitExceeded(u32 tid, BufferedStackTrace *stack_)
240      : ErrorBase(tid, 10, "rss-limit-exceeded"),
241        stack(stack_) {}
242  void Print();
243};
244
245struct ErrorOutOfMemory : ErrorBase {
246  const BufferedStackTrace *stack;
247  uptr requested_size;
248
249  ErrorOutOfMemory() = default;  // (*)
250  ErrorOutOfMemory(u32 tid, BufferedStackTrace *stack_, uptr requested_size_)
251      : ErrorBase(tid, 10, "out-of-memory"),
252        stack(stack_),
253        requested_size(requested_size_) {}
254  void Print();
255};
256
257struct ErrorStringFunctionMemoryRangesOverlap : ErrorBase {
258  const BufferedStackTrace *stack;
259  uptr length1, length2;
260  AddressDescription addr1_description;
261  AddressDescription addr2_description;
262  const char *function;
263
264  ErrorStringFunctionMemoryRangesOverlap() = default;  // (*)
265  ErrorStringFunctionMemoryRangesOverlap(u32 tid, BufferedStackTrace *stack_,
266                                         uptr addr1, uptr length1_, uptr addr2,
267                                         uptr length2_, const char *function_)
268      : ErrorBase(tid),
269        stack(stack_),
270        length1(length1_),
271        length2(length2_),
272        addr1_description(addr1, length1, /*shouldLockThreadRegistry=*/false),
273        addr2_description(addr2, length2, /*shouldLockThreadRegistry=*/false),
274        function(function_) {
275    char bug_type[100];
276    internal_snprintf(bug_type, sizeof(bug_type), "%s-param-overlap", function);
277    scariness.Clear();
278    scariness.Scare(10, bug_type);
279  }
280  void Print();
281};
282
283struct ErrorStringFunctionSizeOverflow : ErrorBase {
284  const BufferedStackTrace *stack;
285  AddressDescription addr_description;
286  uptr size;
287
288  ErrorStringFunctionSizeOverflow() = default;  // (*)
289  ErrorStringFunctionSizeOverflow(u32 tid, BufferedStackTrace *stack_,
290                                  uptr addr, uptr size_)
291      : ErrorBase(tid, 10, "negative-size-param"),
292        stack(stack_),
293        addr_description(addr, /*shouldLockThreadRegistry=*/false),
294        size(size_) {}
295  void Print();
296};
297
298struct ErrorBadParamsToAnnotateContiguousContainer : ErrorBase {
299  const BufferedStackTrace *stack;
300  uptr beg, end, old_mid, new_mid;
301
302  ErrorBadParamsToAnnotateContiguousContainer() = default;  // (*)
303  // PS4: Do we want an AddressDescription for beg?
304  ErrorBadParamsToAnnotateContiguousContainer(u32 tid,
305                                              BufferedStackTrace *stack_,
306                                              uptr beg_, uptr end_,
307                                              uptr old_mid_, uptr new_mid_)
308      : ErrorBase(tid, 10, "bad-__sanitizer_annotate_contiguous_container"),
309        stack(stack_),
310        beg(beg_),
311        end(end_),
312        old_mid(old_mid_),
313        new_mid(new_mid_) {}
314  void Print();
315};
316
317struct ErrorODRViolation : ErrorBase {
318  __asan_global global1, global2;
319  u32 stack_id1, stack_id2;
320
321  ErrorODRViolation() = default;  // (*)
322  ErrorODRViolation(u32 tid, const __asan_global *g1, u32 stack_id1_,
323                    const __asan_global *g2, u32 stack_id2_)
324      : ErrorBase(tid, 10, "odr-violation"),
325        global1(*g1),
326        global2(*g2),
327        stack_id1(stack_id1_),
328        stack_id2(stack_id2_) {}
329  void Print();
330};
331
332struct ErrorInvalidPointerPair : ErrorBase {
333  uptr pc, bp, sp;
334  AddressDescription addr1_description;
335  AddressDescription addr2_description;
336
337  ErrorInvalidPointerPair() = default;  // (*)
338  ErrorInvalidPointerPair(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr p1,
339                          uptr p2)
340      : ErrorBase(tid, 10, "invalid-pointer-pair"),
341        pc(pc_),
342        bp(bp_),
343        sp(sp_),
344        addr1_description(p1, 1, /*shouldLockThreadRegistry=*/false),
345        addr2_description(p2, 1, /*shouldLockThreadRegistry=*/false) {}
346  void Print();
347};
348
349struct ErrorGeneric : ErrorBase {
350  AddressDescription addr_description;
351  uptr pc, bp, sp;
352  uptr access_size;
353  const char *bug_descr;
354  bool is_write;
355  u8 shadow_val;
356
357  ErrorGeneric() = default;  // (*)
358  ErrorGeneric(u32 tid, uptr addr, uptr pc_, uptr bp_, uptr sp_, bool is_write_,
359               uptr access_size_);
360  void Print();
361};
362
363// clang-format off
364#define ASAN_FOR_EACH_ERROR_KIND(macro)         \
365  macro(DeadlySignal)                           \
366  macro(DoubleFree)                             \
367  macro(NewDeleteTypeMismatch)                  \
368  macro(FreeNotMalloced)                        \
369  macro(AllocTypeMismatch)                      \
370  macro(MallocUsableSizeNotOwned)               \
371  macro(SanitizerGetAllocatedSizeNotOwned)      \
372  macro(CallocOverflow)                         \
373  macro(PvallocOverflow)                        \
374  macro(InvalidAllocationAlignment)             \
375  macro(InvalidAlignedAllocAlignment)           \
376  macro(InvalidPosixMemalignAlignment)          \
377  macro(AllocationSizeTooBig)                   \
378  macro(RssLimitExceeded)                       \
379  macro(OutOfMemory)                            \
380  macro(StringFunctionMemoryRangesOverlap)      \
381  macro(StringFunctionSizeOverflow)             \
382  macro(BadParamsToAnnotateContiguousContainer) \
383  macro(ODRViolation)                           \
384  macro(InvalidPointerPair)                     \
385  macro(Generic)
386// clang-format on
387
388#define ASAN_DEFINE_ERROR_KIND(name) kErrorKind##name,
389#define ASAN_ERROR_DESCRIPTION_MEMBER(name) Error##name name;
390#define ASAN_ERROR_DESCRIPTION_CONSTRUCTOR(name) \
391  ErrorDescription(Error##name const &e) : kind(kErrorKind##name), name(e) {}
392#define ASAN_ERROR_DESCRIPTION_PRINT(name) \
393  case kErrorKind##name:                   \
394    return name.Print();
395
396enum ErrorKind {
397  kErrorKindInvalid = 0,
398  ASAN_FOR_EACH_ERROR_KIND(ASAN_DEFINE_ERROR_KIND)
399};
400
401struct ErrorDescription {
402  ErrorKind kind;
403  // We're using a tagged union because it allows us to have a trivially
404  // copiable type and use the same structures as the public interface.
405  //
406  // We can add a wrapper around it to make it "more c++-like", but that would
407  // add a lot of code and the benefit wouldn't be that big.
408  union {
409    ErrorBase Base;
410    ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_MEMBER)
411  };
412
413  ErrorDescription() { internal_memset(this, 0, sizeof(*this)); }
414  explicit ErrorDescription(LinkerInitialized) {}
415  ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_CONSTRUCTOR)
416
417  bool IsValid() { return kind != kErrorKindInvalid; }
418  void Print() {
419    switch (kind) {
420      ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_PRINT)
421      case kErrorKindInvalid:
422        CHECK(0);
423    }
424    CHECK(0);
425  }
426};
427
428#undef ASAN_FOR_EACH_ERROR_KIND
429#undef ASAN_DEFINE_ERROR_KIND
430#undef ASAN_ERROR_DESCRIPTION_MEMBER
431#undef ASAN_ERROR_DESCRIPTION_CONSTRUCTOR
432#undef ASAN_ERROR_DESCRIPTION_PRINT
433
434}  // namespace __asan
435
436#endif  // ASAN_ERRORS_H
437