ubsan.c revision 1.5.2.3 1 1.5.2.3 martin /* $NetBSD: ubsan.c,v 1.5.2.3 2020/04/13 07:45:08 martin Exp $ */
2 1.5.2.2 christos
3 1.5.2.2 christos /*-
4 1.5.2.2 christos * Copyright (c) 2018 The NetBSD Foundation, Inc.
5 1.5.2.2 christos * All rights reserved.
6 1.5.2.2 christos *
7 1.5.2.2 christos * Redistribution and use in source and binary forms, with or without
8 1.5.2.2 christos * modification, are permitted provided that the following conditions
9 1.5.2.2 christos * are met:
10 1.5.2.2 christos * 1. Redistributions of source code must retain the above copyright
11 1.5.2.2 christos * notice, this list of conditions and the following disclaimer.
12 1.5.2.2 christos * 2. Redistributions in binary form must reproduce the above copyright
13 1.5.2.2 christos * notice, this list of conditions and the following disclaimer in the
14 1.5.2.2 christos * documentation and/or other materials provided with the distribution.
15 1.5.2.2 christos *
16 1.5.2.2 christos * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 1.5.2.2 christos * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 1.5.2.2 christos * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 1.5.2.2 christos * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 1.5.2.2 christos * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 1.5.2.2 christos * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 1.5.2.2 christos * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 1.5.2.2 christos * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 1.5.2.2 christos * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 1.5.2.2 christos * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 1.5.2.2 christos * POSSIBILITY OF SUCH DAMAGE.
27 1.5.2.2 christos */
28 1.5.2.2 christos
29 1.5.2.2 christos
30 1.5.2.2 christos /*
31 1.5.2.2 christos * The micro UBSan implementation for the userland (uUBSan) and kernel (kUBSan).
32 1.5.2.2 christos * The uBSSan versions is suitable for inclusion into libc or used standalone
33 1.5.2.2 christos * with ATF tests.
34 1.5.2.2 christos *
35 1.5.2.2 christos * This file due to long symbol names generated by a compiler during the
36 1.5.2.2 christos * instrumentation process does not follow the KNF style with 80-column limit.
37 1.5.2.2 christos */
38 1.5.2.2 christos
39 1.5.2.2 christos #include <sys/cdefs.h>
40 1.5.2.2 christos #if defined(_KERNEL)
41 1.5.2.3 martin __KERNEL_RCSID(0, "$NetBSD: ubsan.c,v 1.5.2.3 2020/04/13 07:45:08 martin Exp $");
42 1.5.2.2 christos #else
43 1.5.2.3 martin __RCSID("$NetBSD: ubsan.c,v 1.5.2.3 2020/04/13 07:45:08 martin Exp $");
44 1.5.2.2 christos #endif
45 1.5.2.2 christos
46 1.5.2.2 christos #if defined(_KERNEL)
47 1.5.2.2 christos #include <sys/param.h>
48 1.5.2.2 christos #include <sys/types.h>
49 1.5.2.2 christos #include <sys/stdarg.h>
50 1.5.2.2 christos #define ASSERT(x) KASSERT(x)
51 1.5.2.2 christos #else
52 1.5.2.2 christos #if defined(_LIBC)
53 1.5.2.2 christos #include "namespace.h"
54 1.5.2.2 christos #endif
55 1.5.2.2 christos #include <sys/param.h>
56 1.5.2.2 christos #include <assert.h>
57 1.5.2.2 christos #include <inttypes.h>
58 1.5.2.2 christos #include <math.h>
59 1.5.2.2 christos #include <signal.h>
60 1.5.2.2 christos #include <stdarg.h>
61 1.5.2.2 christos #include <stdbool.h>
62 1.5.2.2 christos #include <stdint.h>
63 1.5.2.2 christos #include <stdio.h>
64 1.5.2.2 christos #include <stdlib.h>
65 1.5.2.2 christos #include <string.h>
66 1.5.2.2 christos #include <syslog.h>
67 1.5.2.2 christos #include <unistd.h>
68 1.5.2.2 christos #if defined(_LIBC)
69 1.5.2.2 christos #include "extern.h"
70 1.5.2.2 christos #define ubsan_vsyslog vsyslog_ss
71 1.5.2.2 christos #define ASSERT(x) _DIAGASSERT(x)
72 1.5.2.2 christos #else
73 1.5.2.2 christos #define ubsan_vsyslog vsyslog_r
74 1.5.2.2 christos #define ASSERT(x) assert(x)
75 1.5.2.2 christos #endif
76 1.5.2.2 christos /* These macros are available in _KERNEL only */
77 1.5.2.2 christos #define SET(t, f) ((t) |= (f))
78 1.5.2.2 christos #define ISSET(t, f) ((t) & (f))
79 1.5.2.2 christos #define CLR(t, f) ((t) &= ~(f))
80 1.5.2.2 christos #endif
81 1.5.2.2 christos
82 1.5.2.3 martin #ifdef UBSAN_ALWAYS_FATAL
83 1.5.2.3 martin static const bool alwaysFatal = true;
84 1.5.2.3 martin #else
85 1.5.2.3 martin static const bool alwaysFatal = false;
86 1.5.2.3 martin #endif
87 1.5.2.3 martin
88 1.5.2.2 christos #define REINTERPRET_CAST(__dt, __st) ((__dt)(__st))
89 1.5.2.2 christos #define STATIC_CAST(__dt, __st) ((__dt)(__st))
90 1.5.2.2 christos
91 1.5.2.2 christos #define ACK_REPORTED __BIT(31)
92 1.5.2.2 christos
93 1.5.2.2 christos #define MUL_STRING "*"
94 1.5.2.2 christos #define PLUS_STRING "+"
95 1.5.2.2 christos #define MINUS_STRING "-"
96 1.5.2.2 christos #define DIVREM_STRING "divrem"
97 1.5.2.2 christos
98 1.5.2.2 christos #define CFI_VCALL 0
99 1.5.2.2 christos #define CFI_NVCALL 1
100 1.5.2.2 christos #define CFI_DERIVEDCAST 2
101 1.5.2.2 christos #define CFI_UNRELATEDCAST 3
102 1.5.2.2 christos #define CFI_ICALL 4
103 1.5.2.2 christos #define CFI_NVMFCALL 5
104 1.5.2.2 christos #define CFI_VMFCALL 6
105 1.5.2.2 christos
106 1.5.2.2 christos #define NUMBER_MAXLEN 128
107 1.5.2.2 christos #define LOCATION_MAXLEN (PATH_MAX + 32 /* ':LINE:COLUMN' */)
108 1.5.2.2 christos
109 1.5.2.2 christos #define WIDTH_8 8
110 1.5.2.2 christos #define WIDTH_16 16
111 1.5.2.2 christos #define WIDTH_32 32
112 1.5.2.2 christos #define WIDTH_64 64
113 1.5.2.2 christos #define WIDTH_80 80
114 1.5.2.2 christos #define WIDTH_96 96
115 1.5.2.2 christos #define WIDTH_128 128
116 1.5.2.2 christos
117 1.5.2.2 christos #define NUMBER_SIGNED_BIT 1U
118 1.5.2.2 christos
119 1.5.2.2 christos #ifdef __SIZEOF_INT128__
120 1.5.2.2 christos typedef __int128 longest;
121 1.5.2.2 christos typedef unsigned __int128 ulongest;
122 1.5.2.2 christos #else
123 1.5.2.2 christos typedef int64_t longest;
124 1.5.2.2 christos typedef uint64_t ulongest;
125 1.5.2.2 christos #endif
126 1.5.2.2 christos
127 1.5.2.2 christos #ifndef _KERNEL
128 1.5.2.2 christos static int ubsan_flags = -1;
129 1.5.2.2 christos #define UBSAN_ABORT __BIT(0)
130 1.5.2.2 christos #define UBSAN_STDOUT __BIT(1)
131 1.5.2.2 christos #define UBSAN_STDERR __BIT(2)
132 1.5.2.2 christos #define UBSAN_SYSLOG __BIT(3)
133 1.5.2.2 christos #endif
134 1.5.2.2 christos
135 1.5.2.2 christos /* Undefined Behavior specific defines and structures */
136 1.5.2.2 christos
137 1.5.2.2 christos #define KIND_INTEGER 0
138 1.5.2.2 christos #define KIND_FLOAT 1
139 1.5.2.2 christos #define KIND_UNKNOWN UINT16_MAX
140 1.5.2.2 christos
141 1.5.2.2 christos struct CSourceLocation {
142 1.5.2.2 christos char *mFilename;
143 1.5.2.2 christos uint32_t mLine;
144 1.5.2.2 christos uint32_t mColumn;
145 1.5.2.2 christos };
146 1.5.2.2 christos
147 1.5.2.2 christos struct CTypeDescriptor {
148 1.5.2.2 christos uint16_t mTypeKind;
149 1.5.2.2 christos uint16_t mTypeInfo;
150 1.5.2.2 christos uint8_t mTypeName[1];
151 1.5.2.2 christos };
152 1.5.2.2 christos
153 1.5.2.2 christos struct COverflowData {
154 1.5.2.2 christos struct CSourceLocation mLocation;
155 1.5.2.2 christos struct CTypeDescriptor *mType;
156 1.5.2.2 christos };
157 1.5.2.2 christos
158 1.5.2.2 christos struct CUnreachableData {
159 1.5.2.2 christos struct CSourceLocation mLocation;
160 1.5.2.2 christos };
161 1.5.2.2 christos
162 1.5.2.2 christos struct CCFICheckFailData {
163 1.5.2.2 christos uint8_t mCheckKind;
164 1.5.2.2 christos struct CSourceLocation mLocation;
165 1.5.2.2 christos struct CTypeDescriptor *mType;
166 1.5.2.2 christos };
167 1.5.2.2 christos
168 1.5.2.2 christos struct CDynamicTypeCacheMissData {
169 1.5.2.2 christos struct CSourceLocation mLocation;
170 1.5.2.2 christos struct CTypeDescriptor *mType;
171 1.5.2.2 christos void *mTypeInfo;
172 1.5.2.2 christos uint8_t mTypeCheckKind;
173 1.5.2.2 christos };
174 1.5.2.2 christos
175 1.5.2.2 christos struct CFunctionTypeMismatchData {
176 1.5.2.2 christos struct CSourceLocation mLocation;
177 1.5.2.2 christos struct CTypeDescriptor *mType;
178 1.5.2.2 christos };
179 1.5.2.2 christos
180 1.5.2.2 christos struct CInvalidBuiltinData {
181 1.5.2.2 christos struct CSourceLocation mLocation;
182 1.5.2.2 christos uint8_t mKind;
183 1.5.2.2 christos };
184 1.5.2.2 christos
185 1.5.2.2 christos struct CInvalidValueData {
186 1.5.2.2 christos struct CSourceLocation mLocation;
187 1.5.2.2 christos struct CTypeDescriptor *mType;
188 1.5.2.2 christos };
189 1.5.2.2 christos
190 1.5.2.2 christos struct CNonNullArgData {
191 1.5.2.2 christos struct CSourceLocation mLocation;
192 1.5.2.2 christos struct CSourceLocation mAttributeLocation;
193 1.5.2.2 christos int mArgIndex;
194 1.5.2.2 christos };
195 1.5.2.2 christos
196 1.5.2.2 christos struct CNonNullReturnData {
197 1.5.2.2 christos struct CSourceLocation mAttributeLocation;
198 1.5.2.2 christos };
199 1.5.2.2 christos
200 1.5.2.2 christos struct COutOfBoundsData {
201 1.5.2.2 christos struct CSourceLocation mLocation;
202 1.5.2.2 christos struct CTypeDescriptor *mArrayType;
203 1.5.2.2 christos struct CTypeDescriptor *mIndexType;
204 1.5.2.2 christos };
205 1.5.2.2 christos
206 1.5.2.2 christos struct CPointerOverflowData {
207 1.5.2.2 christos struct CSourceLocation mLocation;
208 1.5.2.2 christos };
209 1.5.2.2 christos
210 1.5.2.2 christos struct CShiftOutOfBoundsData {
211 1.5.2.2 christos struct CSourceLocation mLocation;
212 1.5.2.2 christos struct CTypeDescriptor *mLHSType;
213 1.5.2.2 christos struct CTypeDescriptor *mRHSType;
214 1.5.2.2 christos };
215 1.5.2.2 christos
216 1.5.2.2 christos struct CTypeMismatchData {
217 1.5.2.2 christos struct CSourceLocation mLocation;
218 1.5.2.2 christos struct CTypeDescriptor *mType;
219 1.5.2.2 christos unsigned long mLogAlignment;
220 1.5.2.2 christos uint8_t mTypeCheckKind;
221 1.5.2.2 christos };
222 1.5.2.2 christos
223 1.5.2.2 christos struct CTypeMismatchData_v1 {
224 1.5.2.2 christos struct CSourceLocation mLocation;
225 1.5.2.2 christos struct CTypeDescriptor *mType;
226 1.5.2.2 christos uint8_t mLogAlignment;
227 1.5.2.2 christos uint8_t mTypeCheckKind;
228 1.5.2.2 christos };
229 1.5.2.2 christos
230 1.5.2.2 christos struct CVLABoundData {
231 1.5.2.2 christos struct CSourceLocation mLocation;
232 1.5.2.2 christos struct CTypeDescriptor *mType;
233 1.5.2.2 christos };
234 1.5.2.2 christos
235 1.5.2.2 christos struct CFloatCastOverflowData {
236 1.5.2.2 christos struct CSourceLocation mLocation; /* This field exists in this struct since 2015 August 11th */
237 1.5.2.2 christos struct CTypeDescriptor *mFromType;
238 1.5.2.2 christos struct CTypeDescriptor *mToType;
239 1.5.2.2 christos };
240 1.5.2.2 christos
241 1.5.2.3 martin struct CImplicitConversionData {
242 1.5.2.3 martin struct CSourceLocation mLocation;
243 1.5.2.3 martin struct CTypeDescriptor *mFromType;
244 1.5.2.3 martin struct CTypeDescriptor *mToType;
245 1.5.2.3 martin uint8_t mKind;
246 1.5.2.3 martin };
247 1.5.2.3 martin
248 1.5.2.3 martin struct CAlignmentAssumptionData {
249 1.5.2.3 martin struct CSourceLocation mLocation;
250 1.5.2.3 martin struct CSourceLocation mAssumptionLocation;
251 1.5.2.3 martin struct CTypeDescriptor *mType;
252 1.5.2.3 martin };
253 1.5.2.3 martin
254 1.5.2.2 christos /* Local utility functions */
255 1.5.2.2 christos static void Report(bool isFatal, const char *pFormat, ...) __printflike(2, 3);
256 1.5.2.2 christos static bool isAlreadyReported(struct CSourceLocation *pLocation);
257 1.5.2.2 christos static size_t zDeserializeTypeWidth(struct CTypeDescriptor *pType);
258 1.5.2.2 christos static void DeserializeLocation(char *pBuffer, size_t zBUfferLength, struct CSourceLocation *pLocation);
259 1.5.2.2 christos #ifdef __SIZEOF_INT128__
260 1.5.2.2 christos static void DeserializeUINT128(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, __uint128_t U128);
261 1.5.2.2 christos #endif
262 1.5.2.2 christos static void DeserializeNumberSigned(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, longest L);
263 1.5.2.2 christos static void DeserializeNumberUnsigned(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, ulongest L);
264 1.5.2.2 christos #ifndef _KERNEL
265 1.5.2.2 christos static void DeserializeFloatOverPointer(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long *pNumber);
266 1.5.2.2 christos static void DeserializeFloatInlined(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber);
267 1.5.2.2 christos #endif
268 1.5.2.2 christos static longest llliGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber);
269 1.5.2.2 christos static ulongest llluGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber);
270 1.5.2.2 christos #ifndef _KERNEL
271 1.5.2.2 christos static void DeserializeNumberFloat(char *szLocation, char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber);
272 1.5.2.2 christos #endif
273 1.5.2.2 christos static void DeserializeNumber(char *szLocation, char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber);
274 1.5.2.2 christos static const char *DeserializeTypeCheckKind(uint8_t hhuTypeCheckKind);
275 1.5.2.2 christos static const char *DeserializeBuiltinCheckKind(uint8_t hhuBuiltinCheckKind);
276 1.5.2.2 christos static const char *DeserializeCFICheckKind(uint8_t hhuCFICheckKind);
277 1.5.2.3 martin static const char *DeserializeImplicitConversionCheckKind(uint8_t hhuImplicitConversionCheckKind);
278 1.5.2.2 christos static bool isNegativeNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber);
279 1.5.2.2 christos static bool isShiftExponentTooLarge(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber, size_t zWidth);
280 1.5.2.2 christos
281 1.5.2.2 christos /* Unused in this implementation, emitted by the C++ check dynamic type cast. */
282 1.5.2.2 christos intptr_t __ubsan_vptr_type_cache[128];
283 1.5.2.2 christos
284 1.5.2.2 christos /* Public symbols used in the instrumentation of the code generation part */
285 1.5.2.2 christos void __ubsan_handle_add_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
286 1.5.2.2 christos void __ubsan_handle_add_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
287 1.5.2.3 martin void __ubsan_handle_alignment_assumption(struct CAlignmentAssumptionData *pData, unsigned long ulPointer, unsigned long ulAlignment, unsigned long ulOffset);
288 1.5.2.3 martin void __ubsan_handle_alignment_assumption_abort(struct CAlignmentAssumptionData *pData, unsigned long ulPointer, unsigned long ulAlignment, unsigned long ulOffset);
289 1.5.2.2 christos void __ubsan_handle_builtin_unreachable(struct CUnreachableData *pData);
290 1.5.2.2 christos void __ubsan_handle_cfi_bad_type(struct CCFICheckFailData *pData, unsigned long ulVtable, bool bValidVtable, bool FromUnrecoverableHandler, unsigned long ProgramCounter, unsigned long FramePointer);
291 1.5.2.2 christos void __ubsan_handle_cfi_check_fail(struct CCFICheckFailData *pData, unsigned long ulValue, unsigned long ulValidVtable);
292 1.5.2.2 christos void __ubsan_handle_cfi_check_fail_abort(struct CCFICheckFailData *pData, unsigned long ulValue, unsigned long ulValidVtable);
293 1.5.2.2 christos void __ubsan_handle_divrem_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
294 1.5.2.2 christos void __ubsan_handle_divrem_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
295 1.5.2.2 christos void __ubsan_handle_dynamic_type_cache_miss(struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash);
296 1.5.2.2 christos void __ubsan_handle_dynamic_type_cache_miss_abort(struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash);
297 1.5.2.2 christos void __ubsan_handle_float_cast_overflow(struct CFloatCastOverflowData *pData, unsigned long ulFrom);
298 1.5.2.2 christos void __ubsan_handle_float_cast_overflow_abort(struct CFloatCastOverflowData *pData, unsigned long ulFrom);
299 1.5.2.2 christos void __ubsan_handle_function_type_mismatch(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction);
300 1.5.2.2 christos void __ubsan_handle_function_type_mismatch_abort(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction);
301 1.5.2.3 martin void __ubsan_handle_function_type_mismatch_v1(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction, unsigned long ulCalleeRTTI, unsigned long ulFnRTTI);
302 1.5.2.3 martin void __ubsan_handle_function_type_mismatch_v1_abort(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction, unsigned long ulCalleeRTTI, unsigned long ulFnRTTI);
303 1.5.2.2 christos void __ubsan_handle_invalid_builtin(struct CInvalidBuiltinData *pData);
304 1.5.2.2 christos void __ubsan_handle_invalid_builtin_abort(struct CInvalidBuiltinData *pData);
305 1.5.2.2 christos void __ubsan_handle_load_invalid_value(struct CInvalidValueData *pData, unsigned long ulVal);
306 1.5.2.2 christos void __ubsan_handle_load_invalid_value_abort(struct CInvalidValueData *pData, unsigned long ulVal);
307 1.5.2.2 christos void __ubsan_handle_missing_return(struct CUnreachableData *pData);
308 1.5.2.2 christos void __ubsan_handle_mul_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
309 1.5.2.2 christos void __ubsan_handle_mul_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
310 1.5.2.2 christos void __ubsan_handle_negate_overflow(struct COverflowData *pData, unsigned long ulOldVal);
311 1.5.2.2 christos void __ubsan_handle_negate_overflow_abort(struct COverflowData *pData, unsigned long ulOldVal);
312 1.5.2.2 christos void __ubsan_handle_nonnull_arg(struct CNonNullArgData *pData);
313 1.5.2.2 christos void __ubsan_handle_nonnull_arg_abort(struct CNonNullArgData *pData);
314 1.5.2.2 christos void __ubsan_handle_nonnull_return_v1(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer);
315 1.5.2.2 christos void __ubsan_handle_nonnull_return_v1_abort(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer);
316 1.5.2.2 christos void __ubsan_handle_nullability_arg(struct CNonNullArgData *pData);
317 1.5.2.2 christos void __ubsan_handle_nullability_arg_abort(struct CNonNullArgData *pData);
318 1.5.2.2 christos void __ubsan_handle_nullability_return_v1(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer);
319 1.5.2.2 christos void __ubsan_handle_nullability_return_v1_abort(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer);
320 1.5.2.2 christos void __ubsan_handle_out_of_bounds(struct COutOfBoundsData *pData, unsigned long ulIndex);
321 1.5.2.2 christos void __ubsan_handle_out_of_bounds_abort(struct COutOfBoundsData *pData, unsigned long ulIndex);
322 1.5.2.2 christos void __ubsan_handle_pointer_overflow(struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult);
323 1.5.2.2 christos void __ubsan_handle_pointer_overflow_abort(struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult);
324 1.5.2.2 christos void __ubsan_handle_shift_out_of_bounds(struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS);
325 1.5.2.2 christos void __ubsan_handle_shift_out_of_bounds_abort(struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS);
326 1.5.2.2 christos void __ubsan_handle_sub_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
327 1.5.2.2 christos void __ubsan_handle_sub_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
328 1.5.2.2 christos void __ubsan_handle_type_mismatch(struct CTypeMismatchData *pData, unsigned long ulPointer);
329 1.5.2.2 christos void __ubsan_handle_type_mismatch_abort(struct CTypeMismatchData *pData, unsigned long ulPointer);
330 1.5.2.2 christos void __ubsan_handle_type_mismatch_v1(struct CTypeMismatchData_v1 *pData, unsigned long ulPointer);
331 1.5.2.2 christos void __ubsan_handle_type_mismatch_v1_abort(struct CTypeMismatchData_v1 *pData, unsigned long ulPointer);
332 1.5.2.2 christos void __ubsan_handle_vla_bound_not_positive(struct CVLABoundData *pData, unsigned long ulBound);
333 1.5.2.2 christos void __ubsan_handle_vla_bound_not_positive_abort(struct CVLABoundData *pData, unsigned long ulBound);
334 1.5.2.3 martin void __ubsan_handle_implicit_conversion(struct CImplicitConversionData *pData, unsigned long ulFrom, unsigned long ulTo);
335 1.5.2.3 martin void __ubsan_handle_implicit_conversion_abort(struct CImplicitConversionData *pData, unsigned long ulFrom, unsigned long ulTo);
336 1.5.2.2 christos void __ubsan_get_current_report_data(const char **ppOutIssueKind, const char **ppOutMessage, const char **ppOutFilename, uint32_t *pOutLine, uint32_t *pOutCol, char **ppOutMemoryAddr);
337 1.5.2.2 christos
338 1.5.2.2 christos static void HandleOverflow(bool isFatal, struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS, const char *szOperation);
339 1.5.2.2 christos static void HandleNegateOverflow(bool isFatal, struct COverflowData *pData, unsigned long ulOldValue);
340 1.5.2.2 christos static void HandleBuiltinUnreachable(bool isFatal, struct CUnreachableData *pData);
341 1.5.2.2 christos static void HandleTypeMismatch(bool isFatal, struct CSourceLocation *mLocation, struct CTypeDescriptor *mType, unsigned long mLogAlignment, uint8_t mTypeCheckKind, unsigned long ulPointer);
342 1.5.2.2 christos static void HandleVlaBoundNotPositive(bool isFatal, struct CVLABoundData *pData, unsigned long ulBound);
343 1.5.2.2 christos static void HandleOutOfBounds(bool isFatal, struct COutOfBoundsData *pData, unsigned long ulIndex);
344 1.5.2.2 christos static void HandleShiftOutOfBounds(bool isFatal, struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS);
345 1.5.2.2 christos static void HandleLoadInvalidValue(bool isFatal, struct CInvalidValueData *pData, unsigned long ulValue);
346 1.5.2.2 christos static void HandleInvalidBuiltin(bool isFatal, struct CInvalidBuiltinData *pData);
347 1.5.2.2 christos static void HandleFunctionTypeMismatch(bool isFatal, struct CFunctionTypeMismatchData *pData, unsigned long ulFunction);
348 1.5.2.2 christos static void HandleCFIBadType(bool isFatal, struct CCFICheckFailData *pData, unsigned long ulVtable, bool *bValidVtable, bool *FromUnrecoverableHandler, unsigned long *ProgramCounter, unsigned long *FramePointer);
349 1.5.2.2 christos static void HandleDynamicTypeCacheMiss(bool isFatal, struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash);
350 1.5.2.2 christos static void HandleFloatCastOverflow(bool isFatal, struct CFloatCastOverflowData *pData, unsigned long ulFrom);
351 1.5.2.2 christos static void HandleMissingReturn(bool isFatal, struct CUnreachableData *pData);
352 1.5.2.2 christos static void HandleNonnullArg(bool isFatal, struct CNonNullArgData *pData);
353 1.5.2.2 christos static void HandleNonnullReturn(bool isFatal, struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer);
354 1.5.2.2 christos static void HandlePointerOverflow(bool isFatal, struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult);
355 1.5.2.3 martin static void HandleAlignmentAssumption(bool isFatal, struct CAlignmentAssumptionData *pData, unsigned long ulPointer, unsigned long ulAlignment, unsigned long ulOffset);
356 1.5.2.2 christos
357 1.5.2.2 christos static void
358 1.5.2.2 christos HandleOverflow(bool isFatal, struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS, const char *szOperation)
359 1.5.2.2 christos {
360 1.5.2.2 christos char szLocation[LOCATION_MAXLEN];
361 1.5.2.2 christos char szLHS[NUMBER_MAXLEN];
362 1.5.2.2 christos char szRHS[NUMBER_MAXLEN];
363 1.5.2.2 christos
364 1.5.2.2 christos ASSERT(pData);
365 1.5.2.2 christos
366 1.5.2.2 christos if (isAlreadyReported(&pData->mLocation))
367 1.5.2.2 christos return;
368 1.5.2.2 christos
369 1.5.2.2 christos DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
370 1.5.2.2 christos DeserializeNumber(szLocation, szLHS, NUMBER_MAXLEN, pData->mType, ulLHS);
371 1.5.2.2 christos DeserializeNumber(szLocation, szRHS, NUMBER_MAXLEN, pData->mType, ulRHS);
372 1.5.2.2 christos
373 1.5.2.2 christos Report(isFatal, "UBSan: Undefined Behavior in %s, %s integer overflow: %s %s %s cannot be represented in type %s\n",
374 1.5.2.2 christos szLocation, ISSET(pData->mType->mTypeInfo, NUMBER_SIGNED_BIT) ? "signed" : "unsigned", szLHS, szOperation, szRHS, pData->mType->mTypeName);
375 1.5.2.2 christos }
376 1.5.2.2 christos
377 1.5.2.2 christos static void
378 1.5.2.2 christos HandleNegateOverflow(bool isFatal, struct COverflowData *pData, unsigned long ulOldValue)
379 1.5.2.2 christos {
380 1.5.2.2 christos char szLocation[LOCATION_MAXLEN];
381 1.5.2.2 christos char szOldValue[NUMBER_MAXLEN];
382 1.5.2.2 christos
383 1.5.2.2 christos ASSERT(pData);
384 1.5.2.2 christos
385 1.5.2.2 christos if (isAlreadyReported(&pData->mLocation))
386 1.5.2.2 christos return;
387 1.5.2.2 christos
388 1.5.2.2 christos DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
389 1.5.2.2 christos DeserializeNumber(szLocation, szOldValue, NUMBER_MAXLEN, pData->mType, ulOldValue);
390 1.5.2.2 christos
391 1.5.2.2 christos Report(isFatal, "UBSan: Undefined Behavior in %s, negation of %s cannot be represented in type %s\n",
392 1.5.2.2 christos szLocation, szOldValue, pData->mType->mTypeName);
393 1.5.2.2 christos }
394 1.5.2.2 christos
395 1.5.2.2 christos static void
396 1.5.2.2 christos HandleBuiltinUnreachable(bool isFatal, struct CUnreachableData *pData)
397 1.5.2.2 christos {
398 1.5.2.2 christos char szLocation[LOCATION_MAXLEN];
399 1.5.2.2 christos
400 1.5.2.2 christos ASSERT(pData);
401 1.5.2.2 christos
402 1.5.2.2 christos if (isAlreadyReported(&pData->mLocation))
403 1.5.2.2 christos return;
404 1.5.2.2 christos
405 1.5.2.2 christos DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
406 1.5.2.2 christos
407 1.5.2.2 christos Report(isFatal, "UBSan: Undefined Behavior in %s, calling __builtin_unreachable()\n",
408 1.5.2.2 christos szLocation);
409 1.5.2.2 christos }
410 1.5.2.2 christos
411 1.5.2.2 christos static void
412 1.5.2.2 christos HandleTypeMismatch(bool isFatal, struct CSourceLocation *mLocation, struct CTypeDescriptor *mType, unsigned long mLogAlignment, uint8_t mTypeCheckKind, unsigned long ulPointer)
413 1.5.2.2 christos {
414 1.5.2.2 christos char szLocation[LOCATION_MAXLEN];
415 1.5.2.2 christos
416 1.5.2.2 christos ASSERT(mLocation);
417 1.5.2.2 christos ASSERT(mType);
418 1.5.2.2 christos
419 1.5.2.2 christos if (isAlreadyReported(mLocation))
420 1.5.2.2 christos return;
421 1.5.2.2 christos
422 1.5.2.2 christos DeserializeLocation(szLocation, LOCATION_MAXLEN, mLocation);
423 1.5.2.2 christos
424 1.5.2.2 christos if (ulPointer == 0) {
425 1.5.2.2 christos Report(isFatal, "UBSan: Undefined Behavior in %s, %s null pointer of type %s\n",
426 1.5.2.2 christos szLocation, DeserializeTypeCheckKind(mTypeCheckKind), mType->mTypeName);
427 1.5.2.2 christos } else if ((mLogAlignment - 1) & ulPointer) {
428 1.5.2.2 christos Report(isFatal, "UBSan: Undefined Behavior in %s, %s misaligned address %p for type %s which requires %ld byte alignment\n",
429 1.5.2.2 christos szLocation, DeserializeTypeCheckKind(mTypeCheckKind), REINTERPRET_CAST(void *, ulPointer), mType->mTypeName, mLogAlignment);
430 1.5.2.2 christos } else {
431 1.5.2.2 christos Report(isFatal, "UBSan: Undefined Behavior in %s, %s address %p with insufficient space for an object of type %s\n",
432 1.5.2.2 christos szLocation, DeserializeTypeCheckKind(mTypeCheckKind), REINTERPRET_CAST(void *, ulPointer), mType->mTypeName);
433 1.5.2.2 christos }
434 1.5.2.2 christos }
435 1.5.2.2 christos
436 1.5.2.2 christos static void
437 1.5.2.2 christos HandleVlaBoundNotPositive(bool isFatal, struct CVLABoundData *pData, unsigned long ulBound)
438 1.5.2.2 christos {
439 1.5.2.2 christos char szLocation[LOCATION_MAXLEN];
440 1.5.2.2 christos char szBound[NUMBER_MAXLEN];
441 1.5.2.2 christos
442 1.5.2.2 christos ASSERT(pData);
443 1.5.2.2 christos
444 1.5.2.2 christos if (isAlreadyReported(&pData->mLocation))
445 1.5.2.2 christos return;
446 1.5.2.2 christos
447 1.5.2.2 christos DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
448 1.5.2.2 christos DeserializeNumber(szLocation, szBound, NUMBER_MAXLEN, pData->mType, ulBound);
449 1.5.2.2 christos
450 1.5.2.2 christos Report(isFatal, "UBSan: Undefined Behavior in %s, variable length array bound value %s <= 0\n",
451 1.5.2.2 christos szLocation, szBound);
452 1.5.2.2 christos }
453 1.5.2.2 christos
454 1.5.2.2 christos static void
455 1.5.2.2 christos HandleOutOfBounds(bool isFatal, struct COutOfBoundsData *pData, unsigned long ulIndex)
456 1.5.2.2 christos {
457 1.5.2.2 christos char szLocation[LOCATION_MAXLEN];
458 1.5.2.2 christos char szIndex[NUMBER_MAXLEN];
459 1.5.2.2 christos
460 1.5.2.2 christos ASSERT(pData);
461 1.5.2.2 christos
462 1.5.2.2 christos if (isAlreadyReported(&pData->mLocation))
463 1.5.2.2 christos return;
464 1.5.2.2 christos
465 1.5.2.2 christos DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
466 1.5.2.2 christos DeserializeNumber(szLocation, szIndex, NUMBER_MAXLEN, pData->mIndexType, ulIndex);
467 1.5.2.2 christos
468 1.5.2.2 christos Report(isFatal, "UBSan: Undefined Behavior in %s, index %s is out of range for type %s\n",
469 1.5.2.2 christos szLocation, szIndex, pData->mArrayType->mTypeName);
470 1.5.2.2 christos }
471 1.5.2.2 christos
472 1.5.2.2 christos static void
473 1.5.2.2 christos HandleShiftOutOfBounds(bool isFatal, struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS)
474 1.5.2.2 christos {
475 1.5.2.2 christos char szLocation[LOCATION_MAXLEN];
476 1.5.2.2 christos char szLHS[NUMBER_MAXLEN];
477 1.5.2.2 christos char szRHS[NUMBER_MAXLEN];
478 1.5.2.2 christos
479 1.5.2.2 christos ASSERT(pData);
480 1.5.2.2 christos
481 1.5.2.2 christos if (isAlreadyReported(&pData->mLocation))
482 1.5.2.2 christos return;
483 1.5.2.2 christos
484 1.5.2.2 christos DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
485 1.5.2.2 christos DeserializeNumber(szLocation, szLHS, NUMBER_MAXLEN, pData->mLHSType, ulLHS);
486 1.5.2.2 christos DeserializeNumber(szLocation, szRHS, NUMBER_MAXLEN, pData->mRHSType, ulRHS);
487 1.5.2.2 christos
488 1.5.2.2 christos if (isNegativeNumber(szLocation, pData->mRHSType, ulRHS))
489 1.5.2.2 christos Report(isFatal, "UBSan: Undefined Behavior in %s, shift exponent %s is negative\n",
490 1.5.2.2 christos szLocation, szRHS);
491 1.5.2.2 christos else if (isShiftExponentTooLarge(szLocation, pData->mRHSType, ulRHS, zDeserializeTypeWidth(pData->mLHSType)))
492 1.5.2.2 christos Report(isFatal, "UBSan: Undefined Behavior in %s, shift exponent %s is too large for %zu-bit type %s\n",
493 1.5.2.2 christos szLocation, szRHS, zDeserializeTypeWidth(pData->mLHSType), pData->mLHSType->mTypeName);
494 1.5.2.2 christos else if (isNegativeNumber(szLocation, pData->mLHSType, ulLHS))
495 1.5.2.2 christos Report(isFatal, "UBSan: Undefined Behavior in %s, left shift of negative value %s\n",
496 1.5.2.2 christos szLocation, szLHS);
497 1.5.2.2 christos else
498 1.5.2.2 christos Report(isFatal, "UBSan: Undefined Behavior in %s, left shift of %s by %s places cannot be represented in type %s\n",
499 1.5.2.2 christos szLocation, szLHS, szRHS, pData->mLHSType->mTypeName);
500 1.5.2.2 christos }
501 1.5.2.2 christos
502 1.5.2.2 christos static void
503 1.5.2.2 christos HandleLoadInvalidValue(bool isFatal, struct CInvalidValueData *pData, unsigned long ulValue)
504 1.5.2.2 christos {
505 1.5.2.2 christos char szLocation[LOCATION_MAXLEN];
506 1.5.2.2 christos char szValue[NUMBER_MAXLEN];
507 1.5.2.2 christos
508 1.5.2.2 christos ASSERT(pData);
509 1.5.2.2 christos
510 1.5.2.2 christos if (isAlreadyReported(&pData->mLocation))
511 1.5.2.2 christos return;
512 1.5.2.2 christos
513 1.5.2.2 christos DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
514 1.5.2.2 christos DeserializeNumber(szLocation, szValue, NUMBER_MAXLEN, pData->mType, ulValue);
515 1.5.2.2 christos
516 1.5.2.2 christos Report(isFatal, "UBSan: Undefined Behavior in %s, load of value %s is not a valid value for type %s\n",
517 1.5.2.2 christos szLocation, szValue, pData->mType->mTypeName);
518 1.5.2.2 christos }
519 1.5.2.2 christos
520 1.5.2.2 christos static void
521 1.5.2.2 christos HandleInvalidBuiltin(bool isFatal, struct CInvalidBuiltinData *pData)
522 1.5.2.2 christos {
523 1.5.2.2 christos char szLocation[LOCATION_MAXLEN];
524 1.5.2.2 christos
525 1.5.2.2 christos ASSERT(pData);
526 1.5.2.2 christos
527 1.5.2.2 christos if (isAlreadyReported(&pData->mLocation))
528 1.5.2.2 christos return;
529 1.5.2.2 christos
530 1.5.2.2 christos DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
531 1.5.2.2 christos
532 1.5.2.2 christos Report(isFatal, "UBSan: Undefined Behavior in %s, passing zero to %s, which is not a valid argument\n",
533 1.5.2.2 christos szLocation, DeserializeBuiltinCheckKind(pData->mKind));
534 1.5.2.2 christos }
535 1.5.2.2 christos
536 1.5.2.2 christos static void
537 1.5.2.2 christos HandleFunctionTypeMismatch(bool isFatal, struct CFunctionTypeMismatchData *pData, unsigned long ulFunction)
538 1.5.2.2 christos {
539 1.5.2.2 christos char szLocation[LOCATION_MAXLEN];
540 1.5.2.2 christos
541 1.5.2.2 christos /*
542 1.5.2.2 christos * There is no a portable C solution to translate an address of a
543 1.5.2.2 christos * function to its name. On the cost of getting this routine simple
544 1.5.2.2 christos * and portable without ifdefs between the userland and the kernel
545 1.5.2.2 christos * just print the address of the function as-is.
546 1.5.2.2 christos *
547 1.5.2.2 christos * For better diagnostic messages in the userland, users shall use
548 1.5.2.2 christos * the full upstream version shipped along with the compiler toolchain.
549 1.5.2.2 christos */
550 1.5.2.2 christos
551 1.5.2.2 christos ASSERT(pData);
552 1.5.2.2 christos
553 1.5.2.2 christos if (isAlreadyReported(&pData->mLocation))
554 1.5.2.2 christos return;
555 1.5.2.2 christos
556 1.5.2.2 christos DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
557 1.5.2.2 christos
558 1.5.2.2 christos Report(isFatal, "UBSan: Undefined Behavior in %s, call to function %#lx through pointer to incorrect function type %s\n",
559 1.5.2.2 christos szLocation, ulFunction, pData->mType->mTypeName);
560 1.5.2.2 christos }
561 1.5.2.2 christos
562 1.5.2.2 christos static void
563 1.5.2.2 christos HandleCFIBadType(bool isFatal, struct CCFICheckFailData *pData, unsigned long ulVtable, bool *bValidVtable, bool *FromUnrecoverableHandler, unsigned long *ProgramCounter, unsigned long *FramePointer)
564 1.5.2.2 christos {
565 1.5.2.2 christos char szLocation[LOCATION_MAXLEN];
566 1.5.2.2 christos
567 1.5.2.2 christos /*
568 1.5.2.2 christos * This is a minimal implementation without diving into C++
569 1.5.2.2 christos * specifics and (Itanium) ABI deserialization.
570 1.5.2.2 christos */
571 1.5.2.2 christos
572 1.5.2.2 christos ASSERT(pData);
573 1.5.2.2 christos
574 1.5.2.2 christos if (isAlreadyReported(&pData->mLocation))
575 1.5.2.2 christos return;
576 1.5.2.2 christos
577 1.5.2.2 christos DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
578 1.5.2.2 christos
579 1.5.2.2 christos if (pData->mCheckKind == CFI_ICALL || pData->mCheckKind == CFI_VMFCALL) {
580 1.5.2.2 christos Report(isFatal, "UBSan: Undefined Behavior in %s, control flow integrity check for type %s failed during %s (vtable address %#lx)\n",
581 1.5.2.2 christos szLocation, pData->mType->mTypeName, DeserializeCFICheckKind(pData->mCheckKind), ulVtable);
582 1.5.2.2 christos } else {
583 1.5.2.2 christos Report(isFatal || FromUnrecoverableHandler, "UBSan: Undefined Behavior in %s, control flow integrity check for type %s failed during %s (vtable address %#lx; %s vtable; from %s handler; Program Counter %#lx; Frame Pointer %#lx)\n",
584 1.5.2.2 christos szLocation, pData->mType->mTypeName, DeserializeCFICheckKind(pData->mCheckKind), ulVtable, *bValidVtable ? "valid" : "invalid", *FromUnrecoverableHandler ? "unrecoverable" : "recoverable", *ProgramCounter, *FramePointer);
585 1.5.2.2 christos }
586 1.5.2.2 christos }
587 1.5.2.2 christos
588 1.5.2.2 christos static void
589 1.5.2.2 christos HandleDynamicTypeCacheMiss(bool isFatal, struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash)
590 1.5.2.2 christos {
591 1.5.2.2 christos #if 0
592 1.5.2.2 christos char szLocation[LOCATION_MAXLEN];
593 1.5.2.2 christos
594 1.5.2.2 christos /*
595 1.5.2.2 christos * Unimplemented.
596 1.5.2.2 christos *
597 1.5.2.2 christos * This UBSan handler is special as the check has to be impelemented
598 1.5.2.2 christos * in an implementation. In order to handle it there is need to
599 1.5.2.2 christos * introspect into C++ ABI internals (RTTI) and use low-level
600 1.5.2.2 christos * C++ runtime interfaces.
601 1.5.2.2 christos */
602 1.5.2.2 christos
603 1.5.2.2 christos ASSERT(pData);
604 1.5.2.2 christos
605 1.5.2.2 christos if (isAlreadyReported(&pData->mLocation))
606 1.5.2.2 christos return;
607 1.5.2.2 christos
608 1.5.2.2 christos DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
609 1.5.2.2 christos
610 1.5.2.2 christos Report(isFatal, "UBSan: Undefined Behavior in %s, %s address %#lx which might not point to an object of type %s\n"
611 1.5.2.2 christos szLocation, DeserializeTypeCheckKind(pData->mTypeCheckKind), ulPointer, pData->mType);
612 1.5.2.2 christos #endif
613 1.5.2.2 christos }
614 1.5.2.2 christos
615 1.5.2.2 christos static void
616 1.5.2.2 christos HandleFloatCastOverflow(bool isFatal, struct CFloatCastOverflowData *pData, unsigned long ulFrom)
617 1.5.2.2 christos {
618 1.5.2.2 christos char szLocation[LOCATION_MAXLEN];
619 1.5.2.2 christos char szFrom[NUMBER_MAXLEN];
620 1.5.2.2 christos
621 1.5.2.2 christos ASSERT(pData);
622 1.5.2.2 christos
623 1.5.2.2 christos if (isAlreadyReported(&pData->mLocation))
624 1.5.2.2 christos return;
625 1.5.2.2 christos
626 1.5.2.2 christos DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
627 1.5.2.2 christos DeserializeNumber(szLocation, szFrom, NUMBER_MAXLEN, pData->mFromType, ulFrom);
628 1.5.2.2 christos
629 1.5.2.2 christos Report(isFatal, "UBSan: Undefined Behavior in %s, %s (of type %s) is outside the range of representable values of type %s\n",
630 1.5.2.2 christos szLocation, szFrom, pData->mFromType->mTypeName, pData->mToType->mTypeName);
631 1.5.2.2 christos }
632 1.5.2.2 christos
633 1.5.2.2 christos static void
634 1.5.2.2 christos HandleMissingReturn(bool isFatal, struct CUnreachableData *pData)
635 1.5.2.2 christos {
636 1.5.2.2 christos char szLocation[LOCATION_MAXLEN];
637 1.5.2.2 christos
638 1.5.2.2 christos ASSERT(pData);
639 1.5.2.2 christos
640 1.5.2.2 christos if (isAlreadyReported(&pData->mLocation))
641 1.5.2.2 christos return;
642 1.5.2.2 christos
643 1.5.2.2 christos DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
644 1.5.2.2 christos
645 1.5.2.2 christos Report(isFatal, "UBSan: Undefined Behavior in %s, execution reached the end of a value-returning function without returning a value\n",
646 1.5.2.2 christos szLocation);
647 1.5.2.2 christos }
648 1.5.2.2 christos
649 1.5.2.2 christos static void
650 1.5.2.2 christos HandleNonnullArg(bool isFatal, struct CNonNullArgData *pData)
651 1.5.2.2 christos {
652 1.5.2.2 christos char szLocation[LOCATION_MAXLEN];
653 1.5.2.2 christos char szAttributeLocation[LOCATION_MAXLEN];
654 1.5.2.2 christos
655 1.5.2.2 christos ASSERT(pData);
656 1.5.2.2 christos
657 1.5.2.2 christos if (isAlreadyReported(&pData->mLocation))
658 1.5.2.2 christos return;
659 1.5.2.2 christos
660 1.5.2.2 christos DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
661 1.5.2.2 christos if (pData->mAttributeLocation.mFilename)
662 1.5.2.2 christos DeserializeLocation(szAttributeLocation, LOCATION_MAXLEN, &pData->mAttributeLocation);
663 1.5.2.2 christos else
664 1.5.2.2 christos szAttributeLocation[0] = '\0';
665 1.5.2.2 christos
666 1.5.2.2 christos Report(isFatal, "UBSan: Undefined Behavior in %s, null pointer passed as argument %d, which is declared to never be null%s%s\n",
667 1.5.2.2 christos szLocation, pData->mArgIndex, pData->mAttributeLocation.mFilename ? ", nonnull/_Nonnull specified in " : "", szAttributeLocation);
668 1.5.2.2 christos }
669 1.5.2.2 christos
670 1.5.2.2 christos static void
671 1.5.2.2 christos HandleNonnullReturn(bool isFatal, struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
672 1.5.2.2 christos {
673 1.5.2.2 christos char szLocation[LOCATION_MAXLEN];
674 1.5.2.2 christos char szAttributeLocation[LOCATION_MAXLEN];
675 1.5.2.2 christos
676 1.5.2.2 christos ASSERT(pData);
677 1.5.2.2 christos ASSERT(pLocationPointer);
678 1.5.2.2 christos
679 1.5.2.2 christos if (isAlreadyReported(pLocationPointer))
680 1.5.2.2 christos return;
681 1.5.2.2 christos
682 1.5.2.2 christos DeserializeLocation(szLocation, LOCATION_MAXLEN, pLocationPointer);
683 1.5.2.2 christos if (pData->mAttributeLocation.mFilename)
684 1.5.2.2 christos DeserializeLocation(szAttributeLocation, LOCATION_MAXLEN, &pData->mAttributeLocation);
685 1.5.2.2 christos else
686 1.5.2.2 christos szAttributeLocation[0] = '\0';
687 1.5.2.2 christos
688 1.5.2.2 christos Report(isFatal, "UBSan: Undefined Behavior in %s, null pointer returned from function declared to never return null%s%s\n",
689 1.5.2.2 christos szLocation, pData->mAttributeLocation.mFilename ? ", nonnull/_Nonnull specified in " : "", szAttributeLocation);
690 1.5.2.2 christos }
691 1.5.2.2 christos
692 1.5.2.2 christos static void
693 1.5.2.2 christos HandlePointerOverflow(bool isFatal, struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult)
694 1.5.2.2 christos {
695 1.5.2.2 christos char szLocation[LOCATION_MAXLEN];
696 1.5.2.2 christos
697 1.5.2.2 christos ASSERT(pData);
698 1.5.2.2 christos
699 1.5.2.2 christos if (isAlreadyReported(&pData->mLocation))
700 1.5.2.2 christos return;
701 1.5.2.2 christos
702 1.5.2.2 christos DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
703 1.5.2.2 christos
704 1.5.2.2 christos Report(isFatal, "UBSan: Undefined Behavior in %s, pointer expression with base %#lx overflowed to %#lx\n",
705 1.5.2.2 christos szLocation, ulBase, ulResult);
706 1.5.2.2 christos }
707 1.5.2.2 christos
708 1.5.2.3 martin static void
709 1.5.2.3 martin HandleImplicitConversion(bool isFatal, struct CImplicitConversionData *pData, unsigned long ulFrom, unsigned long ulTo)
710 1.5.2.3 martin {
711 1.5.2.3 martin char szLocation[LOCATION_MAXLEN];
712 1.5.2.3 martin char szFrom[NUMBER_MAXLEN];
713 1.5.2.3 martin char szTo[NUMBER_MAXLEN];
714 1.5.2.3 martin
715 1.5.2.3 martin ASSERT(pData);
716 1.5.2.3 martin
717 1.5.2.3 martin if (isAlreadyReported(&pData->mLocation))
718 1.5.2.3 martin return;
719 1.5.2.3 martin
720 1.5.2.3 martin DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
721 1.5.2.3 martin DeserializeNumber(szLocation, szFrom, NUMBER_MAXLEN, pData->mFromType, ulFrom);
722 1.5.2.3 martin DeserializeNumber(szLocation, szTo, NUMBER_MAXLEN, pData->mToType, ulTo);
723 1.5.2.3 martin
724 1.5.2.3 martin Report(isFatal, "UBSan: Undefined Behavior in %s, %s from %s %zu-bit %s (%s) to %s changed the value to %s %zu-bit %s\n",
725 1.5.2.3 martin szLocation, DeserializeImplicitConversionCheckKind(pData->mKind), szFrom, zDeserializeTypeWidth(pData->mFromType), ISSET(pData->mFromType->mTypeInfo, NUMBER_SIGNED_BIT) ? "signed" : "unsigned", pData->mFromType->mTypeName, pData->mToType->mTypeName, szTo, zDeserializeTypeWidth(pData->mToType), ISSET(pData->mToType->mTypeInfo, NUMBER_SIGNED_BIT) ? "signed" : "unsigned");
726 1.5.2.3 martin }
727 1.5.2.3 martin
728 1.5.2.3 martin static void
729 1.5.2.3 martin HandleAlignmentAssumption(bool isFatal, struct CAlignmentAssumptionData *pData, unsigned long ulPointer, unsigned long ulAlignment, unsigned long ulOffset)
730 1.5.2.3 martin {
731 1.5.2.3 martin char szLocation[LOCATION_MAXLEN];
732 1.5.2.3 martin char szAssumptionLocation[LOCATION_MAXLEN];
733 1.5.2.3 martin unsigned long ulRealPointer;
734 1.5.2.3 martin
735 1.5.2.3 martin ASSERT(pData);
736 1.5.2.3 martin
737 1.5.2.3 martin if (isAlreadyReported(&pData->mLocation))
738 1.5.2.3 martin return;
739 1.5.2.3 martin
740 1.5.2.3 martin DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
741 1.5.2.3 martin
742 1.5.2.3 martin ulRealPointer = ulPointer - ulOffset;
743 1.5.2.3 martin
744 1.5.2.3 martin if (pData->mAssumptionLocation.mFilename != NULL) {
745 1.5.2.3 martin DeserializeLocation(szAssumptionLocation, LOCATION_MAXLEN,
746 1.5.2.3 martin &pData->mAssumptionLocation);
747 1.5.2.3 martin Report(isFatal, "UBSan: Undefined Behavior in %s, alignment assumption of %#lx for pointer %#lx (offset %#lx), asumption made in %s\n",
748 1.5.2.3 martin szLocation, ulAlignment, ulRealPointer, ulOffset,
749 1.5.2.3 martin szAssumptionLocation);
750 1.5.2.3 martin } else {
751 1.5.2.3 martin Report(isFatal, "UBSan: Undefined Behavior in %s, alignment assumption of %#lx for pointer %#lx (offset %#lx)\n",
752 1.5.2.3 martin szLocation, ulAlignment, ulRealPointer, ulOffset);
753 1.5.2.3 martin }
754 1.5.2.3 martin }
755 1.5.2.3 martin
756 1.5.2.2 christos /* Definions of public symbols emitted by the instrumentation code */
757 1.5.2.2 christos void
758 1.5.2.2 christos __ubsan_handle_add_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
759 1.5.2.2 christos {
760 1.5.2.2 christos
761 1.5.2.2 christos ASSERT(pData);
762 1.5.2.2 christos
763 1.5.2.2 christos HandleOverflow(false, pData, ulLHS, ulRHS, PLUS_STRING);
764 1.5.2.2 christos }
765 1.5.2.2 christos
766 1.5.2.2 christos void
767 1.5.2.2 christos __ubsan_handle_add_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
768 1.5.2.2 christos {
769 1.5.2.2 christos
770 1.5.2.2 christos ASSERT(pData);
771 1.5.2.2 christos
772 1.5.2.2 christos HandleOverflow(true, pData, ulLHS, ulRHS, PLUS_STRING);
773 1.5.2.2 christos }
774 1.5.2.2 christos
775 1.5.2.2 christos void
776 1.5.2.3 martin __ubsan_handle_alignment_assumption(struct CAlignmentAssumptionData *pData, unsigned long ulPointer, unsigned long ulAlignment, unsigned long ulOffset)
777 1.5.2.3 martin {
778 1.5.2.3 martin
779 1.5.2.3 martin ASSERT(pData);
780 1.5.2.3 martin
781 1.5.2.3 martin HandleAlignmentAssumption(false, pData, ulPointer, ulAlignment, ulOffset);
782 1.5.2.3 martin }
783 1.5.2.3 martin
784 1.5.2.3 martin void
785 1.5.2.3 martin __ubsan_handle_alignment_assumption_abort(struct CAlignmentAssumptionData *pData, unsigned long ulPointer, unsigned long ulAlignment, unsigned long ulOffset)
786 1.5.2.3 martin {
787 1.5.2.3 martin
788 1.5.2.3 martin ASSERT(pData);
789 1.5.2.3 martin
790 1.5.2.3 martin HandleAlignmentAssumption(true, pData, ulPointer, ulAlignment, ulOffset);
791 1.5.2.3 martin }
792 1.5.2.3 martin
793 1.5.2.3 martin void
794 1.5.2.2 christos __ubsan_handle_builtin_unreachable(struct CUnreachableData *pData)
795 1.5.2.2 christos {
796 1.5.2.2 christos
797 1.5.2.2 christos ASSERT(pData);
798 1.5.2.2 christos
799 1.5.2.2 christos HandleBuiltinUnreachable(true, pData);
800 1.5.2.2 christos }
801 1.5.2.2 christos
802 1.5.2.2 christos void
803 1.5.2.2 christos __ubsan_handle_cfi_bad_type(struct CCFICheckFailData *pData, unsigned long ulVtable, bool bValidVtable, bool FromUnrecoverableHandler, unsigned long ProgramCounter, unsigned long FramePointer)
804 1.5.2.2 christos {
805 1.5.2.2 christos
806 1.5.2.2 christos ASSERT(pData);
807 1.5.2.2 christos
808 1.5.2.2 christos HandleCFIBadType(false, pData, ulVtable, &bValidVtable, &FromUnrecoverableHandler, &ProgramCounter, &FramePointer);
809 1.5.2.2 christos }
810 1.5.2.2 christos
811 1.5.2.2 christos void
812 1.5.2.2 christos __ubsan_handle_cfi_check_fail(struct CCFICheckFailData *pData, unsigned long ulValue, unsigned long ulValidVtable)
813 1.5.2.2 christos {
814 1.5.2.2 christos
815 1.5.2.2 christos ASSERT(pData);
816 1.5.2.2 christos
817 1.5.2.2 christos HandleCFIBadType(false, pData, ulValue, 0, 0, 0, 0);
818 1.5.2.2 christos }
819 1.5.2.2 christos
820 1.5.2.2 christos void
821 1.5.2.2 christos __ubsan_handle_cfi_check_fail_abort(struct CCFICheckFailData *pData, unsigned long ulValue, unsigned long ulValidVtable)
822 1.5.2.2 christos {
823 1.5.2.2 christos
824 1.5.2.2 christos ASSERT(pData);
825 1.5.2.2 christos
826 1.5.2.2 christos HandleCFIBadType(true, pData, ulValue, 0, 0, 0, 0);
827 1.5.2.2 christos }
828 1.5.2.2 christos
829 1.5.2.2 christos void
830 1.5.2.2 christos __ubsan_handle_divrem_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
831 1.5.2.2 christos {
832 1.5.2.2 christos
833 1.5.2.2 christos ASSERT(pData);
834 1.5.2.2 christos
835 1.5.2.2 christos HandleOverflow(false, pData, ulLHS, ulRHS, DIVREM_STRING);
836 1.5.2.2 christos }
837 1.5.2.2 christos
838 1.5.2.2 christos void
839 1.5.2.2 christos __ubsan_handle_divrem_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
840 1.5.2.2 christos {
841 1.5.2.2 christos
842 1.5.2.2 christos ASSERT(pData);
843 1.5.2.2 christos
844 1.5.2.2 christos HandleOverflow(true, pData, ulLHS, ulRHS, DIVREM_STRING);
845 1.5.2.2 christos }
846 1.5.2.2 christos
847 1.5.2.2 christos void
848 1.5.2.2 christos __ubsan_handle_dynamic_type_cache_miss(struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash)
849 1.5.2.2 christos {
850 1.5.2.2 christos
851 1.5.2.2 christos ASSERT(pData);
852 1.5.2.2 christos
853 1.5.2.2 christos HandleDynamicTypeCacheMiss(false, pData, ulPointer, ulHash);
854 1.5.2.2 christos }
855 1.5.2.2 christos
856 1.5.2.2 christos void
857 1.5.2.2 christos __ubsan_handle_dynamic_type_cache_miss_abort(struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash)
858 1.5.2.2 christos {
859 1.5.2.2 christos
860 1.5.2.2 christos ASSERT(pData);
861 1.5.2.2 christos
862 1.5.2.2 christos HandleDynamicTypeCacheMiss(false, pData, ulPointer, ulHash);
863 1.5.2.2 christos }
864 1.5.2.2 christos
865 1.5.2.2 christos void
866 1.5.2.2 christos __ubsan_handle_float_cast_overflow(struct CFloatCastOverflowData *pData, unsigned long ulFrom)
867 1.5.2.2 christos {
868 1.5.2.2 christos
869 1.5.2.2 christos ASSERT(pData);
870 1.5.2.2 christos
871 1.5.2.2 christos HandleFloatCastOverflow(false, pData, ulFrom);
872 1.5.2.2 christos }
873 1.5.2.2 christos
874 1.5.2.2 christos void
875 1.5.2.2 christos __ubsan_handle_float_cast_overflow_abort(struct CFloatCastOverflowData *pData, unsigned long ulFrom)
876 1.5.2.2 christos {
877 1.5.2.2 christos
878 1.5.2.2 christos ASSERT(pData);
879 1.5.2.2 christos
880 1.5.2.2 christos HandleFloatCastOverflow(true, pData, ulFrom);
881 1.5.2.2 christos }
882 1.5.2.2 christos
883 1.5.2.2 christos void
884 1.5.2.2 christos __ubsan_handle_function_type_mismatch(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction)
885 1.5.2.2 christos {
886 1.5.2.2 christos
887 1.5.2.2 christos ASSERT(pData);
888 1.5.2.2 christos
889 1.5.2.2 christos HandleFunctionTypeMismatch(false, pData, ulFunction);
890 1.5.2.2 christos }
891 1.5.2.2 christos
892 1.5.2.2 christos void
893 1.5.2.2 christos __ubsan_handle_function_type_mismatch_abort(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction)
894 1.5.2.2 christos {
895 1.5.2.2 christos
896 1.5.2.2 christos ASSERT(pData);
897 1.5.2.2 christos
898 1.5.2.3 martin HandleFunctionTypeMismatch(true, pData, ulFunction);
899 1.5.2.3 martin }
900 1.5.2.3 martin
901 1.5.2.3 martin void
902 1.5.2.3 martin __ubsan_handle_function_type_mismatch_v1(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction, unsigned long ulCalleeRTTI, unsigned long ulFnRTTI)
903 1.5.2.3 martin {
904 1.5.2.3 martin
905 1.5.2.3 martin ASSERT(pData);
906 1.5.2.3 martin #if 0
907 1.5.2.3 martin /*
908 1.5.2.3 martin * Unimplemented.
909 1.5.2.3 martin *
910 1.5.2.3 martin * This UBSan handler is special as the check has to be impelemented
911 1.5.2.3 martin * in an implementation. In order to handle it there is need to
912 1.5.2.3 martin * introspect into C++ ABI internals (RTTI) and use low-level
913 1.5.2.3 martin * C++ runtime interfaces.
914 1.5.2.3 martin */
915 1.5.2.3 martin
916 1.5.2.2 christos HandleFunctionTypeMismatch(false, pData, ulFunction);
917 1.5.2.3 martin #endif
918 1.5.2.3 martin }
919 1.5.2.3 martin
920 1.5.2.3 martin void
921 1.5.2.3 martin __ubsan_handle_function_type_mismatch_v1_abort(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction, unsigned long ulCalleeRTTI, unsigned long ulFnRTTI)
922 1.5.2.3 martin {
923 1.5.2.3 martin
924 1.5.2.3 martin ASSERT(pData);
925 1.5.2.3 martin #if 0
926 1.5.2.3 martin /*
927 1.5.2.3 martin * Unimplemented.
928 1.5.2.3 martin *
929 1.5.2.3 martin * This UBSan handler is special as the check has to be impelemented
930 1.5.2.3 martin * in an implementation. In order to handle it there is need to
931 1.5.2.3 martin * introspect into C++ ABI internals (RTTI) and use low-level
932 1.5.2.3 martin * C++ runtime interfaces.
933 1.5.2.3 martin */
934 1.5.2.3 martin
935 1.5.2.3 martin HandleFunctionTypeMismatch(true, pData, ulFunction);
936 1.5.2.3 martin #endif
937 1.5.2.2 christos }
938 1.5.2.2 christos
939 1.5.2.2 christos void
940 1.5.2.2 christos __ubsan_handle_invalid_builtin(struct CInvalidBuiltinData *pData)
941 1.5.2.2 christos {
942 1.5.2.2 christos
943 1.5.2.2 christos ASSERT(pData);
944 1.5.2.2 christos
945 1.5.2.2 christos HandleInvalidBuiltin(true, pData);
946 1.5.2.2 christos }
947 1.5.2.2 christos
948 1.5.2.2 christos void
949 1.5.2.2 christos __ubsan_handle_invalid_builtin_abort(struct CInvalidBuiltinData *pData)
950 1.5.2.2 christos {
951 1.5.2.2 christos
952 1.5.2.2 christos ASSERT(pData);
953 1.5.2.2 christos
954 1.5.2.2 christos HandleInvalidBuiltin(true, pData);
955 1.5.2.2 christos }
956 1.5.2.2 christos
957 1.5.2.2 christos void
958 1.5.2.2 christos __ubsan_handle_load_invalid_value(struct CInvalidValueData *pData, unsigned long ulValue)
959 1.5.2.2 christos {
960 1.5.2.2 christos
961 1.5.2.2 christos ASSERT(pData);
962 1.5.2.2 christos
963 1.5.2.2 christos HandleLoadInvalidValue(false, pData, ulValue);
964 1.5.2.2 christos }
965 1.5.2.2 christos
966 1.5.2.2 christos void
967 1.5.2.2 christos __ubsan_handle_load_invalid_value_abort(struct CInvalidValueData *pData, unsigned long ulValue)
968 1.5.2.2 christos {
969 1.5.2.2 christos
970 1.5.2.2 christos ASSERT(pData);
971 1.5.2.2 christos
972 1.5.2.2 christos HandleLoadInvalidValue(true, pData, ulValue);
973 1.5.2.2 christos }
974 1.5.2.2 christos
975 1.5.2.2 christos void
976 1.5.2.2 christos __ubsan_handle_missing_return(struct CUnreachableData *pData)
977 1.5.2.2 christos {
978 1.5.2.2 christos
979 1.5.2.2 christos ASSERT(pData);
980 1.5.2.2 christos
981 1.5.2.2 christos HandleMissingReturn(true, pData);
982 1.5.2.2 christos }
983 1.5.2.2 christos
984 1.5.2.2 christos void
985 1.5.2.2 christos __ubsan_handle_mul_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
986 1.5.2.2 christos {
987 1.5.2.2 christos
988 1.5.2.2 christos ASSERT(pData);
989 1.5.2.2 christos
990 1.5.2.2 christos HandleOverflow(false, pData, ulLHS, ulRHS, MUL_STRING);
991 1.5.2.2 christos }
992 1.5.2.2 christos
993 1.5.2.2 christos void
994 1.5.2.2 christos __ubsan_handle_mul_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
995 1.5.2.2 christos {
996 1.5.2.2 christos
997 1.5.2.2 christos ASSERT(pData);
998 1.5.2.2 christos
999 1.5.2.2 christos HandleOverflow(true, pData, ulLHS, ulRHS, MUL_STRING);
1000 1.5.2.2 christos }
1001 1.5.2.2 christos
1002 1.5.2.2 christos void
1003 1.5.2.2 christos __ubsan_handle_negate_overflow(struct COverflowData *pData, unsigned long ulOldValue)
1004 1.5.2.2 christos {
1005 1.5.2.2 christos
1006 1.5.2.2 christos ASSERT(pData);
1007 1.5.2.2 christos
1008 1.5.2.2 christos HandleNegateOverflow(false, pData, ulOldValue);
1009 1.5.2.2 christos }
1010 1.5.2.2 christos
1011 1.5.2.2 christos void
1012 1.5.2.2 christos __ubsan_handle_negate_overflow_abort(struct COverflowData *pData, unsigned long ulOldValue)
1013 1.5.2.2 christos {
1014 1.5.2.2 christos
1015 1.5.2.2 christos ASSERT(pData);
1016 1.5.2.2 christos
1017 1.5.2.2 christos HandleNegateOverflow(true, pData, ulOldValue);
1018 1.5.2.2 christos }
1019 1.5.2.2 christos
1020 1.5.2.2 christos void
1021 1.5.2.2 christos __ubsan_handle_nonnull_arg(struct CNonNullArgData *pData)
1022 1.5.2.2 christos {
1023 1.5.2.2 christos
1024 1.5.2.2 christos ASSERT(pData);
1025 1.5.2.2 christos
1026 1.5.2.2 christos HandleNonnullArg(false, pData);
1027 1.5.2.2 christos }
1028 1.5.2.2 christos
1029 1.5.2.2 christos void
1030 1.5.2.2 christos __ubsan_handle_nonnull_arg_abort(struct CNonNullArgData *pData)
1031 1.5.2.2 christos {
1032 1.5.2.2 christos
1033 1.5.2.2 christos ASSERT(pData);
1034 1.5.2.2 christos
1035 1.5.2.2 christos HandleNonnullArg(true, pData);
1036 1.5.2.2 christos }
1037 1.5.2.2 christos
1038 1.5.2.2 christos void
1039 1.5.2.2 christos __ubsan_handle_nonnull_return_v1(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
1040 1.5.2.2 christos {
1041 1.5.2.2 christos
1042 1.5.2.2 christos ASSERT(pData);
1043 1.5.2.2 christos ASSERT(pLocationPointer);
1044 1.5.2.2 christos
1045 1.5.2.2 christos HandleNonnullReturn(false, pData, pLocationPointer);
1046 1.5.2.2 christos }
1047 1.5.2.2 christos
1048 1.5.2.2 christos void
1049 1.5.2.2 christos __ubsan_handle_nonnull_return_v1_abort(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
1050 1.5.2.2 christos {
1051 1.5.2.2 christos
1052 1.5.2.2 christos ASSERT(pData);
1053 1.5.2.2 christos ASSERT(pLocationPointer);
1054 1.5.2.2 christos
1055 1.5.2.2 christos HandleNonnullReturn(true, pData, pLocationPointer);
1056 1.5.2.2 christos }
1057 1.5.2.2 christos
1058 1.5.2.2 christos void
1059 1.5.2.2 christos __ubsan_handle_nullability_arg(struct CNonNullArgData *pData)
1060 1.5.2.2 christos {
1061 1.5.2.2 christos
1062 1.5.2.2 christos ASSERT(pData);
1063 1.5.2.2 christos
1064 1.5.2.2 christos HandleNonnullArg(false, pData);
1065 1.5.2.2 christos }
1066 1.5.2.2 christos
1067 1.5.2.2 christos void
1068 1.5.2.2 christos __ubsan_handle_nullability_arg_abort(struct CNonNullArgData *pData)
1069 1.5.2.2 christos {
1070 1.5.2.2 christos
1071 1.5.2.2 christos ASSERT(pData);
1072 1.5.2.2 christos
1073 1.5.2.2 christos HandleNonnullArg(true, pData);
1074 1.5.2.2 christos }
1075 1.5.2.2 christos
1076 1.5.2.2 christos void
1077 1.5.2.2 christos __ubsan_handle_nullability_return_v1(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
1078 1.5.2.2 christos {
1079 1.5.2.2 christos
1080 1.5.2.2 christos ASSERT(pData);
1081 1.5.2.2 christos ASSERT(pLocationPointer);
1082 1.5.2.2 christos
1083 1.5.2.2 christos HandleNonnullReturn(false, pData, pLocationPointer);
1084 1.5.2.2 christos }
1085 1.5.2.2 christos
1086 1.5.2.2 christos void
1087 1.5.2.2 christos __ubsan_handle_nullability_return_v1_abort(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
1088 1.5.2.2 christos {
1089 1.5.2.2 christos
1090 1.5.2.2 christos ASSERT(pData);
1091 1.5.2.2 christos ASSERT(pLocationPointer);
1092 1.5.2.2 christos
1093 1.5.2.2 christos HandleNonnullReturn(true, pData, pLocationPointer);
1094 1.5.2.2 christos }
1095 1.5.2.2 christos
1096 1.5.2.2 christos void
1097 1.5.2.2 christos __ubsan_handle_out_of_bounds(struct COutOfBoundsData *pData, unsigned long ulIndex)
1098 1.5.2.2 christos {
1099 1.5.2.2 christos
1100 1.5.2.2 christos ASSERT(pData);
1101 1.5.2.2 christos
1102 1.5.2.2 christos HandleOutOfBounds(false, pData, ulIndex);
1103 1.5.2.2 christos }
1104 1.5.2.2 christos
1105 1.5.2.2 christos void
1106 1.5.2.2 christos __ubsan_handle_out_of_bounds_abort(struct COutOfBoundsData *pData, unsigned long ulIndex)
1107 1.5.2.2 christos {
1108 1.5.2.2 christos
1109 1.5.2.2 christos ASSERT(pData);
1110 1.5.2.2 christos
1111 1.5.2.2 christos HandleOutOfBounds(true, pData, ulIndex);
1112 1.5.2.2 christos }
1113 1.5.2.2 christos
1114 1.5.2.2 christos void
1115 1.5.2.2 christos __ubsan_handle_pointer_overflow(struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult)
1116 1.5.2.2 christos {
1117 1.5.2.2 christos
1118 1.5.2.2 christos ASSERT(pData);
1119 1.5.2.2 christos
1120 1.5.2.2 christos HandlePointerOverflow(false, pData, ulBase, ulResult);
1121 1.5.2.2 christos }
1122 1.5.2.2 christos
1123 1.5.2.2 christos void
1124 1.5.2.2 christos __ubsan_handle_pointer_overflow_abort(struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult)
1125 1.5.2.2 christos {
1126 1.5.2.2 christos
1127 1.5.2.2 christos ASSERT(pData);
1128 1.5.2.2 christos
1129 1.5.2.2 christos HandlePointerOverflow(true, pData, ulBase, ulResult);
1130 1.5.2.2 christos }
1131 1.5.2.2 christos
1132 1.5.2.2 christos void
1133 1.5.2.2 christos __ubsan_handle_shift_out_of_bounds(struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS)
1134 1.5.2.2 christos {
1135 1.5.2.2 christos
1136 1.5.2.2 christos ASSERT(pData);
1137 1.5.2.2 christos
1138 1.5.2.2 christos HandleShiftOutOfBounds(false, pData, ulLHS, ulRHS);
1139 1.5.2.2 christos }
1140 1.5.2.2 christos
1141 1.5.2.2 christos void
1142 1.5.2.2 christos __ubsan_handle_shift_out_of_bounds_abort(struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS)
1143 1.5.2.2 christos {
1144 1.5.2.2 christos
1145 1.5.2.2 christos ASSERT(pData);
1146 1.5.2.2 christos
1147 1.5.2.2 christos HandleShiftOutOfBounds(true, pData, ulLHS, ulRHS);
1148 1.5.2.2 christos }
1149 1.5.2.2 christos
1150 1.5.2.2 christos void
1151 1.5.2.2 christos __ubsan_handle_sub_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
1152 1.5.2.2 christos {
1153 1.5.2.2 christos
1154 1.5.2.2 christos ASSERT(pData);
1155 1.5.2.2 christos
1156 1.5.2.2 christos HandleOverflow(false, pData, ulLHS, ulRHS, MINUS_STRING);
1157 1.5.2.2 christos }
1158 1.5.2.2 christos
1159 1.5.2.2 christos void
1160 1.5.2.2 christos __ubsan_handle_sub_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
1161 1.5.2.2 christos {
1162 1.5.2.2 christos
1163 1.5.2.2 christos ASSERT(pData);
1164 1.5.2.2 christos
1165 1.5.2.2 christos HandleOverflow(true, pData, ulLHS, ulRHS, MINUS_STRING);
1166 1.5.2.2 christos }
1167 1.5.2.2 christos
1168 1.5.2.2 christos void
1169 1.5.2.2 christos __ubsan_handle_type_mismatch(struct CTypeMismatchData *pData, unsigned long ulPointer)
1170 1.5.2.2 christos {
1171 1.5.2.2 christos
1172 1.5.2.2 christos ASSERT(pData);
1173 1.5.2.2 christos
1174 1.5.2.2 christos HandleTypeMismatch(false, &pData->mLocation, pData->mType, pData->mLogAlignment, pData->mTypeCheckKind, ulPointer);
1175 1.5.2.2 christos }
1176 1.5.2.2 christos
1177 1.5.2.2 christos void
1178 1.5.2.2 christos __ubsan_handle_type_mismatch_abort(struct CTypeMismatchData *pData, unsigned long ulPointer)
1179 1.5.2.2 christos {
1180 1.5.2.2 christos
1181 1.5.2.2 christos ASSERT(pData);
1182 1.5.2.2 christos
1183 1.5.2.2 christos HandleTypeMismatch(true, &pData->mLocation, pData->mType, pData->mLogAlignment, pData->mTypeCheckKind, ulPointer);
1184 1.5.2.2 christos }
1185 1.5.2.2 christos
1186 1.5.2.2 christos void
1187 1.5.2.2 christos __ubsan_handle_type_mismatch_v1(struct CTypeMismatchData_v1 *pData, unsigned long ulPointer)
1188 1.5.2.2 christos {
1189 1.5.2.2 christos
1190 1.5.2.2 christos ASSERT(pData);
1191 1.5.2.2 christos
1192 1.5.2.2 christos HandleTypeMismatch(false, &pData->mLocation, pData->mType, __BIT(pData->mLogAlignment), pData->mTypeCheckKind, ulPointer);
1193 1.5.2.2 christos }
1194 1.5.2.2 christos
1195 1.5.2.2 christos void
1196 1.5.2.2 christos __ubsan_handle_type_mismatch_v1_abort(struct CTypeMismatchData_v1 *pData, unsigned long ulPointer)
1197 1.5.2.2 christos {
1198 1.5.2.2 christos
1199 1.5.2.2 christos ASSERT(pData);
1200 1.5.2.2 christos
1201 1.5.2.2 christos HandleTypeMismatch(true, &pData->mLocation, pData->mType, __BIT(pData->mLogAlignment), pData->mTypeCheckKind, ulPointer);
1202 1.5.2.2 christos }
1203 1.5.2.2 christos
1204 1.5.2.2 christos void
1205 1.5.2.2 christos __ubsan_handle_vla_bound_not_positive(struct CVLABoundData *pData, unsigned long ulBound)
1206 1.5.2.2 christos {
1207 1.5.2.2 christos
1208 1.5.2.2 christos ASSERT(pData);
1209 1.5.2.2 christos
1210 1.5.2.2 christos HandleVlaBoundNotPositive(false, pData, ulBound);
1211 1.5.2.2 christos }
1212 1.5.2.2 christos
1213 1.5.2.2 christos void
1214 1.5.2.2 christos __ubsan_handle_vla_bound_not_positive_abort(struct CVLABoundData *pData, unsigned long ulBound)
1215 1.5.2.2 christos {
1216 1.5.2.2 christos
1217 1.5.2.2 christos ASSERT(pData);
1218 1.5.2.2 christos
1219 1.5.2.2 christos HandleVlaBoundNotPositive(true, pData, ulBound);
1220 1.5.2.2 christos }
1221 1.5.2.2 christos
1222 1.5.2.2 christos void
1223 1.5.2.3 martin __ubsan_handle_implicit_conversion(struct CImplicitConversionData *pData, unsigned long ulFrom, unsigned long ulTo)
1224 1.5.2.3 martin {
1225 1.5.2.3 martin
1226 1.5.2.3 martin ASSERT(pData);
1227 1.5.2.3 martin
1228 1.5.2.3 martin HandleImplicitConversion(false, pData, ulFrom, ulTo);
1229 1.5.2.3 martin }
1230 1.5.2.3 martin
1231 1.5.2.3 martin void
1232 1.5.2.3 martin __ubsan_handle_implicit_conversion_abort(struct CImplicitConversionData *pData, unsigned long ulFrom, unsigned long ulTo)
1233 1.5.2.3 martin {
1234 1.5.2.3 martin ASSERT(pData);
1235 1.5.2.3 martin
1236 1.5.2.3 martin HandleImplicitConversion(true, pData, ulFrom, ulTo);
1237 1.5.2.3 martin }
1238 1.5.2.3 martin
1239 1.5.2.3 martin void
1240 1.5.2.2 christos __ubsan_get_current_report_data(const char **ppOutIssueKind, const char **ppOutMessage, const char **ppOutFilename, uint32_t *pOutLine, uint32_t *pOutCol, char **ppOutMemoryAddr)
1241 1.5.2.2 christos {
1242 1.5.2.2 christos /*
1243 1.5.2.2 christos * Unimplemented.
1244 1.5.2.2 christos *
1245 1.5.2.2 christos * The __ubsan_on_report() feature is non trivial to implement in a
1246 1.5.2.2 christos * shared code between the kernel and userland. It's also opening
1247 1.5.2.2 christos * new sets of potential problems as we are not expected to slow down
1248 1.5.2.2 christos * execution of certain kernel subsystems (synchronization issues,
1249 1.5.2.2 christos * interrupt handling etc).
1250 1.5.2.2 christos *
1251 1.5.2.2 christos * A proper solution would need probably a lock-free bounded queue built
1252 1.5.2.2 christos * with atomic operations with the property of miltiple consumers and
1253 1.5.2.2 christos * multiple producers. Maintaining and validating such code is not
1254 1.5.2.2 christos * worth the effort.
1255 1.5.2.2 christos *
1256 1.5.2.2 christos * A legitimate user - besides testing framework - is a debugger plugin
1257 1.5.2.2 christos * intercepting reports from the UBSan instrumentation. For such
1258 1.5.2.2 christos * scenarios it is better to run the Clang/GCC version.
1259 1.5.2.2 christos */
1260 1.5.2.2 christos }
1261 1.5.2.2 christos
1262 1.5.2.2 christos /* Local utility functions */
1263 1.5.2.2 christos
1264 1.5.2.2 christos static void
1265 1.5.2.2 christos Report(bool isFatal, const char *pFormat, ...)
1266 1.5.2.2 christos {
1267 1.5.2.2 christos va_list ap;
1268 1.5.2.2 christos
1269 1.5.2.2 christos ASSERT(pFormat);
1270 1.5.2.2 christos
1271 1.5.2.2 christos va_start(ap, pFormat);
1272 1.5.2.2 christos #if defined(_KERNEL)
1273 1.5.2.3 martin if (isFatal || alwaysFatal)
1274 1.5.2.2 christos vpanic(pFormat, ap);
1275 1.5.2.2 christos else
1276 1.5.2.2 christos vprintf(pFormat, ap);
1277 1.5.2.2 christos #else
1278 1.5.2.2 christos if (ubsan_flags == -1) {
1279 1.5.2.2 christos char buf[1024];
1280 1.5.2.2 christos char *p;
1281 1.5.2.2 christos
1282 1.5.2.2 christos ubsan_flags = UBSAN_STDERR;
1283 1.5.2.2 christos
1284 1.5.2.2 christos if (getenv_r("LIBC_UBSAN", buf, sizeof(buf)) != -1) {
1285 1.5.2.2 christos for (p = buf; *p; p++) {
1286 1.5.2.2 christos switch (*p) {
1287 1.5.2.2 christos case 'a':
1288 1.5.2.2 christos SET(ubsan_flags, UBSAN_ABORT);
1289 1.5.2.2 christos break;
1290 1.5.2.2 christos case 'A':
1291 1.5.2.2 christos CLR(ubsan_flags, UBSAN_ABORT);
1292 1.5.2.2 christos break;
1293 1.5.2.2 christos case 'e':
1294 1.5.2.2 christos SET(ubsan_flags, UBSAN_STDERR);
1295 1.5.2.2 christos break;
1296 1.5.2.2 christos case 'E':
1297 1.5.2.2 christos CLR(ubsan_flags, UBSAN_STDERR);
1298 1.5.2.2 christos break;
1299 1.5.2.2 christos case 'l':
1300 1.5.2.2 christos SET(ubsan_flags, UBSAN_SYSLOG);
1301 1.5.2.2 christos break;
1302 1.5.2.2 christos case 'L':
1303 1.5.2.2 christos CLR(ubsan_flags, UBSAN_SYSLOG);
1304 1.5.2.2 christos break;
1305 1.5.2.2 christos case 'o':
1306 1.5.2.2 christos SET(ubsan_flags, UBSAN_STDOUT);
1307 1.5.2.2 christos break;
1308 1.5.2.2 christos case 'O':
1309 1.5.2.2 christos CLR(ubsan_flags, UBSAN_STDOUT);
1310 1.5.2.2 christos break;
1311 1.5.2.2 christos default:
1312 1.5.2.2 christos break;
1313 1.5.2.2 christos }
1314 1.5.2.2 christos }
1315 1.5.2.2 christos }
1316 1.5.2.2 christos }
1317 1.5.2.2 christos
1318 1.5.2.2 christos // The *v*print* functions can flush the va_list argument.
1319 1.5.2.2 christos // Create a local copy for each call to prevent invalid read.
1320 1.5.2.2 christos if (ISSET(ubsan_flags, UBSAN_STDOUT)) {
1321 1.5.2.2 christos va_list tmp;
1322 1.5.2.2 christos va_copy(tmp, ap);
1323 1.5.2.2 christos vprintf(pFormat, tmp);
1324 1.5.2.2 christos va_end(tmp);
1325 1.5.2.2 christos fflush(stdout);
1326 1.5.2.2 christos }
1327 1.5.2.2 christos if (ISSET(ubsan_flags, UBSAN_STDERR)) {
1328 1.5.2.2 christos va_list tmp;
1329 1.5.2.2 christos va_copy(tmp, ap);
1330 1.5.2.2 christos vfprintf(stderr, pFormat, tmp);
1331 1.5.2.2 christos va_end(tmp);
1332 1.5.2.2 christos fflush(stderr);
1333 1.5.2.2 christos }
1334 1.5.2.2 christos if (ISSET(ubsan_flags, UBSAN_SYSLOG)) {
1335 1.5.2.2 christos va_list tmp;
1336 1.5.2.2 christos va_copy(tmp, ap);
1337 1.5.2.2 christos struct syslog_data SyslogData = SYSLOG_DATA_INIT;
1338 1.5.2.2 christos ubsan_vsyslog(LOG_DEBUG | LOG_USER, &SyslogData, pFormat, tmp);
1339 1.5.2.2 christos va_end(tmp);
1340 1.5.2.2 christos }
1341 1.5.2.3 martin if (isFatal || alwaysFatal || ISSET(ubsan_flags, UBSAN_ABORT)) {
1342 1.5.2.2 christos abort();
1343 1.5.2.2 christos __unreachable();
1344 1.5.2.2 christos /* NOTREACHED */
1345 1.5.2.2 christos }
1346 1.5.2.2 christos #endif
1347 1.5.2.2 christos va_end(ap);
1348 1.5.2.2 christos }
1349 1.5.2.2 christos
1350 1.5.2.2 christos static bool
1351 1.5.2.2 christos isAlreadyReported(struct CSourceLocation *pLocation)
1352 1.5.2.2 christos {
1353 1.5.2.2 christos /*
1354 1.5.2.2 christos * This code is shared between libc, kernel and standalone usage.
1355 1.5.2.2 christos * It shall work in early bootstrap phase of both of them.
1356 1.5.2.2 christos */
1357 1.5.2.2 christos
1358 1.5.2.2 christos uint32_t siOldValue;
1359 1.5.2.2 christos volatile uint32_t *pLine;
1360 1.5.2.2 christos
1361 1.5.2.2 christos ASSERT(pLocation);
1362 1.5.2.2 christos
1363 1.5.2.2 christos pLine = &pLocation->mLine;
1364 1.5.2.2 christos
1365 1.5.2.2 christos do {
1366 1.5.2.2 christos siOldValue = *pLine;
1367 1.5.2.2 christos } while (__sync_val_compare_and_swap(pLine, siOldValue, siOldValue | ACK_REPORTED) != siOldValue);
1368 1.5.2.2 christos
1369 1.5.2.2 christos return ISSET(siOldValue, ACK_REPORTED);
1370 1.5.2.2 christos }
1371 1.5.2.2 christos
1372 1.5.2.2 christos static size_t
1373 1.5.2.2 christos zDeserializeTypeWidth(struct CTypeDescriptor *pType)
1374 1.5.2.2 christos {
1375 1.5.2.2 christos size_t zWidth = 0;
1376 1.5.2.2 christos
1377 1.5.2.2 christos ASSERT(pType);
1378 1.5.2.2 christos
1379 1.5.2.2 christos switch (pType->mTypeKind) {
1380 1.5.2.2 christos case KIND_INTEGER:
1381 1.5.2.2 christos zWidth = __BIT(__SHIFTOUT(pType->mTypeInfo, ~NUMBER_SIGNED_BIT));
1382 1.5.2.2 christos break;
1383 1.5.2.2 christos case KIND_FLOAT:
1384 1.5.2.2 christos zWidth = pType->mTypeInfo;
1385 1.5.2.2 christos break;
1386 1.5.2.2 christos default:
1387 1.5.2.2 christos Report(true, "UBSan: Unknown variable type %#04" PRIx16 "\n", pType->mTypeKind);
1388 1.5.2.2 christos __unreachable();
1389 1.5.2.2 christos /* NOTREACHED */
1390 1.5.2.2 christos }
1391 1.5.2.2 christos
1392 1.5.2.2 christos /* Invalid width will be transformed to 0 */
1393 1.5.2.2 christos ASSERT(zWidth > 0);
1394 1.5.2.2 christos
1395 1.5.2.2 christos return zWidth;
1396 1.5.2.2 christos }
1397 1.5.2.2 christos
1398 1.5.2.2 christos static void
1399 1.5.2.2 christos DeserializeLocation(char *pBuffer, size_t zBUfferLength, struct CSourceLocation *pLocation)
1400 1.5.2.2 christos {
1401 1.5.2.2 christos
1402 1.5.2.2 christos ASSERT(pLocation);
1403 1.5.2.2 christos ASSERT(pLocation->mFilename);
1404 1.5.2.2 christos
1405 1.5.2.2 christos snprintf(pBuffer, zBUfferLength, "%s:%" PRIu32 ":%" PRIu32, pLocation->mFilename, pLocation->mLine & (uint32_t)~ACK_REPORTED, pLocation->mColumn);
1406 1.5.2.2 christos }
1407 1.5.2.2 christos
1408 1.5.2.2 christos #ifdef __SIZEOF_INT128__
1409 1.5.2.2 christos static void
1410 1.5.2.2 christos DeserializeUINT128(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, __uint128_t U128)
1411 1.5.2.2 christos {
1412 1.5.2.2 christos char szBuf[3]; /* 'XX\0' */
1413 1.5.2.2 christos char rgNumber[sizeof(ulongest)];
1414 1.5.2.2 christos ssize_t zI;
1415 1.5.2.2 christos
1416 1.5.2.2 christos memcpy(rgNumber, &U128, sizeof(U128));
1417 1.5.2.2 christos
1418 1.5.2.2 christos strlcpy(pBuffer, "Undecoded-128-bit-Integer-Type (0x", zBUfferLength);
1419 1.5.2.2 christos #if BYTE_ORDER == LITTLE_ENDIAN
1420 1.5.2.2 christos for (zI = sizeof(ulongest) - 1; zI >= 0; zI--) {
1421 1.5.2.2 christos #else
1422 1.5.2.2 christos for (zI = 0; zI < (ssize_t)sizeof(ulongest); zI++) {
1423 1.5.2.2 christos #endif
1424 1.5.2.2 christos snprintf(szBuf, sizeof(szBuf), "%02" PRIx8, rgNumber[zI]);
1425 1.5.2.2 christos strlcat(pBuffer, szBuf, zBUfferLength);
1426 1.5.2.2 christos }
1427 1.5.2.2 christos strlcat(pBuffer, ")", zBUfferLength);
1428 1.5.2.2 christos }
1429 1.5.2.2 christos #endif
1430 1.5.2.2 christos
1431 1.5.2.2 christos static void
1432 1.5.2.2 christos DeserializeNumberSigned(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, longest L)
1433 1.5.2.2 christos {
1434 1.5.2.2 christos
1435 1.5.2.2 christos ASSERT(pBuffer);
1436 1.5.2.2 christos ASSERT(zBUfferLength > 0);
1437 1.5.2.2 christos ASSERT(pType);
1438 1.5.2.2 christos ASSERT(ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT));
1439 1.5.2.2 christos
1440 1.5.2.2 christos switch (zDeserializeTypeWidth(pType)) {
1441 1.5.2.2 christos default:
1442 1.5.2.2 christos ASSERT(0 && "Invalid codepath");
1443 1.5.2.2 christos __unreachable();
1444 1.5.2.2 christos /* NOTREACHED */
1445 1.5.2.2 christos #ifdef __SIZEOF_INT128__
1446 1.5.2.2 christos case WIDTH_128:
1447 1.5.2.2 christos DeserializeUINT128(pBuffer, zBUfferLength, pType, STATIC_CAST(__uint128_t, L));
1448 1.5.2.2 christos break;
1449 1.5.2.2 christos #endif
1450 1.5.2.2 christos case WIDTH_64:
1451 1.5.2.2 christos /* FALLTHROUGH */
1452 1.5.2.2 christos case WIDTH_32:
1453 1.5.2.2 christos /* FALLTHROUGH */
1454 1.5.2.2 christos case WIDTH_16:
1455 1.5.2.2 christos /* FALLTHROUGH */
1456 1.5.2.2 christos case WIDTH_8:
1457 1.5.2.2 christos snprintf(pBuffer, zBUfferLength, "%" PRId64, STATIC_CAST(int64_t, L));
1458 1.5.2.2 christos break;
1459 1.5.2.2 christos }
1460 1.5.2.2 christos }
1461 1.5.2.2 christos
1462 1.5.2.2 christos static void
1463 1.5.2.2 christos DeserializeNumberUnsigned(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, ulongest L)
1464 1.5.2.2 christos {
1465 1.5.2.2 christos
1466 1.5.2.2 christos ASSERT(pBuffer);
1467 1.5.2.2 christos ASSERT(zBUfferLength > 0);
1468 1.5.2.2 christos ASSERT(pType);
1469 1.5.2.2 christos ASSERT(!ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT));
1470 1.5.2.2 christos
1471 1.5.2.2 christos switch (zDeserializeTypeWidth(pType)) {
1472 1.5.2.2 christos default:
1473 1.5.2.2 christos ASSERT(0 && "Invalid codepath");
1474 1.5.2.2 christos __unreachable();
1475 1.5.2.2 christos /* NOTREACHED */
1476 1.5.2.2 christos #ifdef __SIZEOF_INT128__
1477 1.5.2.2 christos case WIDTH_128:
1478 1.5.2.2 christos DeserializeUINT128(pBuffer, zBUfferLength, pType, STATIC_CAST(__uint128_t, L));
1479 1.5.2.2 christos break;
1480 1.5.2.2 christos #endif
1481 1.5.2.2 christos case WIDTH_64:
1482 1.5.2.2 christos /* FALLTHROUGH */
1483 1.5.2.2 christos case WIDTH_32:
1484 1.5.2.2 christos /* FALLTHROUGH */
1485 1.5.2.2 christos case WIDTH_16:
1486 1.5.2.2 christos /* FALLTHROUGH */
1487 1.5.2.2 christos case WIDTH_8:
1488 1.5.2.2 christos snprintf(pBuffer, zBUfferLength, "%" PRIu64, STATIC_CAST(uint64_t, L));
1489 1.5.2.2 christos break;
1490 1.5.2.2 christos }
1491 1.5.2.2 christos }
1492 1.5.2.2 christos
1493 1.5.2.2 christos #ifndef _KERNEL
1494 1.5.2.2 christos static void
1495 1.5.2.2 christos DeserializeFloatOverPointer(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long *pNumber)
1496 1.5.2.2 christos {
1497 1.5.2.2 christos double D;
1498 1.5.2.2 christos #ifdef __HAVE_LONG_DOUBLE
1499 1.5.2.2 christos long double LD;
1500 1.5.2.2 christos #endif
1501 1.5.2.2 christos
1502 1.5.2.2 christos ASSERT(pBuffer);
1503 1.5.2.2 christos ASSERT(zBUfferLength > 0);
1504 1.5.2.2 christos ASSERT(pType);
1505 1.5.2.2 christos ASSERT(pNumber);
1506 1.5.2.2 christos /*
1507 1.5.2.2 christos * This function handles 64-bit number over a pointer on 32-bit CPUs.
1508 1.5.2.2 christos */
1509 1.5.2.2 christos ASSERT((sizeof(*pNumber) * CHAR_BIT < WIDTH_64) || (zDeserializeTypeWidth(pType) >= WIDTH_64));
1510 1.5.2.2 christos ASSERT(sizeof(D) == sizeof(uint64_t));
1511 1.5.2.2 christos #ifdef __HAVE_LONG_DOUBLE
1512 1.5.2.2 christos ASSERT(sizeof(LD) > sizeof(uint64_t));
1513 1.5.2.2 christos #endif
1514 1.5.2.2 christos
1515 1.5.2.2 christos switch (zDeserializeTypeWidth(pType)) {
1516 1.5.2.2 christos #ifdef __HAVE_LONG_DOUBLE
1517 1.5.2.2 christos case WIDTH_128:
1518 1.5.2.2 christos /* FALLTHROUGH */
1519 1.5.2.2 christos case WIDTH_96:
1520 1.5.2.2 christos /* FALLTHROUGH */
1521 1.5.2.2 christos case WIDTH_80:
1522 1.5.2.2 christos memcpy(&LD, pNumber, sizeof(long double));
1523 1.5.2.2 christos snprintf(pBuffer, zBUfferLength, "%Lg", LD);
1524 1.5.2.2 christos break;
1525 1.5.2.2 christos #endif
1526 1.5.2.2 christos case WIDTH_64:
1527 1.5.2.2 christos memcpy(&D, pNumber, sizeof(double));
1528 1.5.2.2 christos snprintf(pBuffer, zBUfferLength, "%g", D);
1529 1.5.2.2 christos break;
1530 1.5.2.2 christos }
1531 1.5.2.2 christos }
1532 1.5.2.2 christos
1533 1.5.2.2 christos static void
1534 1.5.2.2 christos DeserializeFloatInlined(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber)
1535 1.5.2.2 christos {
1536 1.5.2.2 christos float F;
1537 1.5.2.2 christos double D;
1538 1.5.2.2 christos uint32_t U32;
1539 1.5.2.2 christos
1540 1.5.2.2 christos ASSERT(pBuffer);
1541 1.5.2.2 christos ASSERT(zBUfferLength > 0);
1542 1.5.2.2 christos ASSERT(pType);
1543 1.5.2.2 christos ASSERT(sizeof(F) == sizeof(uint32_t));
1544 1.5.2.2 christos ASSERT(sizeof(D) == sizeof(uint64_t));
1545 1.5.2.2 christos
1546 1.5.2.2 christos switch (zDeserializeTypeWidth(pType)) {
1547 1.5.2.2 christos case WIDTH_64:
1548 1.5.2.3 martin ASSERT(sizeof(D) == sizeof(ulNumber));
1549 1.5.2.3 martin memcpy(&D, &ulNumber, sizeof(ulNumber));
1550 1.5.2.2 christos snprintf(pBuffer, zBUfferLength, "%g", D);
1551 1.5.2.2 christos break;
1552 1.5.2.2 christos case WIDTH_32:
1553 1.5.2.2 christos /*
1554 1.5.2.2 christos * On supported platforms sizeof(float)==sizeof(uint32_t)
1555 1.5.2.2 christos * unsigned long is either 32 or 64-bit, cast it to 32-bit
1556 1.5.2.2 christos * value in order to call memcpy(3) in an Endian-aware way.
1557 1.5.2.2 christos */
1558 1.5.2.2 christos U32 = STATIC_CAST(uint32_t, ulNumber);
1559 1.5.2.2 christos memcpy(&F, &U32, sizeof(float));
1560 1.5.2.2 christos snprintf(pBuffer, zBUfferLength, "%g", F);
1561 1.5.2.2 christos break;
1562 1.5.2.2 christos case WIDTH_16:
1563 1.5.2.2 christos snprintf(pBuffer, zBUfferLength, "Undecoded-16-bit-Floating-Type (%#04" PRIx16 ")", STATIC_CAST(uint16_t, ulNumber));
1564 1.5.2.2 christos break;
1565 1.5.2.2 christos }
1566 1.5.2.2 christos }
1567 1.5.2.2 christos #endif
1568 1.5.2.2 christos
1569 1.5.2.2 christos static longest
1570 1.5.2.2 christos llliGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber)
1571 1.5.2.2 christos {
1572 1.5.2.2 christos size_t zNumberWidth;
1573 1.5.2.2 christos longest L = 0;
1574 1.5.2.2 christos
1575 1.5.2.2 christos ASSERT(szLocation);
1576 1.5.2.2 christos ASSERT(pType);
1577 1.5.2.2 christos
1578 1.5.2.2 christos zNumberWidth = zDeserializeTypeWidth(pType);
1579 1.5.2.2 christos switch (zNumberWidth) {
1580 1.5.2.2 christos default:
1581 1.5.2.2 christos Report(true, "UBSan: Unexpected %zu-Bit Type in %s\n", zNumberWidth, szLocation);
1582 1.5.2.2 christos __unreachable();
1583 1.5.2.2 christos /* NOTREACHED */
1584 1.5.2.2 christos case WIDTH_128:
1585 1.5.2.2 christos #ifdef __SIZEOF_INT128__
1586 1.5.2.2 christos memcpy(&L, REINTERPRET_CAST(longest *, ulNumber), sizeof(longest));
1587 1.5.2.2 christos break;
1588 1.5.2.2 christos #else
1589 1.5.2.2 christos Report(true, "UBSan: Unexpected 128-Bit Type in %s\n", szLocation);
1590 1.5.2.2 christos __unreachable();
1591 1.5.2.2 christos /* NOTREACHED */
1592 1.5.2.2 christos #endif
1593 1.5.2.2 christos case WIDTH_64:
1594 1.5.2.2 christos if (sizeof(ulNumber) * CHAR_BIT < WIDTH_64) {
1595 1.5.2.2 christos L = *REINTERPRET_CAST(int64_t *, ulNumber);
1596 1.5.2.2 christos } else {
1597 1.5.2.2 christos L = STATIC_CAST(int64_t, STATIC_CAST(uint64_t, ulNumber));
1598 1.5.2.2 christos }
1599 1.5.2.2 christos break;
1600 1.5.2.2 christos case WIDTH_32:
1601 1.5.2.2 christos L = STATIC_CAST(int32_t, STATIC_CAST(uint32_t, ulNumber));
1602 1.5.2.2 christos break;
1603 1.5.2.2 christos case WIDTH_16:
1604 1.5.2.2 christos L = STATIC_CAST(int16_t, STATIC_CAST(uint16_t, ulNumber));
1605 1.5.2.2 christos break;
1606 1.5.2.2 christos case WIDTH_8:
1607 1.5.2.2 christos L = STATIC_CAST(int8_t, STATIC_CAST(uint8_t, ulNumber));
1608 1.5.2.2 christos break;
1609 1.5.2.2 christos }
1610 1.5.2.2 christos
1611 1.5.2.2 christos return L;
1612 1.5.2.2 christos }
1613 1.5.2.2 christos
1614 1.5.2.2 christos static ulongest
1615 1.5.2.2 christos llluGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber)
1616 1.5.2.2 christos {
1617 1.5.2.2 christos size_t zNumberWidth;
1618 1.5.2.2 christos ulongest UL = 0;
1619 1.5.2.2 christos
1620 1.5.2.2 christos ASSERT(pType);
1621 1.5.2.2 christos
1622 1.5.2.2 christos zNumberWidth = zDeserializeTypeWidth(pType);
1623 1.5.2.2 christos switch (zNumberWidth) {
1624 1.5.2.2 christos default:
1625 1.5.2.2 christos Report(true, "UBSan: Unexpected %zu-Bit Type in %s\n", zNumberWidth, szLocation);
1626 1.5.2.2 christos __unreachable();
1627 1.5.2.2 christos /* NOTREACHED */
1628 1.5.2.2 christos case WIDTH_128:
1629 1.5.2.2 christos #ifdef __SIZEOF_INT128__
1630 1.5.2.2 christos memcpy(&UL, REINTERPRET_CAST(ulongest *, ulNumber), sizeof(ulongest));
1631 1.5.2.2 christos break;
1632 1.5.2.2 christos #else
1633 1.5.2.2 christos Report(true, "UBSan: Unexpected 128-Bit Type in %s\n", szLocation);
1634 1.5.2.2 christos __unreachable();
1635 1.5.2.2 christos /* NOTREACHED */
1636 1.5.2.2 christos #endif
1637 1.5.2.2 christos case WIDTH_64:
1638 1.5.2.2 christos if (sizeof(ulNumber) * CHAR_BIT < WIDTH_64) {
1639 1.5.2.2 christos UL = *REINTERPRET_CAST(uint64_t *, ulNumber);
1640 1.5.2.2 christos break;
1641 1.5.2.2 christos }
1642 1.5.2.2 christos /* FALLTHROUGH */
1643 1.5.2.2 christos case WIDTH_32:
1644 1.5.2.2 christos /* FALLTHROUGH */
1645 1.5.2.2 christos case WIDTH_16:
1646 1.5.2.2 christos /* FALLTHROUGH */
1647 1.5.2.2 christos case WIDTH_8:
1648 1.5.2.2 christos UL = ulNumber;
1649 1.5.2.2 christos break;
1650 1.5.2.2 christos }
1651 1.5.2.2 christos
1652 1.5.2.2 christos return UL;
1653 1.5.2.2 christos }
1654 1.5.2.2 christos
1655 1.5.2.2 christos #ifndef _KERNEL
1656 1.5.2.2 christos static void
1657 1.5.2.2 christos DeserializeNumberFloat(char *szLocation, char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber)
1658 1.5.2.2 christos {
1659 1.5.2.2 christos size_t zNumberWidth;
1660 1.5.2.2 christos
1661 1.5.2.2 christos ASSERT(szLocation);
1662 1.5.2.2 christos ASSERT(pBuffer);
1663 1.5.2.2 christos ASSERT(zBUfferLength > 0);
1664 1.5.2.2 christos ASSERT(pType);
1665 1.5.2.2 christos ASSERT(pType->mTypeKind == KIND_FLOAT);
1666 1.5.2.2 christos
1667 1.5.2.2 christos zNumberWidth = zDeserializeTypeWidth(pType);
1668 1.5.2.2 christos switch (zNumberWidth) {
1669 1.5.2.2 christos default:
1670 1.5.2.2 christos Report(true, "UBSan: Unexpected %zu-Bit Type in %s\n", zNumberWidth, szLocation);
1671 1.5.2.2 christos __unreachable();
1672 1.5.2.2 christos /* NOTREACHED */
1673 1.5.2.2 christos #ifdef __HAVE_LONG_DOUBLE
1674 1.5.2.2 christos case WIDTH_128:
1675 1.5.2.2 christos /* FALLTHROUGH */
1676 1.5.2.2 christos case WIDTH_96:
1677 1.5.2.2 christos /* FALLTHROUGH */
1678 1.5.2.2 christos case WIDTH_80:
1679 1.5.2.2 christos DeserializeFloatOverPointer(pBuffer, zBUfferLength, pType, REINTERPRET_CAST(unsigned long *, ulNumber));
1680 1.5.2.2 christos break;
1681 1.5.2.2 christos #endif
1682 1.5.2.2 christos case WIDTH_64:
1683 1.5.2.2 christos if (sizeof(ulNumber) * CHAR_BIT < WIDTH_64) {
1684 1.5.2.2 christos DeserializeFloatOverPointer(pBuffer, zBUfferLength, pType, REINTERPRET_CAST(unsigned long *, ulNumber));
1685 1.5.2.2 christos break;
1686 1.5.2.2 christos }
1687 1.5.2.2 christos /* FALLTHROUGH */
1688 1.5.2.2 christos case WIDTH_32:
1689 1.5.2.2 christos /* FALLTHROUGH */
1690 1.5.2.2 christos case WIDTH_16:
1691 1.5.2.2 christos DeserializeFloatInlined(pBuffer, zBUfferLength, pType, ulNumber);
1692 1.5.2.2 christos break;
1693 1.5.2.2 christos }
1694 1.5.2.2 christos }
1695 1.5.2.2 christos #endif
1696 1.5.2.2 christos
1697 1.5.2.2 christos static void
1698 1.5.2.2 christos DeserializeNumber(char *szLocation, char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber)
1699 1.5.2.2 christos {
1700 1.5.2.2 christos
1701 1.5.2.2 christos ASSERT(szLocation);
1702 1.5.2.2 christos ASSERT(pBuffer);
1703 1.5.2.2 christos ASSERT(zBUfferLength > 0);
1704 1.5.2.2 christos ASSERT(pType);
1705 1.5.2.2 christos
1706 1.5.2.2 christos switch(pType->mTypeKind) {
1707 1.5.2.2 christos case KIND_INTEGER:
1708 1.5.2.2 christos if (ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT)) {
1709 1.5.2.2 christos longest L = llliGetNumber(szLocation, pType, ulNumber);
1710 1.5.2.2 christos DeserializeNumberSigned(pBuffer, zBUfferLength, pType, L);
1711 1.5.2.2 christos } else {
1712 1.5.2.2 christos ulongest UL = llluGetNumber(szLocation, pType, ulNumber);
1713 1.5.2.2 christos DeserializeNumberUnsigned(pBuffer, zBUfferLength, pType, UL);
1714 1.5.2.2 christos }
1715 1.5.2.2 christos break;
1716 1.5.2.2 christos case KIND_FLOAT:
1717 1.5.2.2 christos #ifdef _KERNEL
1718 1.5.2.2 christos Report(true, "UBSan: Unexpected Float Type in %s\n", szLocation);
1719 1.5.2.2 christos __unreachable();
1720 1.5.2.2 christos /* NOTREACHED */
1721 1.5.2.2 christos #else
1722 1.5.2.2 christos DeserializeNumberFloat(szLocation, pBuffer, zBUfferLength, pType, ulNumber);
1723 1.5.2.2 christos break;
1724 1.5.2.2 christos #endif
1725 1.5.2.2 christos case KIND_UNKNOWN:
1726 1.5.2.2 christos Report(true, "UBSan: Unknown Type in %s\n", szLocation);
1727 1.5.2.2 christos __unreachable();
1728 1.5.2.2 christos /* NOTREACHED */
1729 1.5.2.2 christos }
1730 1.5.2.2 christos }
1731 1.5.2.2 christos
1732 1.5.2.2 christos static const char *
1733 1.5.2.2 christos DeserializeTypeCheckKind(uint8_t hhuTypeCheckKind)
1734 1.5.2.2 christos {
1735 1.5.2.2 christos const char *rgczTypeCheckKinds[] = {
1736 1.5.2.2 christos "load of",
1737 1.5.2.2 christos "store to",
1738 1.5.2.2 christos "reference binding to",
1739 1.5.2.2 christos "member access within",
1740 1.5.2.2 christos "member call on",
1741 1.5.2.2 christos "constructor call on",
1742 1.5.2.2 christos "downcast of",
1743 1.5.2.2 christos "downcast of",
1744 1.5.2.2 christos "upcast of",
1745 1.5.2.2 christos "cast to virtual base of",
1746 1.5.2.2 christos "_Nonnull binding to",
1747 1.5.2.2 christos "dynamic operation on"
1748 1.5.2.2 christos };
1749 1.5.2.2 christos
1750 1.5.2.2 christos ASSERT(__arraycount(rgczTypeCheckKinds) > hhuTypeCheckKind);
1751 1.5.2.2 christos
1752 1.5.2.2 christos return rgczTypeCheckKinds[hhuTypeCheckKind];
1753 1.5.2.2 christos }
1754 1.5.2.2 christos
1755 1.5.2.2 christos static const char *
1756 1.5.2.2 christos DeserializeBuiltinCheckKind(uint8_t hhuBuiltinCheckKind)
1757 1.5.2.2 christos {
1758 1.5.2.2 christos const char *rgczBuiltinCheckKinds[] = {
1759 1.5.2.2 christos "ctz()",
1760 1.5.2.2 christos "clz()"
1761 1.5.2.2 christos };
1762 1.5.2.2 christos
1763 1.5.2.2 christos ASSERT(__arraycount(rgczBuiltinCheckKinds) > hhuBuiltinCheckKind);
1764 1.5.2.2 christos
1765 1.5.2.2 christos return rgczBuiltinCheckKinds[hhuBuiltinCheckKind];
1766 1.5.2.2 christos }
1767 1.5.2.2 christos
1768 1.5.2.2 christos static const char *
1769 1.5.2.2 christos DeserializeCFICheckKind(uint8_t hhuCFICheckKind)
1770 1.5.2.2 christos {
1771 1.5.2.2 christos const char *rgczCFICheckKinds[] = {
1772 1.5.2.2 christos "virtual call", // CFI_VCALL
1773 1.5.2.2 christos "non-virtual call", // CFI_NVCALL
1774 1.5.2.2 christos "base-to-derived cast", // CFI_DERIVEDCAST
1775 1.5.2.2 christos "cast to unrelated type", // CFI_UNRELATEDCAST
1776 1.5.2.2 christos "indirect function call", // CFI_ICALL
1777 1.5.2.2 christos "non-virtual pointer to member function call", // CFI_NVMFCALL
1778 1.5.2.2 christos "virtual pointer to member function call", // CFI_VMFCALL
1779 1.5.2.2 christos };
1780 1.5.2.2 christos
1781 1.5.2.2 christos ASSERT(__arraycount(rgczCFICheckKinds) > hhuCFICheckKind);
1782 1.5.2.2 christos
1783 1.5.2.2 christos return rgczCFICheckKinds[hhuCFICheckKind];
1784 1.5.2.2 christos }
1785 1.5.2.2 christos
1786 1.5.2.3 martin static const char *
1787 1.5.2.3 martin DeserializeImplicitConversionCheckKind(uint8_t hhuImplicitConversionCheckKind)
1788 1.5.2.3 martin {
1789 1.5.2.3 martin const char *rgczImplicitConversionCheckKind[] = {
1790 1.5.2.3 martin "integer truncation", /* Not used since 2018 October 11th */
1791 1.5.2.3 martin "unsigned integer truncation",
1792 1.5.2.3 martin "signed integer truncation",
1793 1.5.2.3 martin "integer sign change",
1794 1.5.2.3 martin "signed integer trunctation or sign change",
1795 1.5.2.3 martin };
1796 1.5.2.3 martin
1797 1.5.2.3 martin ASSERT(__arraycount(rgczImplicitConversionCheckKind) > hhuImplicitConversionCheckKind);
1798 1.5.2.3 martin
1799 1.5.2.3 martin return rgczImplicitConversionCheckKind[hhuImplicitConversionCheckKind];
1800 1.5.2.3 martin }
1801 1.5.2.3 martin
1802 1.5.2.2 christos static bool
1803 1.5.2.2 christos isNegativeNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber)
1804 1.5.2.2 christos {
1805 1.5.2.2 christos
1806 1.5.2.2 christos ASSERT(szLocation);
1807 1.5.2.2 christos ASSERT(pType);
1808 1.5.2.2 christos ASSERT(pType->mTypeKind == KIND_INTEGER);
1809 1.5.2.2 christos
1810 1.5.2.2 christos if (!ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT))
1811 1.5.2.2 christos return false;
1812 1.5.2.2 christos
1813 1.5.2.2 christos return llliGetNumber(szLocation, pType, ulNumber) < 0;
1814 1.5.2.2 christos }
1815 1.5.2.2 christos
1816 1.5.2.2 christos static bool
1817 1.5.2.2 christos isShiftExponentTooLarge(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber, size_t zWidth)
1818 1.5.2.2 christos {
1819 1.5.2.2 christos
1820 1.5.2.2 christos ASSERT(szLocation);
1821 1.5.2.2 christos ASSERT(pType);
1822 1.5.2.2 christos ASSERT(pType->mTypeKind == KIND_INTEGER);
1823 1.5.2.2 christos
1824 1.5.2.2 christos return llluGetNumber(szLocation, pType, ulNumber) >= zWidth;
1825 1.5.2.2 christos }
1826