Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/compiler-rt/lib/asan/asan_errors.h
35233 views
1
//===-- asan_errors.h -------------------------------------------*- C++ -*-===//
2
//
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
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
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
27
struct ErrorBase {
28
ScarinessScoreBase scariness;
29
u32 tid;
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
}
37
};
38
39
struct ErrorDeadlySignal : ErrorBase {
40
SignalContext signal;
41
42
ErrorDeadlySignal() = default; // (*)
43
ErrorDeadlySignal(u32 tid, const SignalContext &sig)
44
: ErrorBase(tid),
45
signal(sig) {
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");
51
} else if (signal.is_true_faulting_addr &&
52
signal.addr < GetPageSizeCached()) {
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;
70
71
ErrorDoubleFree() = default; // (*)
72
ErrorDoubleFree(u32 tid, BufferedStackTrace *stack, uptr addr)
73
: ErrorBase(tid, 42, "double-free"),
74
second_free_stack(stack) {
75
CHECK_GT(second_free_stack->size, 0);
76
GetHeapAddressInformation(addr, 1, &addr_description);
77
}
78
void Print();
79
};
80
81
struct ErrorNewDeleteTypeMismatch : ErrorBase {
82
const BufferedStackTrace *free_stack;
83
HeapAddressDescription addr_description;
84
uptr delete_size;
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_) {
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;
102
103
ErrorFreeNotMalloced() = default; // (*)
104
ErrorFreeNotMalloced(u32 tid, BufferedStackTrace *stack, uptr addr)
105
: ErrorBase(tid, 40, "bad-free"),
106
free_stack(stack),
107
addr_description(addr, /*shouldLockThreadRegistry=*/false) {}
108
void Print();
109
};
110
111
struct ErrorAllocTypeMismatch : ErrorBase {
112
const BufferedStackTrace *dealloc_stack;
113
AllocType alloc_type, dealloc_type;
114
AddressDescription addr_description;
115
116
ErrorAllocTypeMismatch() = default; // (*)
117
ErrorAllocTypeMismatch(u32 tid, BufferedStackTrace *stack, uptr addr,
118
AllocType alloc_type_, AllocType dealloc_type_)
119
: ErrorBase(tid, 10, "alloc-dealloc-mismatch"),
120
dealloc_stack(stack),
121
alloc_type(alloc_type_),
122
dealloc_type(dealloc_type_),
123
addr_description(addr, 1, false) {}
124
void Print();
125
};
126
127
struct ErrorMallocUsableSizeNotOwned : ErrorBase {
128
const BufferedStackTrace *stack;
129
AddressDescription addr_description;
130
131
ErrorMallocUsableSizeNotOwned() = default; // (*)
132
ErrorMallocUsableSizeNotOwned(u32 tid, BufferedStackTrace *stack_, uptr addr)
133
: ErrorBase(tid, 10, "bad-malloc_usable_size"),
134
stack(stack_),
135
addr_description(addr, /*shouldLockThreadRegistry=*/false) {}
136
void Print();
137
};
138
139
struct ErrorSanitizerGetAllocatedSizeNotOwned : ErrorBase {
140
const BufferedStackTrace *stack;
141
AddressDescription addr_description;
142
143
ErrorSanitizerGetAllocatedSizeNotOwned() = default; // (*)
144
ErrorSanitizerGetAllocatedSizeNotOwned(u32 tid, BufferedStackTrace *stack_,
145
uptr addr)
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"),
202
stack(stack_),
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_) {}
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;
280
281
ErrorStringFunctionMemoryRangesOverlap() = default; // (*)
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;
304
305
ErrorStringFunctionSizeOverflow() = default; // (*)
306
ErrorStringFunctionSizeOverflow(u32 tid, BufferedStackTrace *stack_,
307
uptr addr, uptr size_)
308
: ErrorBase(tid, 10, "negative-size-param"),
309
stack(stack_),
310
addr_description(addr, /*shouldLockThreadRegistry=*/false),
311
size(size_) {}
312
void Print();
313
};
314
315
struct ErrorBadParamsToAnnotateContiguousContainer : ErrorBase {
316
const BufferedStackTrace *stack;
317
uptr beg, end, old_mid, new_mid;
318
319
ErrorBadParamsToAnnotateContiguousContainer() = default; // (*)
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_)
325
: ErrorBase(tid, 10, "bad-__sanitizer_annotate_contiguous_container"),
326
stack(stack_),
327
beg(beg_),
328
end(end_),
329
old_mid(old_mid_),
330
new_mid(new_mid_) {}
331
void Print();
332
};
333
334
struct ErrorBadParamsToAnnotateDoubleEndedContiguousContainer : ErrorBase {
335
const BufferedStackTrace *stack;
336
uptr storage_beg, storage_end, old_container_beg, old_container_end,
337
new_container_beg, new_container_end;
338
339
ErrorBadParamsToAnnotateDoubleEndedContiguousContainer() = default; // (*)
340
ErrorBadParamsToAnnotateDoubleEndedContiguousContainer(
341
u32 tid, BufferedStackTrace *stack_, uptr storage_beg_, uptr storage_end_,
342
uptr old_container_beg_, uptr old_container_end_, uptr new_container_beg_,
343
uptr new_container_end_)
344
: ErrorBase(tid, 10,
345
"bad-__sanitizer_annotate_double_ended_contiguous_container"),
346
stack(stack_),
347
storage_beg(storage_beg_),
348
storage_end(storage_end_),
349
old_container_beg(old_container_beg_),
350
old_container_end(old_container_end_),
351
new_container_beg(new_container_beg_),
352
new_container_end(new_container_end_) {}
353
void Print();
354
};
355
356
struct ErrorODRViolation : ErrorBase {
357
__asan_global global1, global2;
358
u32 stack_id1, stack_id2;
359
360
ErrorODRViolation() = default; // (*)
361
ErrorODRViolation(u32 tid, const __asan_global *g1, u32 stack_id1_,
362
const __asan_global *g2, u32 stack_id2_)
363
: ErrorBase(tid, 10, "odr-violation"),
364
global1(*g1),
365
global2(*g2),
366
stack_id1(stack_id1_),
367
stack_id2(stack_id2_) {}
368
void Print();
369
};
370
371
struct ErrorInvalidPointerPair : ErrorBase {
372
uptr pc, bp, sp;
373
AddressDescription addr1_description;
374
AddressDescription addr2_description;
375
376
ErrorInvalidPointerPair() = default; // (*)
377
ErrorInvalidPointerPair(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr p1,
378
uptr p2)
379
: ErrorBase(tid, 10, "invalid-pointer-pair"),
380
pc(pc_),
381
bp(bp_),
382
sp(sp_),
383
addr1_description(p1, 1, /*shouldLockThreadRegistry=*/false),
384
addr2_description(p2, 1, /*shouldLockThreadRegistry=*/false) {}
385
void Print();
386
};
387
388
struct ErrorGeneric : ErrorBase {
389
AddressDescription addr_description;
390
uptr pc, bp, sp;
391
uptr access_size;
392
const char *bug_descr;
393
bool is_write;
394
u8 shadow_val;
395
396
ErrorGeneric() = default; // (*)
397
ErrorGeneric(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr addr, bool is_write_,
398
uptr access_size_);
399
void Print();
400
};
401
402
// clang-format off
403
#define ASAN_FOR_EACH_ERROR_KIND(macro) \
404
macro(DeadlySignal) \
405
macro(DoubleFree) \
406
macro(NewDeleteTypeMismatch) \
407
macro(FreeNotMalloced) \
408
macro(AllocTypeMismatch) \
409
macro(MallocUsableSizeNotOwned) \
410
macro(SanitizerGetAllocatedSizeNotOwned) \
411
macro(CallocOverflow) \
412
macro(ReallocArrayOverflow) \
413
macro(PvallocOverflow) \
414
macro(InvalidAllocationAlignment) \
415
macro(InvalidAlignedAllocAlignment) \
416
macro(InvalidPosixMemalignAlignment) \
417
macro(AllocationSizeTooBig) \
418
macro(RssLimitExceeded) \
419
macro(OutOfMemory) \
420
macro(StringFunctionMemoryRangesOverlap) \
421
macro(StringFunctionSizeOverflow) \
422
macro(BadParamsToAnnotateContiguousContainer) \
423
macro(BadParamsToAnnotateDoubleEndedContiguousContainer) \
424
macro(ODRViolation) \
425
macro(InvalidPointerPair) \
426
macro(Generic)
427
// clang-format on
428
429
#define ASAN_DEFINE_ERROR_KIND(name) kErrorKind##name,
430
#define ASAN_ERROR_DESCRIPTION_MEMBER(name) Error##name name;
431
#define ASAN_ERROR_DESCRIPTION_CONSTRUCTOR(name) \
432
ErrorDescription(Error##name const &e) : kind(kErrorKind##name) { \
433
internal_memcpy(&name, &e, sizeof(name)); \
434
}
435
#define ASAN_ERROR_DESCRIPTION_PRINT(name) \
436
case kErrorKind##name: \
437
return name.Print();
438
439
enum ErrorKind {
440
kErrorKindInvalid = 0,
441
ASAN_FOR_EACH_ERROR_KIND(ASAN_DEFINE_ERROR_KIND)
442
};
443
444
struct ErrorDescription {
445
ErrorKind kind;
446
// We're using a tagged union because it allows us to have a trivially
447
// copiable type and use the same structures as the public interface.
448
//
449
// We can add a wrapper around it to make it "more c++-like", but that would
450
// add a lot of code and the benefit wouldn't be that big.
451
union {
452
ErrorBase Base;
453
ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_MEMBER)
454
};
455
456
ErrorDescription() { internal_memset(this, 0, sizeof(*this)); }
457
explicit ErrorDescription(LinkerInitialized) {}
458
ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_CONSTRUCTOR)
459
460
bool IsValid() { return kind != kErrorKindInvalid; }
461
void Print() {
462
switch (kind) {
463
ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_PRINT)
464
case kErrorKindInvalid:
465
CHECK(0);
466
}
467
CHECK(0);
468
}
469
};
470
471
#undef ASAN_FOR_EACH_ERROR_KIND
472
#undef ASAN_DEFINE_ERROR_KIND
473
#undef ASAN_ERROR_DESCRIPTION_MEMBER
474
#undef ASAN_ERROR_DESCRIPTION_CONSTRUCTOR
475
#undef ASAN_ERROR_DESCRIPTION_PRINT
476
477
} // namespace __asan
478
479
#endif // ASAN_ERRORS_H
480
481