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