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