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