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