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