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