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 | struct UnreachableData { |
94 | SourceLocation Loc; |
95 | }; |
96 | |
97 | /// \brief Handle a __builtin_unreachable which is reached. |
98 | UNRECOVERABLE(builtin_unreachable, UnreachableData *Data) |
99 | /// \brief Handle reaching the end of a value-returning function. |
100 | UNRECOVERABLE(missing_return, UnreachableData *Data) |
101 | |
102 | struct VLABoundData { |
103 | SourceLocation Loc; |
104 | const TypeDescriptor &Type; |
105 | }; |
106 | |
107 | /// \brief Handle a VLA with a non-positive bound. |
108 | RECOVERABLE(vla_bound_not_positive, VLABoundData *Data, ValueHandle Bound) |
109 | |
110 | // Keeping this around for binary compatibility with (sanitized) programs |
111 | // compiled with older compilers. |
112 | struct FloatCastOverflowData { |
113 | const TypeDescriptor &FromType; |
114 | const TypeDescriptor &ToType; |
115 | }; |
116 | |
117 | struct FloatCastOverflowDataV2 { |
118 | SourceLocation Loc; |
119 | const TypeDescriptor &FromType; |
120 | const TypeDescriptor &ToType; |
121 | }; |
122 | |
123 | /// Handle overflow in a conversion to or from a floating-point type. |
124 | /// void *Data is one of FloatCastOverflowData* or FloatCastOverflowDataV2* |
125 | RECOVERABLE(float_cast_overflow, void *Data, ValueHandle From) |
126 | |
127 | struct InvalidValueData { |
128 | SourceLocation Loc; |
129 | const TypeDescriptor &Type; |
130 | }; |
131 | |
132 | /// \brief Handle a load of an invalid value for the type. |
133 | RECOVERABLE(load_invalid_value, InvalidValueData *Data, ValueHandle Val) |
134 | |
135 | /// Known implicit conversion check kinds. |
136 | /// Keep in sync with the enum of the same name in CGExprScalar.cpp |
137 | enum ImplicitConversionCheckKind : unsigned char { |
138 | ICCK_IntegerTruncation = 0, // Legacy, was only used by clang 7. |
139 | ICCK_UnsignedIntegerTruncation = 1, |
140 | ICCK_SignedIntegerTruncation = 2, |
141 | ICCK_IntegerSignChange = 3, |
142 | ICCK_SignedIntegerTruncationOrSignChange = 4, |
143 | }; |
144 | |
145 | struct ImplicitConversionData { |
146 | SourceLocation Loc; |
147 | const TypeDescriptor &FromType; |
148 | const TypeDescriptor &ToType; |
149 | /* ImplicitConversionCheckKind */ unsigned char Kind; |
150 | unsigned int BitfieldBits; |
151 | }; |
152 | |
153 | /// \brief Implict conversion that changed the value. |
154 | RECOVERABLE(implicit_conversion, ImplicitConversionData *Data, ValueHandle Src, |
155 | ValueHandle Dst) |
156 | |
157 | /// Known builtin check kinds. |
158 | /// Keep in sync with the enum of the same name in CodeGenFunction.h |
159 | enum BuiltinCheckKind : unsigned char { |
160 | BCK_CTZPassedZero, |
161 | BCK_CLZPassedZero, |
162 | }; |
163 | |
164 | struct InvalidBuiltinData { |
165 | SourceLocation Loc; |
166 | unsigned char Kind; |
167 | }; |
168 | |
169 | /// Handle a builtin called in an invalid way. |
170 | RECOVERABLE(invalid_builtin, InvalidBuiltinData *Data) |
171 | |
172 | struct InvalidObjCCast { |
173 | SourceLocation Loc; |
174 | const TypeDescriptor &ExpectedType; |
175 | }; |
176 | |
177 | /// Handle an invalid ObjC cast. |
178 | RECOVERABLE(invalid_objc_cast, InvalidObjCCast *Data, ValueHandle Pointer) |
179 | |
180 | struct NonNullReturnData { |
181 | SourceLocation AttrLoc; |
182 | }; |
183 | |
184 | /// \brief Handle returning null from function with the returns_nonnull |
185 | /// attribute, or a return type annotated with _Nonnull. |
186 | RECOVERABLE(nonnull_return_v1, NonNullReturnData *Data, SourceLocation *Loc) |
187 | RECOVERABLE(nullability_return_v1, NonNullReturnData *Data, SourceLocation *Loc) |
188 | |
189 | struct NonNullArgData { |
190 | SourceLocation Loc; |
191 | SourceLocation AttrLoc; |
192 | int ArgIndex; |
193 | }; |
194 | |
195 | /// \brief Handle passing null pointer to a function parameter with the nonnull |
196 | /// attribute, or a _Nonnull type annotation. |
197 | RECOVERABLE(nonnull_arg, NonNullArgData *Data) |
198 | RECOVERABLE(nullability_arg, NonNullArgData *Data) |
199 | |
200 | struct PointerOverflowData { |
201 | SourceLocation Loc; |
202 | }; |
203 | |
204 | RECOVERABLE(pointer_overflow, PointerOverflowData *Data, ValueHandle Base, |
205 | ValueHandle Result) |
206 | |
207 | /// \brief Known CFI check kinds. |
208 | /// Keep in sync with the enum of the same name in CodeGenFunction.h |
209 | enum CFITypeCheckKind : unsigned char { |
210 | CFITCK_VCall, |
211 | CFITCK_NVCall, |
212 | CFITCK_DerivedCast, |
213 | CFITCK_UnrelatedCast, |
214 | CFITCK_ICall, |
215 | CFITCK_NVMFCall, |
216 | CFITCK_VMFCall, |
217 | }; |
218 | |
219 | struct CFICheckFailData { |
220 | CFITypeCheckKind CheckKind; |
221 | SourceLocation Loc; |
222 | const TypeDescriptor &Type; |
223 | }; |
224 | |
225 | /// \brief Handle control flow integrity failures. |
226 | RECOVERABLE(cfi_check_fail, CFICheckFailData *Data, ValueHandle Function, |
227 | uptr VtableIsValid) |
228 | |
229 | struct ReportOptions; |
230 | |
231 | extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __ubsan_handle_cfi_bad_type( |
232 | CFICheckFailData *Data, ValueHandle Vtable, bool ValidVtable, |
233 | ReportOptions Opts); |
234 | |
235 | struct FunctionTypeMismatchData { |
236 | SourceLocation Loc; |
237 | const TypeDescriptor &Type; |
238 | }; |
239 | |
240 | extern "C" SANITIZER_INTERFACE_ATTRIBUTE void |
241 | __ubsan_handle_function_type_mismatch(FunctionTypeMismatchData *Data, |
242 | ValueHandle Val); |
243 | extern "C" SANITIZER_INTERFACE_ATTRIBUTE void |
244 | __ubsan_handle_function_type_mismatch_abort(FunctionTypeMismatchData *Data, |
245 | ValueHandle Val); |
246 | } |
247 | |
248 | #endif // UBSAN_HANDLERS_H |
249 | |