re PR c++/63508 (ICE when using bracketed initializer on pointer to member function...
[official-gcc.git] / libsanitizer / asan / asan_errors.h
blobb155f2452af933b2f64dcdf38ecf245050ec8312
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
15 #include "asan_descriptions.h"
16 #include "asan_scariness_score.h"
17 #include "sanitizer_common/sanitizer_common.h"
19 namespace __asan {
21 // (*) VS2013 does not implement unrestricted unions, so we need a trivial
22 // default constructor explicitly defined for each particular error.
24 // None of the error classes own the stack traces mentioned in them.
26 struct ErrorBase {
27 ScarinessScoreBase scariness;
28 u32 tid;
30 ErrorBase() = default; // (*)
31 explicit ErrorBase(u32 tid_) : tid(tid_) {}
32 ErrorBase(u32 tid_, int initial_score, const char *reason) : tid(tid_) {
33 scariness.Clear();
34 scariness.Scare(initial_score, reason);
38 struct ErrorDeadlySignal : ErrorBase {
39 SignalContext signal;
41 ErrorDeadlySignal() = default; // (*)
42 ErrorDeadlySignal(u32 tid, const SignalContext &sig)
43 : ErrorBase(tid),
44 signal(sig) {
45 scariness.Clear();
46 if (signal.IsStackOverflow()) {
47 scariness.Scare(10, "stack-overflow");
48 } else if (!signal.is_memory_access) {
49 scariness.Scare(10, "signal");
50 } else if (signal.addr < GetPageSizeCached()) {
51 scariness.Scare(10, "null-deref");
52 } else if (signal.addr == signal.pc) {
53 scariness.Scare(60, "wild-jump");
54 } else if (signal.write_flag == SignalContext::WRITE) {
55 scariness.Scare(30, "wild-addr-write");
56 } else if (signal.write_flag == SignalContext::READ) {
57 scariness.Scare(20, "wild-addr-read");
58 } else {
59 scariness.Scare(25, "wild-addr");
62 void Print();
65 struct ErrorDoubleFree : ErrorBase {
66 const BufferedStackTrace *second_free_stack;
67 HeapAddressDescription addr_description;
69 ErrorDoubleFree() = default; // (*)
70 ErrorDoubleFree(u32 tid, BufferedStackTrace *stack, uptr addr)
71 : ErrorBase(tid, 42, "double-free"),
72 second_free_stack(stack) {
73 CHECK_GT(second_free_stack->size, 0);
74 GetHeapAddressInformation(addr, 1, &addr_description);
76 void Print();
79 struct ErrorNewDeleteTypeMismatch : ErrorBase {
80 const BufferedStackTrace *free_stack;
81 HeapAddressDescription addr_description;
82 uptr delete_size;
83 uptr delete_alignment;
85 ErrorNewDeleteTypeMismatch() = default; // (*)
86 ErrorNewDeleteTypeMismatch(u32 tid, BufferedStackTrace *stack, uptr addr,
87 uptr delete_size_, uptr delete_alignment_)
88 : ErrorBase(tid, 10, "new-delete-type-mismatch"),
89 free_stack(stack),
90 delete_size(delete_size_),
91 delete_alignment(delete_alignment_) {
92 GetHeapAddressInformation(addr, 1, &addr_description);
94 void Print();
97 struct ErrorFreeNotMalloced : ErrorBase {
98 const BufferedStackTrace *free_stack;
99 AddressDescription addr_description;
101 ErrorFreeNotMalloced() = default; // (*)
102 ErrorFreeNotMalloced(u32 tid, BufferedStackTrace *stack, uptr addr)
103 : ErrorBase(tid, 40, "bad-free"),
104 free_stack(stack),
105 addr_description(addr, /*shouldLockThreadRegistry=*/false) {}
106 void Print();
109 struct ErrorAllocTypeMismatch : ErrorBase {
110 const BufferedStackTrace *dealloc_stack;
111 AllocType alloc_type, dealloc_type;
112 AddressDescription addr_description;
114 ErrorAllocTypeMismatch() = default; // (*)
115 ErrorAllocTypeMismatch(u32 tid, BufferedStackTrace *stack, uptr addr,
116 AllocType alloc_type_, AllocType dealloc_type_)
117 : ErrorBase(tid, 10, "alloc-dealloc-mismatch"),
118 dealloc_stack(stack),
119 alloc_type(alloc_type_),
120 dealloc_type(dealloc_type_),
121 addr_description(addr, 1, false) {}
122 void Print();
125 struct ErrorMallocUsableSizeNotOwned : ErrorBase {
126 const BufferedStackTrace *stack;
127 AddressDescription addr_description;
129 ErrorMallocUsableSizeNotOwned() = default; // (*)
130 ErrorMallocUsableSizeNotOwned(u32 tid, BufferedStackTrace *stack_, uptr addr)
131 : ErrorBase(tid, 10, "bad-malloc_usable_size"),
132 stack(stack_),
133 addr_description(addr, /*shouldLockThreadRegistry=*/false) {}
134 void Print();
137 struct ErrorSanitizerGetAllocatedSizeNotOwned : ErrorBase {
138 const BufferedStackTrace *stack;
139 AddressDescription addr_description;
141 ErrorSanitizerGetAllocatedSizeNotOwned() = default; // (*)
142 ErrorSanitizerGetAllocatedSizeNotOwned(u32 tid, BufferedStackTrace *stack_,
143 uptr addr)
144 : ErrorBase(tid, 10, "bad-__sanitizer_get_allocated_size"),
145 stack(stack_),
146 addr_description(addr, /*shouldLockThreadRegistry=*/false) {}
147 void Print();
150 struct ErrorCallocOverflow : ErrorBase {
151 const BufferedStackTrace *stack;
152 uptr count;
153 uptr size;
155 ErrorCallocOverflow() = default; // (*)
156 ErrorCallocOverflow(u32 tid, BufferedStackTrace *stack_, uptr count_,
157 uptr size_)
158 : ErrorBase(tid, 10, "calloc-overflow"),
159 stack(stack_),
160 count(count_),
161 size(size_) {}
162 void Print();
165 struct ErrorPvallocOverflow : ErrorBase {
166 const BufferedStackTrace *stack;
167 uptr size;
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();
177 struct ErrorInvalidAllocationAlignment : ErrorBase {
178 const BufferedStackTrace *stack;
179 uptr alignment;
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();
190 struct ErrorInvalidAlignedAllocAlignment : ErrorBase {
191 const BufferedStackTrace *stack;
192 uptr size;
193 uptr alignment;
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();
205 struct ErrorInvalidPosixMemalignAlignment : ErrorBase {
206 const BufferedStackTrace *stack;
207 uptr alignment;
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();
218 struct ErrorAllocationSizeTooBig : ErrorBase {
219 const BufferedStackTrace *stack;
220 uptr user_size;
221 uptr total_size;
222 uptr max_size;
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();
235 struct ErrorRssLimitExceeded : ErrorBase {
236 const BufferedStackTrace *stack;
238 ErrorRssLimitExceeded() = default; // (*)
239 ErrorRssLimitExceeded(u32 tid, BufferedStackTrace *stack_)
240 : ErrorBase(tid, 10, "rss-limit-exceeded"),
241 stack(stack_) {}
242 void Print();
245 struct ErrorOutOfMemory : ErrorBase {
246 const BufferedStackTrace *stack;
247 uptr requested_size;
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();
257 struct ErrorStringFunctionMemoryRangesOverlap : ErrorBase {
258 const BufferedStackTrace *stack;
259 uptr length1, length2;
260 AddressDescription addr1_description;
261 AddressDescription addr2_description;
262 const char *function;
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);
280 void Print();
283 struct ErrorStringFunctionSizeOverflow : ErrorBase {
284 const BufferedStackTrace *stack;
285 AddressDescription addr_description;
286 uptr size;
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();
298 struct ErrorBadParamsToAnnotateContiguousContainer : ErrorBase {
299 const BufferedStackTrace *stack;
300 uptr beg, end, old_mid, new_mid;
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();
317 struct ErrorODRViolation : ErrorBase {
318 __asan_global global1, global2;
319 u32 stack_id1, stack_id2;
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();
332 struct ErrorInvalidPointerPair : ErrorBase {
333 uptr pc, bp, sp;
334 AddressDescription addr1_description;
335 AddressDescription addr2_description;
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();
349 struct 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;
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();
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
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();
396 enum ErrorKind {
397 kErrorKindInvalid = 0,
398 ASAN_FOR_EACH_ERROR_KIND(ASAN_DEFINE_ERROR_KIND)
401 struct 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.
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)
413 ErrorDescription() { internal_memset(this, 0, sizeof(*this)); }
414 explicit ErrorDescription(LinkerInitialized) {}
415 ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_CONSTRUCTOR)
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);
424 CHECK(0);
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
434 } // namespace __asan
436 #endif // ASAN_ERRORS_H