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