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