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