asan_errors.h revision 327952
1193326Sed//===-- asan_errors.h -------------------------------------------*- C++ -*-===//
2193326Sed//
3193326Sed//                     The LLVM Compiler Infrastructure
4193326Sed//
5193326Sed// This file is distributed under the University of Illinois Open Source
6193326Sed// License. See LICENSE.TXT for details.
7193326Sed//
8193326Sed//===----------------------------------------------------------------------===//
9193326Sed//
10193326Sed// This file is a part of AddressSanitizer, an address sanity checker.
11193326Sed//
12193326Sed// ASan-private header for error structures.
13193326Sed//===----------------------------------------------------------------------===//
14252723Sdim#ifndef ASAN_ERRORS_H
15207619Srdivacky#define ASAN_ERRORS_H
16245431Sdim
17193326Sed#include "asan_descriptions.h"
18207619Srdivacky#include "asan_scariness_score.h"
19235633Sdim#include "sanitizer_common/sanitizer_common.h"
20245431Sdim
21252723Sdimnamespace __asan {
22198398Srdivacky
23221345Sdimstruct ErrorBase {
24193326Sed  ErrorBase() = default;
25193326Sed  explicit ErrorBase(u32 tid_) : tid(tid_) {}
26226890Sdim  ScarinessScoreBase scariness;
27193326Sed  u32 tid;
28193326Sed};
29226890Sdim
30198398Srdivackystruct ErrorDeadlySignal : ErrorBase {
31226890Sdim  SignalContext signal;
32224145Sdim  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
33235633Sdim  // constructor
34193326Sed  ErrorDeadlySignal() = default;
35193326Sed  ErrorDeadlySignal(u32 tid, const SignalContext &sig)
36193326Sed      : ErrorBase(tid), signal(sig) {
37193326Sed    scariness.Clear();
38193326Sed    if (signal.IsStackOverflow()) {
39226890Sdim      scariness.Scare(10, "stack-overflow");
40235633Sdim    } else if (!signal.is_memory_access) {
41245431Sdim      scariness.Scare(10, "signal");
42226890Sdim    } else if (signal.addr < GetPageSizeCached()) {
43245431Sdim      scariness.Scare(10, "null-deref");
44245431Sdim    } else if (signal.addr == signal.pc) {
45212904Sdim      scariness.Scare(60, "wild-jump");
46212904Sdim    } else if (signal.write_flag == SignalContext::WRITE) {
47212904Sdim      scariness.Scare(30, "wild-addr-write");
48193326Sed    } else if (signal.write_flag == SignalContext::READ) {
49193326Sed      scariness.Scare(20, "wild-addr-read");
50193326Sed    } else {
51226890Sdim      scariness.Scare(25, "wild-addr");
52201361Srdivacky    }
53193326Sed  }
54198092Srdivacky  void Print();
55245431Sdim};
56245431Sdim
57245431Sdimstruct ErrorDoubleFree : ErrorBase {
58210299Sed  // ErrorDoubleFree doesn't own the stack trace.
59193326Sed  const BufferedStackTrace *second_free_stack;
60198092Srdivacky  HeapAddressDescription addr_description;
61207619Srdivacky  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
62207619Srdivacky  // constructor
63235633Sdim  ErrorDoubleFree() = default;
64198092Srdivacky  ErrorDoubleFree(u32 tid, BufferedStackTrace *stack, uptr addr)
65212904Sdim      : ErrorBase(tid), second_free_stack(stack) {
66193326Sed    CHECK_GT(second_free_stack->size, 0);
67193326Sed    GetHeapAddressInformation(addr, 1, &addr_description);
68226890Sdim    scariness.Clear();
69218893Sdim    scariness.Scare(42, "double-free");
70218893Sdim  }
71193326Sed  void Print();
72193326Sed};
73226890Sdim
74226890Sdimstruct ErrorNewDeleteTypeMismatch : ErrorBase {
75218893Sdim  // ErrorNewDeleteTypeMismatch doesn't own the stack trace.
76218893Sdim  const BufferedStackTrace *free_stack;
77218893Sdim  HeapAddressDescription addr_description;
78218893Sdim  uptr delete_size;
79218893Sdim  uptr delete_alignment;
80218893Sdim  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
81198092Srdivacky  // constructor
82226890Sdim  ErrorNewDeleteTypeMismatch() = default;
83218893Sdim  ErrorNewDeleteTypeMismatch(u32 tid, BufferedStackTrace *stack, uptr addr,
84198092Srdivacky                             uptr delete_size_, uptr delete_alignment_)
85198092Srdivacky      : ErrorBase(tid), free_stack(stack), delete_size(delete_size_),
86226890Sdim        delete_alignment(delete_alignment_) {
87218893Sdim    GetHeapAddressInformation(addr, 1, &addr_description);
88198092Srdivacky    scariness.Clear();
89198092Srdivacky    scariness.Scare(10, "new-delete-type-mismatch");
90218893Sdim  }
91218893Sdim  void Print();
92218893Sdim};
93218893Sdim
94218893Sdimstruct ErrorFreeNotMalloced : ErrorBase {
95198092Srdivacky  // ErrorFreeNotMalloced doesn't own the stack trace.
96198092Srdivacky  const BufferedStackTrace *free_stack;
97198092Srdivacky  AddressDescription addr_description;
98226890Sdim  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
99212904Sdim  // constructor
100252723Sdim  ErrorFreeNotMalloced() = default;
101212904Sdim  ErrorFreeNotMalloced(u32 tid, BufferedStackTrace *stack, uptr addr)
102224145Sdim      : ErrorBase(tid),
103212904Sdim        free_stack(stack),
104212904Sdim        addr_description(addr, /*shouldLockThreadRegistry=*/false) {
105212904Sdim    scariness.Clear();
106212904Sdim    scariness.Scare(40, "bad-free");
107226890Sdim  }
108226890Sdim  void Print();
109224145Sdim};
110212904Sdim
111252723Sdimstruct ErrorAllocTypeMismatch : ErrorBase {
112212904Sdim  // ErrorAllocTypeMismatch doesn't own the stack trace.
113221345Sdim  const BufferedStackTrace *dealloc_stack;
114221345Sdim  HeapAddressDescription addr_description;
115221345Sdim  AllocType alloc_type, dealloc_type;
116221345Sdim  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
117221345Sdim  // constructor
118221345Sdim  ErrorAllocTypeMismatch() = default;
119221345Sdim  ErrorAllocTypeMismatch(u32 tid, BufferedStackTrace *stack, uptr addr,
120221345Sdim                         AllocType alloc_type_, AllocType dealloc_type_)
121221345Sdim      : ErrorBase(tid),
122245431Sdim        dealloc_stack(stack),
123212904Sdim        alloc_type(alloc_type_),
124193326Sed        dealloc_type(dealloc_type_) {
125226890Sdim    GetHeapAddressInformation(addr, 1, &addr_description);
126235633Sdim    scariness.Clear();
127206084Srdivacky    scariness.Scare(10, "alloc-dealloc-mismatch");
128206084Srdivacky  };
129206084Srdivacky  void Print();
130206084Srdivacky};
131206084Srdivacky
132206084Srdivackystruct ErrorMallocUsableSizeNotOwned : ErrorBase {
133206084Srdivacky  // ErrorMallocUsableSizeNotOwned doesn't own the stack trace.
134206084Srdivacky  const BufferedStackTrace *stack;
135226890Sdim  AddressDescription addr_description;
136206084Srdivacky  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
137206084Srdivacky  // constructor
138206084Srdivacky  ErrorMallocUsableSizeNotOwned() = default;
139206084Srdivacky  ErrorMallocUsableSizeNotOwned(u32 tid, BufferedStackTrace *stack_, uptr addr)
140206084Srdivacky      : ErrorBase(tid),
141206084Srdivacky        stack(stack_),
142226890Sdim        addr_description(addr, /*shouldLockThreadRegistry=*/false) {
143226890Sdim    scariness.Clear();
144218893Sdim    scariness.Scare(10, "bad-malloc_usable_size");
145218893Sdim  }
146218893Sdim  void Print();
147198092Srdivacky};
148245431Sdim
149245431Sdimstruct ErrorSanitizerGetAllocatedSizeNotOwned : ErrorBase {
150245431Sdim  // ErrorSanitizerGetAllocatedSizeNotOwned doesn't own the stack trace.
151218893Sdim  const BufferedStackTrace *stack;
152218893Sdim  AddressDescription addr_description;
153218893Sdim  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
154193326Sed  // constructor
155218893Sdim  ErrorSanitizerGetAllocatedSizeNotOwned() = default;
156218893Sdim  ErrorSanitizerGetAllocatedSizeNotOwned(u32 tid, BufferedStackTrace *stack_,
157218893Sdim                                         uptr addr)
158218893Sdim      : ErrorBase(tid),
159218893Sdim        stack(stack_),
160218893Sdim        addr_description(addr, /*shouldLockThreadRegistry=*/false) {
161218893Sdim    scariness.Clear();
162218893Sdim    scariness.Scare(10, "bad-__sanitizer_get_allocated_size");
163193326Sed  }
164193326Sed  void Print();
165226890Sdim};
166235633Sdim
167218893Sdimstruct ErrorStringFunctionMemoryRangesOverlap : ErrorBase {
168218893Sdim  // ErrorStringFunctionMemoryRangesOverlap doesn't own the stack trace.
169218893Sdim  const BufferedStackTrace *stack;
170218893Sdim  uptr length1, length2;
171218893Sdim  AddressDescription addr1_description;
172218893Sdim  AddressDescription addr2_description;
173245431Sdim  const char *function;
174193326Sed  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
175245431Sdim  // constructor
176218893Sdim  ErrorStringFunctionMemoryRangesOverlap() = default;
177235633Sdim  ErrorStringFunctionMemoryRangesOverlap(u32 tid, BufferedStackTrace *stack_,
178235633Sdim                                         uptr addr1, uptr length1_, uptr addr2,
179235633Sdim                                         uptr length2_, const char *function_)
180235633Sdim      : ErrorBase(tid),
181235633Sdim        stack(stack_),
182235633Sdim        length1(length1_),
183226890Sdim        length2(length2_),
184235633Sdim        addr1_description(addr1, length1, /*shouldLockThreadRegistry=*/false),
185226890Sdim        addr2_description(addr2, length2, /*shouldLockThreadRegistry=*/false),
186218893Sdim        function(function_) {
187218893Sdim    char bug_type[100];
188226890Sdim    internal_snprintf(bug_type, sizeof(bug_type), "%s-param-overlap", function);
189218893Sdim    scariness.Clear();
190193326Sed    scariness.Scare(10, bug_type);
191198092Srdivacky  }
192218893Sdim  void Print();
193218893Sdim};
194218893Sdim
195218893Sdimstruct ErrorStringFunctionSizeOverflow : ErrorBase {
196221345Sdim  // ErrorStringFunctionSizeOverflow doesn't own the stack trace.
197218893Sdim  const BufferedStackTrace *stack;
198218893Sdim  AddressDescription addr_description;
199218893Sdim  uptr size;
200218893Sdim  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
201226890Sdim  // constructor
202218893Sdim  ErrorStringFunctionSizeOverflow() = default;
203193326Sed  ErrorStringFunctionSizeOverflow(u32 tid, BufferedStackTrace *stack_,
204193326Sed                                  uptr addr, uptr size_)
205218893Sdim      : ErrorBase(tid),
206218893Sdim        stack(stack_),
207198092Srdivacky        addr_description(addr, /*shouldLockThreadRegistry=*/false),
208218893Sdim        size(size_) {
209218893Sdim    scariness.Clear();
210198092Srdivacky    scariness.Scare(10, "negative-size-param");
211218893Sdim  }
212218893Sdim  void Print();
213218893Sdim};
214226890Sdim
215193326Sedstruct ErrorBadParamsToAnnotateContiguousContainer : ErrorBase {
216193326Sed  // ErrorBadParamsToAnnotateContiguousContainer doesn't own the stack trace.
217218893Sdim  const BufferedStackTrace *stack;
218218893Sdim  uptr beg, end, old_mid, new_mid;
219226890Sdim  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
220218893Sdim  // constructor
221198092Srdivacky  ErrorBadParamsToAnnotateContiguousContainer() = default;
222193326Sed  // PS4: Do we want an AddressDescription for beg?
223218893Sdim  ErrorBadParamsToAnnotateContiguousContainer(u32 tid,
224218893Sdim                                              BufferedStackTrace *stack_,
225218893Sdim                                              uptr beg_, uptr end_,
226218893Sdim                                              uptr old_mid_, uptr new_mid_)
227218893Sdim      : ErrorBase(tid),
228226890Sdim        stack(stack_),
229218893Sdim        beg(beg_),
230218893Sdim        end(end_),
231218893Sdim        old_mid(old_mid_),
232212904Sdim        new_mid(new_mid_) {
233226890Sdim    scariness.Clear();
234226890Sdim    scariness.Scare(10, "bad-__sanitizer_annotate_contiguous_container");
235226890Sdim  }
236226890Sdim  void Print();
237252723Sdim};
238226890Sdim
239226890Sdimstruct ErrorODRViolation : ErrorBase {
240226890Sdim  __asan_global global1, global2;
241226890Sdim  u32 stack_id1, stack_id2;
242226890Sdim  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
243226890Sdim  // constructor
244226890Sdim  ErrorODRViolation() = default;
245226890Sdim  ErrorODRViolation(u32 tid, const __asan_global *g1, u32 stack_id1_,
246226890Sdim                    const __asan_global *g2, u32 stack_id2_)
247226890Sdim      : ErrorBase(tid),
248235633Sdim        global1(*g1),
249235633Sdim        global2(*g2),
250235633Sdim        stack_id1(stack_id1_),
251235633Sdim        stack_id2(stack_id2_) {
252235633Sdim    scariness.Clear();
253235633Sdim    scariness.Scare(10, "odr-violation");
254235633Sdim  }
255235633Sdim  void Print();
256235633Sdim};
257235633Sdim
258235633Sdimstruct ErrorInvalidPointerPair : ErrorBase {
259235633Sdim  uptr pc, bp, sp;
260235633Sdim  AddressDescription addr1_description;
261235633Sdim  AddressDescription addr2_description;
262235633Sdim  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
263235633Sdim  // constructor
264235633Sdim  ErrorInvalidPointerPair() = default;
265235633Sdim  ErrorInvalidPointerPair(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr p1,
266226890Sdim                          uptr p2)
267226890Sdim      : ErrorBase(tid),
268226890Sdim        pc(pc_),
269226890Sdim        bp(bp_),
270226890Sdim        sp(sp_),
271226890Sdim        addr1_description(p1, 1, /*shouldLockThreadRegistry=*/false),
272226890Sdim        addr2_description(p2, 1, /*shouldLockThreadRegistry=*/false)  {
273226890Sdim    scariness.Clear();
274226890Sdim    scariness.Scare(10, "invalid-pointer-pair");
275226890Sdim  }
276226890Sdim  void Print();
277252723Sdim};
278226890Sdim
279226890Sdimstruct ErrorGeneric : ErrorBase {
280226890Sdim  AddressDescription addr_description;
281226890Sdim  uptr pc, bp, sp;
282226890Sdim  uptr access_size;
283226890Sdim  const char *bug_descr;
284226890Sdim  bool is_write;
285226890Sdim  u8 shadow_val;
286226890Sdim  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
287226890Sdim  // constructor
288226890Sdim  ErrorGeneric() = default;
289226890Sdim  ErrorGeneric(u32 tid, uptr addr, uptr pc_, uptr bp_, uptr sp_, bool is_write_,
290226890Sdim               uptr access_size_);
291226890Sdim  void Print();
292226890Sdim};
293226890Sdim
294226890Sdim// clang-format off
295226890Sdim#define ASAN_FOR_EACH_ERROR_KIND(macro)         \
296235633Sdim  macro(DeadlySignal)                           \
297235633Sdim  macro(DoubleFree)                             \
298235633Sdim  macro(NewDeleteTypeMismatch)                  \
299235633Sdim  macro(FreeNotMalloced)                        \
300235633Sdim  macro(AllocTypeMismatch)                      \
301235633Sdim  macro(MallocUsableSizeNotOwned)               \
302235633Sdim  macro(SanitizerGetAllocatedSizeNotOwned)      \
303235633Sdim  macro(StringFunctionMemoryRangesOverlap)      \
304235633Sdim  macro(StringFunctionSizeOverflow)             \
305235633Sdim  macro(BadParamsToAnnotateContiguousContainer) \
306235633Sdim  macro(ODRViolation)                           \
307235633Sdim  macro(InvalidPointerPair)                     \
308235633Sdim  macro(Generic)
309235633Sdim// clang-format on
310235633Sdim
311235633Sdim#define ASAN_DEFINE_ERROR_KIND(name) kErrorKind##name,
312235633Sdim#define ASAN_ERROR_DESCRIPTION_MEMBER(name) Error##name name;
313226890Sdim#define ASAN_ERROR_DESCRIPTION_CONSTRUCTOR(name) \
314226890Sdim  ErrorDescription(Error##name const &e) : kind(kErrorKind##name), name(e) {}
315226890Sdim#define ASAN_ERROR_DESCRIPTION_PRINT(name) \
316226890Sdim  case kErrorKind##name:                   \
317226890Sdim    return name.Print();
318226890Sdim
319226890Sdimenum ErrorKind {
320226890Sdim  kErrorKindInvalid = 0,
321226890Sdim  ASAN_FOR_EACH_ERROR_KIND(ASAN_DEFINE_ERROR_KIND)
322226890Sdim};
323226890Sdim
324252723Sdimstruct ErrorDescription {
325226890Sdim  ErrorKind kind;
326226890Sdim  // We're using a tagged union because it allows us to have a trivially
327226890Sdim  // copiable type and use the same structures as the public interface.
328226890Sdim  //
329226890Sdim  // We can add a wrapper around it to make it "more c++-like", but that would
330226890Sdim  // add a lot of code and the benefit wouldn't be that big.
331226890Sdim  union {
332226890Sdim    ErrorBase Base;
333226890Sdim    ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_MEMBER)
334226890Sdim  };
335226890Sdim
336226890Sdim  ErrorDescription() { internal_memset(this, 0, sizeof(*this)); }
337226890Sdim  ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_CONSTRUCTOR)
338226890Sdim
339226890Sdim  bool IsValid() { return kind != kErrorKindInvalid; }
340226890Sdim  void Print() {
341226890Sdim    switch (kind) {
342235633Sdim      ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_PRINT)
343235633Sdim      case kErrorKindInvalid:
344235633Sdim        CHECK(0);
345252723Sdim    }
346235633Sdim    CHECK(0);
347235633Sdim  }
348235633Sdim};
349235633Sdim
350235633Sdim#undef ASAN_FOR_EACH_ERROR_KIND
351235633Sdim#undef ASAN_DEFINE_ERROR_KIND
352235633Sdim#undef ASAN_ERROR_DESCRIPTION_MEMBER
353235633Sdim#undef ASAN_ERROR_DESCRIPTION_CONSTRUCTOR
354226890Sdim#undef ASAN_ERROR_DESCRIPTION_PRINT
355223017Sdim
356223017Sdim}  // namespace __asan
357223017Sdim
358223017Sdim#endif  // ASAN_ERRORS_H
359223017Sdim