Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/compiler-rt/lib/scudo/standalone/report.cpp
35292 views
1
//===-- report.cpp ----------------------------------------------*- 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
#include "report.h"
10
11
#include "atomic_helpers.h"
12
#include "string_utils.h"
13
14
#include <stdarg.h>
15
16
namespace scudo {
17
18
class ScopedErrorReport {
19
public:
20
ScopedErrorReport() : Message() { Message.append("Scudo ERROR: "); }
21
void append(const char *Format, ...) {
22
va_list Args;
23
va_start(Args, Format);
24
Message.vappend(Format, Args);
25
va_end(Args);
26
}
27
NORETURN ~ScopedErrorReport() { reportRawError(Message.data()); }
28
29
private:
30
ScopedString Message;
31
};
32
33
inline void NORETURN trap() { __builtin_trap(); }
34
35
// This could potentially be called recursively if a CHECK fails in the reports.
36
void NORETURN reportCheckFailed(const char *File, int Line,
37
const char *Condition, u64 Value1, u64 Value2) {
38
static atomic_u32 NumberOfCalls;
39
if (atomic_fetch_add(&NumberOfCalls, 1, memory_order_relaxed) > 2) {
40
// TODO(kostyak): maybe sleep here?
41
trap();
42
}
43
ScopedErrorReport Report;
44
Report.append("CHECK failed @ %s:%d %s ((u64)op1=%llu, (u64)op2=%llu)\n",
45
File, Line, Condition, Value1, Value2);
46
}
47
48
// Generic string fatal error message.
49
void NORETURN reportError(const char *Message) {
50
ScopedErrorReport Report;
51
Report.append("%s\n", Message);
52
}
53
54
// Generic fatal error message without ScopedString.
55
void NORETURN reportRawError(const char *Message) {
56
outputRaw(Message);
57
setAbortMessage(Message);
58
die();
59
}
60
61
void NORETURN reportInvalidFlag(const char *FlagType, const char *Value) {
62
ScopedErrorReport Report;
63
Report.append("invalid value for %s option: '%s'\n", FlagType, Value);
64
}
65
66
// The checksum of a chunk header is invalid. This could be caused by an
67
// {over,under}write of the header, a pointer that is not an actual chunk.
68
void NORETURN reportHeaderCorruption(void *Ptr) {
69
ScopedErrorReport Report;
70
Report.append("corrupted chunk header at address %p\n", Ptr);
71
}
72
73
// The allocator was compiled with parameters that conflict with field size
74
// requirements.
75
void NORETURN reportSanityCheckError(const char *Field) {
76
ScopedErrorReport Report;
77
Report.append("maximum possible %s doesn't fit in header\n", Field);
78
}
79
80
// We enforce a maximum alignment, to keep fields smaller and generally prevent
81
// integer overflows, or unexpected corner cases.
82
void NORETURN reportAlignmentTooBig(uptr Alignment, uptr MaxAlignment) {
83
ScopedErrorReport Report;
84
Report.append("invalid allocation alignment: %zu exceeds maximum supported "
85
"alignment of %zu\n",
86
Alignment, MaxAlignment);
87
}
88
89
// See above, we also enforce a maximum size.
90
void NORETURN reportAllocationSizeTooBig(uptr UserSize, uptr TotalSize,
91
uptr MaxSize) {
92
ScopedErrorReport Report;
93
Report.append("requested allocation size %zu (%zu after adjustments) exceeds "
94
"maximum supported size of %zu\n",
95
UserSize, TotalSize, MaxSize);
96
}
97
98
void NORETURN reportOutOfBatchClass() {
99
ScopedErrorReport Report;
100
Report.append("BatchClass region is used up, can't hold any free block\n");
101
}
102
103
void NORETURN reportOutOfMemory(uptr RequestedSize) {
104
ScopedErrorReport Report;
105
Report.append("out of memory trying to allocate %zu bytes\n", RequestedSize);
106
}
107
108
static const char *stringifyAction(AllocatorAction Action) {
109
switch (Action) {
110
case AllocatorAction::Recycling:
111
return "recycling";
112
case AllocatorAction::Deallocating:
113
return "deallocating";
114
case AllocatorAction::Reallocating:
115
return "reallocating";
116
case AllocatorAction::Sizing:
117
return "sizing";
118
}
119
return "<invalid action>";
120
}
121
122
// The chunk is not in a state congruent with the operation we want to perform.
123
// This is usually the case with a double-free, a realloc of a freed pointer.
124
void NORETURN reportInvalidChunkState(AllocatorAction Action, void *Ptr) {
125
ScopedErrorReport Report;
126
Report.append("invalid chunk state when %s address %p\n",
127
stringifyAction(Action), Ptr);
128
}
129
130
void NORETURN reportMisalignedPointer(AllocatorAction Action, void *Ptr) {
131
ScopedErrorReport Report;
132
Report.append("misaligned pointer when %s address %p\n",
133
stringifyAction(Action), Ptr);
134
}
135
136
// The deallocation function used is at odds with the one used to allocate the
137
// chunk (eg: new[]/delete or malloc/delete, and so on).
138
void NORETURN reportDeallocTypeMismatch(AllocatorAction Action, void *Ptr,
139
u8 TypeA, u8 TypeB) {
140
ScopedErrorReport Report;
141
Report.append("allocation type mismatch when %s address %p (%d vs %d)\n",
142
stringifyAction(Action), Ptr, TypeA, TypeB);
143
}
144
145
// The size specified to the delete operator does not match the one that was
146
// passed to new when allocating the chunk.
147
void NORETURN reportDeleteSizeMismatch(void *Ptr, uptr Size,
148
uptr ExpectedSize) {
149
ScopedErrorReport Report;
150
Report.append(
151
"invalid sized delete when deallocating address %p (%zu vs %zu)\n", Ptr,
152
Size, ExpectedSize);
153
}
154
155
void NORETURN reportAlignmentNotPowerOfTwo(uptr Alignment) {
156
ScopedErrorReport Report;
157
Report.append(
158
"invalid allocation alignment: %zu, alignment must be a power of two\n",
159
Alignment);
160
}
161
162
void NORETURN reportCallocOverflow(uptr Count, uptr Size) {
163
ScopedErrorReport Report;
164
Report.append("calloc parameters overflow: count * size (%zu * %zu) cannot "
165
"be represented with type size_t\n",
166
Count, Size);
167
}
168
169
void NORETURN reportInvalidPosixMemalignAlignment(uptr Alignment) {
170
ScopedErrorReport Report;
171
Report.append(
172
"invalid alignment requested in posix_memalign: %zu, alignment must be a "
173
"power of two and a multiple of sizeof(void *) == %zu\n",
174
Alignment, sizeof(void *));
175
}
176
177
void NORETURN reportPvallocOverflow(uptr Size) {
178
ScopedErrorReport Report;
179
Report.append("pvalloc parameters overflow: size %zu rounded up to system "
180
"page size %zu cannot be represented in type size_t\n",
181
Size, getPageSizeCached());
182
}
183
184
void NORETURN reportInvalidAlignedAllocAlignment(uptr Alignment, uptr Size) {
185
ScopedErrorReport Report;
186
Report.append("invalid alignment requested in aligned_alloc: %zu, alignment "
187
"must be a power of two and the requested size %zu must be a "
188
"multiple of alignment\n",
189
Alignment, Size);
190
}
191
192
} // namespace scudo
193
194