1 | //===-- ubsan_handlers.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 | // Entry points to the runtime library for Clang's undefined behavior sanitizer. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | #ifndef UBSAN_HANDLERS_H |
13 | #define UBSAN_HANDLERS_H |
14 | |
15 | #include "ubsan_value.h" |
16 | |
17 | namespace __ubsan { |
18 | |
19 | struct TypeMismatchData { |
20 | SourceLocation Loc; |
21 | const TypeDescriptor &Type; |
22 | unsigned char LogAlignment; |
23 | unsigned char TypeCheckKind; |
24 | }; |
25 | |
26 | #define UNRECOVERABLE(checkname, ...) \ |
27 | extern "C" SANITIZER_INTERFACE_ATTRIBUTE NORETURN \ |
28 | void __ubsan_handle_ ## checkname( __VA_ARGS__ ); |
29 | |
30 | #define RECOVERABLE(checkname, ...) \ |
31 | extern "C" SANITIZER_INTERFACE_ATTRIBUTE \ |
32 | void __ubsan_handle_ ## checkname( __VA_ARGS__ ); \ |
33 | extern "C" SANITIZER_INTERFACE_ATTRIBUTE NORETURN \ |
34 | void __ubsan_handle_ ## checkname ## _abort( __VA_ARGS__ ); |
35 | |
36 | /// \brief Handle a runtime type check failure, caused by either a misaligned |
37 | /// pointer, a null pointer, or a pointer to insufficient storage for the |
38 | /// type. |
39 | RECOVERABLE(type_mismatch_v1, TypeMismatchData *Data, ValueHandle Pointer) |
40 | |
41 | struct AlignmentAssumptionData { |
42 | SourceLocation Loc; |
43 | SourceLocation AssumptionLoc; |
44 | const TypeDescriptor &Type; |
45 | }; |
46 | |
47 | /// \brief Handle a runtime alignment assumption check failure, |
48 | /// caused by a misaligned pointer. |
49 | RECOVERABLE(alignment_assumption, AlignmentAssumptionData *Data, |
50 | ValueHandle Pointer, ValueHandle Alignment, ValueHandle Offset) |
51 | |
52 | struct OverflowData { |
53 | SourceLocation Loc; |
54 | const TypeDescriptor &Type; |
55 | }; |
56 | |
57 | /// \brief Handle an integer addition overflow. |
58 | RECOVERABLE(add_overflow, OverflowData *Data, ValueHandle LHS, ValueHandle RHS) |
59 | |
60 | /// \brief Handle an integer subtraction overflow. |
61 | RECOVERABLE(sub_overflow, OverflowData *Data, ValueHandle LHS, ValueHandle RHS) |
62 | |
63 | /// \brief Handle an integer multiplication overflow. |
64 | RECOVERABLE(mul_overflow, OverflowData *Data, ValueHandle LHS, ValueHandle RHS) |
65 | |
66 | /// \brief Handle a signed integer overflow for a unary negate operator. |
67 | RECOVERABLE(negate_overflow, OverflowData *Data, ValueHandle OldVal) |
68 | |
69 | /// \brief Handle an INT_MIN/-1 overflow or division by zero. |
70 | RECOVERABLE(divrem_overflow, OverflowData *Data, |
71 | ValueHandle LHS, ValueHandle RHS) |
72 | |
73 | struct ShiftOutOfBoundsData { |
74 | SourceLocation Loc; |
75 | const TypeDescriptor &LHSType; |
76 | const TypeDescriptor &RHSType; |
77 | }; |
78 | |
79 | /// \brief Handle a shift where the RHS is out of bounds or a left shift where |
80 | /// the LHS is negative or overflows. |
81 | RECOVERABLE(shift_out_of_bounds, ShiftOutOfBoundsData *Data, |
82 | ValueHandle LHS, ValueHandle RHS) |
83 | |
84 | struct OutOfBoundsData { |
85 | SourceLocation Loc; |
86 | const TypeDescriptor &ArrayType; |
87 | const TypeDescriptor &IndexType; |
88 | }; |
89 | |
90 | /// \brief Handle an array index out of bounds error. |
91 | RECOVERABLE(out_of_bounds, OutOfBoundsData *Data, ValueHandle Index) |
92 | |
93 | /// \brief Handle an local object access out of bounds error. |
94 | RECOVERABLE(local_out_of_bounds) |
95 | |
96 | struct UnreachableData { |
97 | SourceLocation Loc; |
98 | }; |
99 | |
100 | /// \brief Handle a __builtin_unreachable which is reached. |
101 | UNRECOVERABLE(builtin_unreachable, UnreachableData *Data) |
102 | /// \brief Handle reaching the end of a value-returning function. |
103 | UNRECOVERABLE(missing_return, UnreachableData *Data) |
104 | |
105 | struct VLABoundData { |
106 | SourceLocation Loc; |
107 | const TypeDescriptor &Type; |
108 | }; |
109 | |
110 | /// \brief Handle a VLA with a non-positive bound. |
111 | RECOVERABLE(vla_bound_not_positive, VLABoundData *Data, ValueHandle Bound) |
112 | |
113 | // Keeping this around for binary compatibility with (sanitized) programs |
114 | // compiled with older compilers. |
115 | struct FloatCastOverflowData { |
116 | const TypeDescriptor &FromType; |
117 | const TypeDescriptor &ToType; |
118 | }; |
119 | |
120 | struct FloatCastOverflowDataV2 { |
121 | SourceLocation Loc; |
122 | const TypeDescriptor &FromType; |
123 | const TypeDescriptor &ToType; |
124 | }; |
125 | |
126 | /// Handle overflow in a conversion to or from a floating-point type. |
127 | /// void *Data is one of FloatCastOverflowData* or FloatCastOverflowDataV2* |
128 | RECOVERABLE(float_cast_overflow, void *Data, ValueHandle From) |
129 | |
130 | struct InvalidValueData { |
131 | SourceLocation Loc; |
132 | const TypeDescriptor &Type; |
133 | }; |
134 | |
135 | /// \brief Handle a load of an invalid value for the type. |
136 | RECOVERABLE(load_invalid_value, InvalidValueData *Data, ValueHandle Val) |
137 | |
138 | /// Known implicit conversion check kinds. |
139 | /// Keep in sync with the enum of the same name in CGExprScalar.cpp |
140 | enum ImplicitConversionCheckKind : unsigned char { |
141 | ICCK_IntegerTruncation = 0, // Legacy, was only used by clang 7. |
142 | ICCK_UnsignedIntegerTruncation = 1, |
143 | ICCK_SignedIntegerTruncation = 2, |
144 | ICCK_IntegerSignChange = 3, |
145 | ICCK_SignedIntegerTruncationOrSignChange = 4, |
146 | }; |
147 | |
148 | struct ImplicitConversionData { |
149 | SourceLocation Loc; |
150 | const TypeDescriptor &FromType; |
151 | const TypeDescriptor &ToType; |
152 | /* ImplicitConversionCheckKind */ unsigned char Kind; |
153 | unsigned int BitfieldBits; |
154 | }; |
155 | |
156 | /// \brief Implict conversion that changed the value. |
157 | RECOVERABLE(implicit_conversion, ImplicitConversionData *Data, ValueHandle Src, |
158 | ValueHandle Dst) |
159 | |
160 | /// Known builtin check kinds. |
161 | /// Keep in sync with the enum of the same name in CodeGenFunction.h |
162 | enum BuiltinCheckKind : unsigned char { |
163 | BCK_CTZPassedZero, |
164 | BCK_CLZPassedZero, |
165 | BCK_AssumePassedFalse, |
166 | }; |
167 | |
168 | struct InvalidBuiltinData { |
169 | SourceLocation Loc; |
170 | unsigned char Kind; |
171 | }; |
172 | |
173 | /// Handle a builtin called in an invalid way. |
174 | RECOVERABLE(invalid_builtin, InvalidBuiltinData *Data) |
175 | |
176 | struct InvalidObjCCast { |
177 | SourceLocation Loc; |
178 | const TypeDescriptor &ExpectedType; |
179 | }; |
180 | |
181 | /// Handle an invalid ObjC cast. |
182 | RECOVERABLE(invalid_objc_cast, InvalidObjCCast *Data, ValueHandle Pointer) |
183 | |
184 | struct NonNullReturnData { |
185 | SourceLocation AttrLoc; |
186 | }; |
187 | |
188 | /// \brief Handle returning null from function with the returns_nonnull |
189 | /// attribute, or a return type annotated with _Nonnull. |
190 | RECOVERABLE(nonnull_return_v1, NonNullReturnData *Data, SourceLocation *Loc) |
191 | RECOVERABLE(nullability_return_v1, NonNullReturnData *Data, SourceLocation *Loc) |
192 | |
193 | struct NonNullArgData { |
194 | SourceLocation Loc; |
195 | SourceLocation AttrLoc; |
196 | int ArgIndex; |
197 | }; |
198 | |
199 | /// \brief Handle passing null pointer to a function parameter with the nonnull |
200 | /// attribute, or a _Nonnull type annotation. |
201 | RECOVERABLE(nonnull_arg, NonNullArgData *Data) |
202 | RECOVERABLE(nullability_arg, NonNullArgData *Data) |
203 | |
204 | struct PointerOverflowData { |
205 | SourceLocation Loc; |
206 | }; |
207 | |
208 | RECOVERABLE(pointer_overflow, PointerOverflowData *Data, ValueHandle Base, |
209 | ValueHandle Result) |
210 | |
211 | /// \brief Known CFI check kinds. |
212 | /// Keep in sync with the enum of the same name in CodeGenFunction.h |
213 | enum CFITypeCheckKind : unsigned char { |
214 | CFITCK_VCall, |
215 | CFITCK_NVCall, |
216 | CFITCK_DerivedCast, |
217 | CFITCK_UnrelatedCast, |
218 | CFITCK_ICall, |
219 | CFITCK_NVMFCall, |
220 | CFITCK_VMFCall, |
221 | }; |
222 | |
223 | struct CFICheckFailData { |
224 | CFITypeCheckKind CheckKind; |
225 | SourceLocation Loc; |
226 | const TypeDescriptor &Type; |
227 | }; |
228 | |
229 | /// \brief Handle control flow integrity failures. |
230 | RECOVERABLE(cfi_check_fail, CFICheckFailData *Data, ValueHandle Function, |
231 | uptr VtableIsValid) |
232 | |
233 | struct ReportOptions; |
234 | |
235 | extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __ubsan_handle_cfi_bad_type( |
236 | CFICheckFailData *Data, ValueHandle Vtable, bool ValidVtable, |
237 | ReportOptions Opts); |
238 | |
239 | struct FunctionTypeMismatchData { |
240 | SourceLocation Loc; |
241 | const TypeDescriptor &Type; |
242 | }; |
243 | |
244 | extern "C" SANITIZER_INTERFACE_ATTRIBUTE void |
245 | __ubsan_handle_function_type_mismatch(FunctionTypeMismatchData *Data, |
246 | ValueHandle Val); |
247 | extern "C" SANITIZER_INTERFACE_ATTRIBUTE void |
248 | __ubsan_handle_function_type_mismatch_abort(FunctionTypeMismatchData *Data, |
249 | ValueHandle Val); |
250 | } |
251 | |
252 | #endif // UBSAN_HANDLERS_H |
253 | |