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