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