111
|
1 //===-- asan_errors.h -------------------------------------------*- C++ -*-===//
|
|
2 //
|
145
|
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
4 // See https://llvm.org/LICENSE.txt for license information.
|
|
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
111
|
6 //
|
|
7 //===----------------------------------------------------------------------===//
|
|
8 //
|
|
9 // This file is a part of AddressSanitizer, an address sanity checker.
|
|
10 //
|
|
11 // ASan-private header for error structures.
|
|
12 //===----------------------------------------------------------------------===//
|
|
13 #ifndef ASAN_ERRORS_H
|
|
14 #define ASAN_ERRORS_H
|
|
15
|
|
16 #include "asan_descriptions.h"
|
|
17 #include "asan_scariness_score.h"
|
|
18 #include "sanitizer_common/sanitizer_common.h"
|
|
19
|
|
20 namespace __asan {
|
|
21
|
145
|
22 // (*) VS2013 does not implement unrestricted unions, so we need a trivial
|
|
23 // default constructor explicitly defined for each particular error.
|
|
24
|
|
25 // None of the error classes own the stack traces mentioned in them.
|
|
26
|
111
|
27 struct ErrorBase {
|
|
28 ScarinessScoreBase scariness;
|
|
29 u32 tid;
|
145
|
30
|
|
31 ErrorBase() = default; // (*)
|
|
32 explicit ErrorBase(u32 tid_) : tid(tid_) {}
|
|
33 ErrorBase(u32 tid_, int initial_score, const char *reason) : tid(tid_) {
|
|
34 scariness.Clear();
|
|
35 scariness.Scare(initial_score, reason);
|
|
36 }
|
111
|
37 };
|
|
38
|
|
39 struct ErrorDeadlySignal : ErrorBase {
|
|
40 SignalContext signal;
|
145
|
41
|
|
42 ErrorDeadlySignal() = default; // (*)
|
111
|
43 ErrorDeadlySignal(u32 tid, const SignalContext &sig)
|
145
|
44 : ErrorBase(tid),
|
|
45 signal(sig) {
|
111
|
46 scariness.Clear();
|
|
47 if (signal.IsStackOverflow()) {
|
|
48 scariness.Scare(10, "stack-overflow");
|
|
49 } else if (!signal.is_memory_access) {
|
|
50 scariness.Scare(10, "signal");
|
145
|
51 } else if (signal.is_true_faulting_addr &&
|
|
52 signal.addr < GetPageSizeCached()) {
|
111
|
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
|
|
67 struct ErrorDoubleFree : ErrorBase {
|
|
68 const BufferedStackTrace *second_free_stack;
|
|
69 HeapAddressDescription addr_description;
|
145
|
70
|
|
71 ErrorDoubleFree() = default; // (*)
|
111
|
72 ErrorDoubleFree(u32 tid, BufferedStackTrace *stack, uptr addr)
|
145
|
73 : ErrorBase(tid, 42, "double-free"),
|
|
74 second_free_stack(stack) {
|
111
|
75 CHECK_GT(second_free_stack->size, 0);
|
|
76 GetHeapAddressInformation(addr, 1, &addr_description);
|
|
77 }
|
|
78 void Print();
|
|
79 };
|
|
80
|
145
|
81 struct ErrorNewDeleteTypeMismatch : ErrorBase {
|
111
|
82 const BufferedStackTrace *free_stack;
|
|
83 HeapAddressDescription addr_description;
|
|
84 uptr delete_size;
|
145
|
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_) {
|
111
|
94 GetHeapAddressInformation(addr, 1, &addr_description);
|
|
95 }
|
|
96 void Print();
|
|
97 };
|
|
98
|
|
99 struct ErrorFreeNotMalloced : ErrorBase {
|
|
100 const BufferedStackTrace *free_stack;
|
|
101 AddressDescription addr_description;
|
145
|
102
|
|
103 ErrorFreeNotMalloced() = default; // (*)
|
111
|
104 ErrorFreeNotMalloced(u32 tid, BufferedStackTrace *stack, uptr addr)
|
145
|
105 : ErrorBase(tid, 40, "bad-free"),
|
111
|
106 free_stack(stack),
|
145
|
107 addr_description(addr, /*shouldLockThreadRegistry=*/false) {}
|
111
|
108 void Print();
|
|
109 };
|
|
110
|
|
111 struct ErrorAllocTypeMismatch : ErrorBase {
|
|
112 const BufferedStackTrace *dealloc_stack;
|
|
113 AllocType alloc_type, dealloc_type;
|
145
|
114 AddressDescription addr_description;
|
|
115
|
|
116 ErrorAllocTypeMismatch() = default; // (*)
|
111
|
117 ErrorAllocTypeMismatch(u32 tid, BufferedStackTrace *stack, uptr addr,
|
|
118 AllocType alloc_type_, AllocType dealloc_type_)
|
145
|
119 : ErrorBase(tid, 10, "alloc-dealloc-mismatch"),
|
111
|
120 dealloc_stack(stack),
|
|
121 alloc_type(alloc_type_),
|
145
|
122 dealloc_type(dealloc_type_),
|
|
123 addr_description(addr, 1, false) {}
|
111
|
124 void Print();
|
|
125 };
|
|
126
|
|
127 struct ErrorMallocUsableSizeNotOwned : ErrorBase {
|
|
128 const BufferedStackTrace *stack;
|
|
129 AddressDescription addr_description;
|
145
|
130
|
|
131 ErrorMallocUsableSizeNotOwned() = default; // (*)
|
111
|
132 ErrorMallocUsableSizeNotOwned(u32 tid, BufferedStackTrace *stack_, uptr addr)
|
145
|
133 : ErrorBase(tid, 10, "bad-malloc_usable_size"),
|
111
|
134 stack(stack_),
|
145
|
135 addr_description(addr, /*shouldLockThreadRegistry=*/false) {}
|
111
|
136 void Print();
|
|
137 };
|
|
138
|
|
139 struct ErrorSanitizerGetAllocatedSizeNotOwned : ErrorBase {
|
|
140 const BufferedStackTrace *stack;
|
|
141 AddressDescription addr_description;
|
145
|
142
|
|
143 ErrorSanitizerGetAllocatedSizeNotOwned() = default; // (*)
|
111
|
144 ErrorSanitizerGetAllocatedSizeNotOwned(u32 tid, BufferedStackTrace *stack_,
|
|
145 uptr addr)
|
145
|
146 : ErrorBase(tid, 10, "bad-__sanitizer_get_allocated_size"),
|
|
147 stack(stack_),
|
|
148 addr_description(addr, /*shouldLockThreadRegistry=*/false) {}
|
|
149 void Print();
|
|
150 };
|
|
151
|
|
152 struct 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
|
|
167 struct ErrorReallocArrayOverflow : ErrorBase {
|
|
168 const BufferedStackTrace *stack;
|
|
169 uptr count;
|
|
170 uptr size;
|
|
171
|
|
172 ErrorReallocArrayOverflow() = default; // (*)
|
|
173 ErrorReallocArrayOverflow(u32 tid, BufferedStackTrace *stack_, uptr count_,
|
|
174 uptr size_)
|
|
175 : ErrorBase(tid, 10, "reallocarray-overflow"),
|
|
176 stack(stack_),
|
|
177 count(count_),
|
|
178 size(size_) {}
|
|
179 void Print();
|
|
180 };
|
|
181
|
|
182 struct ErrorPvallocOverflow : ErrorBase {
|
|
183 const BufferedStackTrace *stack;
|
|
184 uptr size;
|
|
185
|
|
186 ErrorPvallocOverflow() = default; // (*)
|
|
187 ErrorPvallocOverflow(u32 tid, BufferedStackTrace *stack_, uptr size_)
|
|
188 : ErrorBase(tid, 10, "pvalloc-overflow"),
|
|
189 stack(stack_),
|
|
190 size(size_) {}
|
|
191 void Print();
|
|
192 };
|
|
193
|
|
194 struct ErrorInvalidAllocationAlignment : ErrorBase {
|
|
195 const BufferedStackTrace *stack;
|
|
196 uptr alignment;
|
|
197
|
|
198 ErrorInvalidAllocationAlignment() = default; // (*)
|
|
199 ErrorInvalidAllocationAlignment(u32 tid, BufferedStackTrace *stack_,
|
|
200 uptr alignment_)
|
|
201 : ErrorBase(tid, 10, "invalid-allocation-alignment"),
|
111
|
202 stack(stack_),
|
145
|
203 alignment(alignment_) {}
|
|
204 void Print();
|
|
205 };
|
|
206
|
|
207 struct ErrorInvalidAlignedAllocAlignment : ErrorBase {
|
|
208 const BufferedStackTrace *stack;
|
|
209 uptr size;
|
|
210 uptr alignment;
|
|
211
|
|
212 ErrorInvalidAlignedAllocAlignment() = default; // (*)
|
|
213 ErrorInvalidAlignedAllocAlignment(u32 tid, BufferedStackTrace *stack_,
|
|
214 uptr size_, uptr alignment_)
|
|
215 : ErrorBase(tid, 10, "invalid-aligned-alloc-alignment"),
|
|
216 stack(stack_),
|
|
217 size(size_),
|
|
218 alignment(alignment_) {}
|
|
219 void Print();
|
|
220 };
|
|
221
|
|
222 struct ErrorInvalidPosixMemalignAlignment : ErrorBase {
|
|
223 const BufferedStackTrace *stack;
|
|
224 uptr alignment;
|
|
225
|
|
226 ErrorInvalidPosixMemalignAlignment() = default; // (*)
|
|
227 ErrorInvalidPosixMemalignAlignment(u32 tid, BufferedStackTrace *stack_,
|
|
228 uptr alignment_)
|
|
229 : ErrorBase(tid, 10, "invalid-posix-memalign-alignment"),
|
|
230 stack(stack_),
|
|
231 alignment(alignment_) {}
|
|
232 void Print();
|
|
233 };
|
|
234
|
|
235 struct ErrorAllocationSizeTooBig : ErrorBase {
|
|
236 const BufferedStackTrace *stack;
|
|
237 uptr user_size;
|
|
238 uptr total_size;
|
|
239 uptr max_size;
|
|
240
|
|
241 ErrorAllocationSizeTooBig() = default; // (*)
|
|
242 ErrorAllocationSizeTooBig(u32 tid, BufferedStackTrace *stack_,
|
|
243 uptr user_size_, uptr total_size_, uptr max_size_)
|
|
244 : ErrorBase(tid, 10, "allocation-size-too-big"),
|
|
245 stack(stack_),
|
|
246 user_size(user_size_),
|
|
247 total_size(total_size_),
|
|
248 max_size(max_size_) {}
|
|
249 void Print();
|
|
250 };
|
|
251
|
|
252 struct ErrorRssLimitExceeded : ErrorBase {
|
|
253 const BufferedStackTrace *stack;
|
|
254
|
|
255 ErrorRssLimitExceeded() = default; // (*)
|
|
256 ErrorRssLimitExceeded(u32 tid, BufferedStackTrace *stack_)
|
|
257 : ErrorBase(tid, 10, "rss-limit-exceeded"),
|
|
258 stack(stack_) {}
|
|
259 void Print();
|
|
260 };
|
|
261
|
|
262 struct ErrorOutOfMemory : ErrorBase {
|
|
263 const BufferedStackTrace *stack;
|
|
264 uptr requested_size;
|
|
265
|
|
266 ErrorOutOfMemory() = default; // (*)
|
|
267 ErrorOutOfMemory(u32 tid, BufferedStackTrace *stack_, uptr requested_size_)
|
|
268 : ErrorBase(tid, 10, "out-of-memory"),
|
|
269 stack(stack_),
|
|
270 requested_size(requested_size_) {}
|
111
|
271 void Print();
|
|
272 };
|
|
273
|
|
274 struct ErrorStringFunctionMemoryRangesOverlap : ErrorBase {
|
|
275 const BufferedStackTrace *stack;
|
|
276 uptr length1, length2;
|
|
277 AddressDescription addr1_description;
|
|
278 AddressDescription addr2_description;
|
|
279 const char *function;
|
145
|
280
|
|
281 ErrorStringFunctionMemoryRangesOverlap() = default; // (*)
|
111
|
282 ErrorStringFunctionMemoryRangesOverlap(u32 tid, BufferedStackTrace *stack_,
|
|
283 uptr addr1, uptr length1_, uptr addr2,
|
|
284 uptr length2_, const char *function_)
|
|
285 : ErrorBase(tid),
|
|
286 stack(stack_),
|
|
287 length1(length1_),
|
|
288 length2(length2_),
|
|
289 addr1_description(addr1, length1, /*shouldLockThreadRegistry=*/false),
|
|
290 addr2_description(addr2, length2, /*shouldLockThreadRegistry=*/false),
|
|
291 function(function_) {
|
|
292 char bug_type[100];
|
|
293 internal_snprintf(bug_type, sizeof(bug_type), "%s-param-overlap", function);
|
|
294 scariness.Clear();
|
|
295 scariness.Scare(10, bug_type);
|
|
296 }
|
|
297 void Print();
|
|
298 };
|
|
299
|
|
300 struct ErrorStringFunctionSizeOverflow : ErrorBase {
|
|
301 const BufferedStackTrace *stack;
|
|
302 AddressDescription addr_description;
|
|
303 uptr size;
|
145
|
304
|
|
305 ErrorStringFunctionSizeOverflow() = default; // (*)
|
111
|
306 ErrorStringFunctionSizeOverflow(u32 tid, BufferedStackTrace *stack_,
|
|
307 uptr addr, uptr size_)
|
145
|
308 : ErrorBase(tid, 10, "negative-size-param"),
|
111
|
309 stack(stack_),
|
|
310 addr_description(addr, /*shouldLockThreadRegistry=*/false),
|
145
|
311 size(size_) {}
|
111
|
312 void Print();
|
|
313 };
|
|
314
|
|
315 struct ErrorBadParamsToAnnotateContiguousContainer : ErrorBase {
|
|
316 const BufferedStackTrace *stack;
|
|
317 uptr beg, end, old_mid, new_mid;
|
145
|
318
|
|
319 ErrorBadParamsToAnnotateContiguousContainer() = default; // (*)
|
111
|
320 // PS4: Do we want an AddressDescription for beg?
|
|
321 ErrorBadParamsToAnnotateContiguousContainer(u32 tid,
|
|
322 BufferedStackTrace *stack_,
|
|
323 uptr beg_, uptr end_,
|
|
324 uptr old_mid_, uptr new_mid_)
|
145
|
325 : ErrorBase(tid, 10, "bad-__sanitizer_annotate_contiguous_container"),
|
111
|
326 stack(stack_),
|
|
327 beg(beg_),
|
|
328 end(end_),
|
|
329 old_mid(old_mid_),
|
145
|
330 new_mid(new_mid_) {}
|
111
|
331 void Print();
|
|
332 };
|
|
333
|
|
334 struct ErrorODRViolation : ErrorBase {
|
|
335 __asan_global global1, global2;
|
|
336 u32 stack_id1, stack_id2;
|
145
|
337
|
|
338 ErrorODRViolation() = default; // (*)
|
111
|
339 ErrorODRViolation(u32 tid, const __asan_global *g1, u32 stack_id1_,
|
|
340 const __asan_global *g2, u32 stack_id2_)
|
145
|
341 : ErrorBase(tid, 10, "odr-violation"),
|
111
|
342 global1(*g1),
|
|
343 global2(*g2),
|
|
344 stack_id1(stack_id1_),
|
145
|
345 stack_id2(stack_id2_) {}
|
111
|
346 void Print();
|
|
347 };
|
|
348
|
|
349 struct ErrorInvalidPointerPair : ErrorBase {
|
|
350 uptr pc, bp, sp;
|
|
351 AddressDescription addr1_description;
|
|
352 AddressDescription addr2_description;
|
145
|
353
|
|
354 ErrorInvalidPointerPair() = default; // (*)
|
111
|
355 ErrorInvalidPointerPair(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr p1,
|
|
356 uptr p2)
|
145
|
357 : ErrorBase(tid, 10, "invalid-pointer-pair"),
|
111
|
358 pc(pc_),
|
|
359 bp(bp_),
|
|
360 sp(sp_),
|
|
361 addr1_description(p1, 1, /*shouldLockThreadRegistry=*/false),
|
145
|
362 addr2_description(p2, 1, /*shouldLockThreadRegistry=*/false) {}
|
111
|
363 void Print();
|
|
364 };
|
|
365
|
|
366 struct ErrorGeneric : ErrorBase {
|
|
367 AddressDescription addr_description;
|
|
368 uptr pc, bp, sp;
|
|
369 uptr access_size;
|
|
370 const char *bug_descr;
|
|
371 bool is_write;
|
|
372 u8 shadow_val;
|
145
|
373
|
|
374 ErrorGeneric() = default; // (*)
|
111
|
375 ErrorGeneric(u32 tid, uptr addr, uptr pc_, uptr bp_, uptr sp_, bool is_write_,
|
|
376 uptr access_size_);
|
|
377 void Print();
|
|
378 };
|
|
379
|
|
380 // clang-format off
|
|
381 #define ASAN_FOR_EACH_ERROR_KIND(macro) \
|
|
382 macro(DeadlySignal) \
|
|
383 macro(DoubleFree) \
|
145
|
384 macro(NewDeleteTypeMismatch) \
|
111
|
385 macro(FreeNotMalloced) \
|
|
386 macro(AllocTypeMismatch) \
|
|
387 macro(MallocUsableSizeNotOwned) \
|
|
388 macro(SanitizerGetAllocatedSizeNotOwned) \
|
145
|
389 macro(CallocOverflow) \
|
|
390 macro(ReallocArrayOverflow) \
|
|
391 macro(PvallocOverflow) \
|
|
392 macro(InvalidAllocationAlignment) \
|
|
393 macro(InvalidAlignedAllocAlignment) \
|
|
394 macro(InvalidPosixMemalignAlignment) \
|
|
395 macro(AllocationSizeTooBig) \
|
|
396 macro(RssLimitExceeded) \
|
|
397 macro(OutOfMemory) \
|
111
|
398 macro(StringFunctionMemoryRangesOverlap) \
|
|
399 macro(StringFunctionSizeOverflow) \
|
|
400 macro(BadParamsToAnnotateContiguousContainer) \
|
|
401 macro(ODRViolation) \
|
|
402 macro(InvalidPointerPair) \
|
|
403 macro(Generic)
|
|
404 // clang-format on
|
|
405
|
|
406 #define ASAN_DEFINE_ERROR_KIND(name) kErrorKind##name,
|
|
407 #define ASAN_ERROR_DESCRIPTION_MEMBER(name) Error##name name;
|
145
|
408 #define ASAN_ERROR_DESCRIPTION_CONSTRUCTOR(name) \
|
|
409 ErrorDescription(Error##name const &e) : kind(kErrorKind##name) { \
|
|
410 internal_memcpy(&name, &e, sizeof(name)); \
|
|
411 }
|
111
|
412 #define ASAN_ERROR_DESCRIPTION_PRINT(name) \
|
|
413 case kErrorKind##name: \
|
|
414 return name.Print();
|
|
415
|
|
416 enum ErrorKind {
|
|
417 kErrorKindInvalid = 0,
|
|
418 ASAN_FOR_EACH_ERROR_KIND(ASAN_DEFINE_ERROR_KIND)
|
|
419 };
|
|
420
|
|
421 struct ErrorDescription {
|
|
422 ErrorKind kind;
|
|
423 // We're using a tagged union because it allows us to have a trivially
|
|
424 // copiable type and use the same structures as the public interface.
|
|
425 //
|
|
426 // We can add a wrapper around it to make it "more c++-like", but that would
|
|
427 // add a lot of code and the benefit wouldn't be that big.
|
|
428 union {
|
|
429 ErrorBase Base;
|
|
430 ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_MEMBER)
|
|
431 };
|
|
432
|
|
433 ErrorDescription() { internal_memset(this, 0, sizeof(*this)); }
|
145
|
434 explicit ErrorDescription(LinkerInitialized) {}
|
111
|
435 ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_CONSTRUCTOR)
|
|
436
|
|
437 bool IsValid() { return kind != kErrorKindInvalid; }
|
|
438 void Print() {
|
|
439 switch (kind) {
|
|
440 ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_PRINT)
|
|
441 case kErrorKindInvalid:
|
|
442 CHECK(0);
|
|
443 }
|
|
444 CHECK(0);
|
|
445 }
|
|
446 };
|
|
447
|
|
448 #undef ASAN_FOR_EACH_ERROR_KIND
|
|
449 #undef ASAN_DEFINE_ERROR_KIND
|
|
450 #undef ASAN_ERROR_DESCRIPTION_MEMBER
|
|
451 #undef ASAN_ERROR_DESCRIPTION_CONSTRUCTOR
|
|
452 #undef ASAN_ERROR_DESCRIPTION_PRINT
|
|
453
|
|
454 } // namespace __asan
|
|
455
|
|
456 #endif // ASAN_ERRORS_H
|