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