Home | History | Annotate | Line # | Download | only in misc
ubsan.c revision 1.2
      1 /*	$NetBSD: ubsan.c,v 1.2 2018/08/03 03:12:32 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.2 2018/08/03 03:12:32 kamil Exp $");
     42 #else
     43 __RCSID("$NetBSD: ubsan.c,v 1.2 2018/08/03 03:12:32 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 #if __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 		/* NOTREACHED */
   1196 	}
   1197 #endif
   1198 	va_end(ap);
   1199 }
   1200 
   1201 static bool
   1202 isAlreadyReported(struct CSourceLocation *pLocation)
   1203 {
   1204 	/*
   1205 	 * This code is shared between libc, kernel and standalone usage.
   1206 	 * It shall work in early bootstrap phase of both of them.
   1207 	 */
   1208 
   1209 	uint32_t siOldValue;
   1210 	volatile uint32_t *pLine;
   1211 
   1212 	ASSERT(pLocation);
   1213 
   1214 	pLine = &pLocation->mLine;
   1215 
   1216 	do {
   1217 		siOldValue = *pLine;
   1218 	} while (__sync_val_compare_and_swap(pLine, siOldValue, siOldValue | ACK_REPORTED) != siOldValue);
   1219 
   1220 	return ISSET(siOldValue, ACK_REPORTED);
   1221 }
   1222 
   1223 static size_t
   1224 zDeserializeTypeWidth(struct CTypeDescriptor *pType)
   1225 {
   1226 	size_t zWidth = 0;
   1227 
   1228 	ASSERT(pType);
   1229 
   1230 	switch (pType->mTypeKind) {
   1231 	case KIND_INTEGER:
   1232 		zWidth = __BIT(__SHIFTOUT(pType->mTypeInfo, ~NUMBER_SIGNED_BIT));
   1233 		break;
   1234 	case KIND_FLOAT:
   1235 		zWidth = pType->mTypeInfo;
   1236 		break;
   1237 	default:
   1238 		Report(true, "UBSan: Unknown variable type %#04" PRIx16 "\n", pType->mTypeKind);
   1239 		/* NOTREACHED */
   1240 	}
   1241 
   1242 	/* Invalid width will be transformed to 0 */
   1243 	ASSERT(zWidth > 0);
   1244 
   1245 	return zWidth;
   1246 }
   1247 
   1248 static void
   1249 DeserializeLocation(char *pBuffer, size_t zBUfferLength, struct CSourceLocation *pLocation)
   1250 {
   1251 
   1252 	ASSERT(pLocation);
   1253 	ASSERT(pLocation->mFilename);
   1254 
   1255 	snprintf(pBuffer, zBUfferLength, "%s:%" PRIu32 ":%" PRIu32, pLocation->mFilename, pLocation->mLine & (uint32_t)~ACK_REPORTED, pLocation->mColumn);
   1256 }
   1257 
   1258 #ifdef __SIZEOF_INT128__
   1259 static void
   1260 DeserializeUINT128(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, __uint128_t U128)
   1261 {
   1262 	char szBuf[3]; /* 'XX\0' */
   1263 	char rgNumber[sizeof(ulongest)];
   1264 	ssize_t zI;
   1265 
   1266 	memcpy(rgNumber, &U128, sizeof(U128));
   1267 
   1268 	strlcpy(pBuffer, "Undecoded-128-bit-Integer-Type (0x", zBUfferLength);
   1269 #if BYTE_ORDER == LITTLE_ENDIAN
   1270 	for (zI = sizeof(ulongest) - 1; zI >= 0; zI--) {
   1271 #else
   1272 	for (zI = 0; zI < sizeof(ulongest); zI++) {
   1273 #endif
   1274 		snprintf(szBuf, sizeof(szBuf), "%02" PRIx8, rgNumber[zI]);
   1275 		strlcat(pBuffer, szBuf, zBUfferLength);
   1276 	}
   1277 	strlcat(pBuffer, ")", zBUfferLength);
   1278 }
   1279 #endif
   1280 
   1281 static void
   1282 DeserializeNumberSigned(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, longest L)
   1283 {
   1284 
   1285 	ASSERT(pBuffer);
   1286 	ASSERT(zBUfferLength > 0);
   1287 	ASSERT(pType);
   1288 	ASSERT(ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT));
   1289 
   1290 	switch (zDeserializeTypeWidth(pType)) {
   1291 	default:
   1292 		ASSERT(0 && "Invalid codepath");
   1293 		/* NOTREACHED */
   1294 #ifdef __SIZEOF_INT128__
   1295 	case WIDTH_128:
   1296 		DeserializeUINT128(pBuffer, zBUfferLength, pType, STATIC_CAST(__uint128_t, L));
   1297 		break;
   1298 #endif
   1299 	case WIDTH_64:
   1300 	case WIDTH_32:
   1301 	case WIDTH_16:
   1302 	case WIDTH_8:
   1303 		snprintf(pBuffer, zBUfferLength, "%" PRId64, STATIC_CAST(int64_t, L));
   1304 		break;
   1305 	}
   1306 }
   1307 
   1308 static void
   1309 DeserializeNumberUnsigned(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, ulongest L)
   1310 {
   1311 
   1312 	ASSERT(pBuffer);
   1313 	ASSERT(zBUfferLength > 0);
   1314 	ASSERT(pType);
   1315 	ASSERT(!ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT));
   1316 
   1317 	switch (zDeserializeTypeWidth(pType)) {
   1318 	default:
   1319 		ASSERT(0 && "Invalid codepath");
   1320 		/* NOTREACHED */
   1321 #ifdef __SIZEOF_INT128__
   1322 	case WIDTH_128:
   1323 		DeserializeUINT128(pBuffer, zBUfferLength, pType, STATIC_CAST(__uint128_t, L));
   1324 		break;
   1325 #endif
   1326 	case WIDTH_64:
   1327 	case WIDTH_32:
   1328 	case WIDTH_16:
   1329 	case WIDTH_8:
   1330 		snprintf(pBuffer, zBUfferLength, "%" PRIu64, STATIC_CAST(uint64_t, L));
   1331 		break;
   1332 	}
   1333 }
   1334 
   1335 #ifndef _KERNEL
   1336 static void
   1337 DeserializeFloatOverPointer(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long *pNumber)
   1338 {
   1339 	double D;
   1340 #ifdef __HAVE_LONG_DOUBLE
   1341 	long double LD;
   1342 #endif
   1343 
   1344 	ASSERT(pBuffer);
   1345 	ASSERT(zBUfferLength > 0);
   1346 	ASSERT(pType);
   1347 	ASSERT(pNumber);
   1348 	/*
   1349 	 * This function handles 64-bit number over a pointer on 32-bit CPUs.
   1350 	 */
   1351 	ASSERT((sizeof(*pNumber) * CHAR_BIT < WIDTH_64) || (zDeserializeTypeWidth(pType) >= WIDTH_64));
   1352 	ASSERT(sizeof(D) == sizeof(uint64_t));
   1353 #ifdef __HAVE_LONG_DOUBLE
   1354 	ASSERT(sizeof(LD) > sizeof(uint64_t));
   1355 #endif
   1356 
   1357 	switch (zDeserializeTypeWidth(pType)) {
   1358 #ifdef __HAVE_LONG_DOUBLE
   1359 	case WIDTH_128:
   1360 	case WIDTH_96:
   1361 	case WIDTH_80:
   1362 		memcpy(&LD, pNumber, sizeof(long double));
   1363 		snprintf(pBuffer, zBUfferLength, "%Lg", LD);
   1364 		break;
   1365 #endif
   1366 	case WIDTH_64:
   1367 		memcpy(&D, pNumber, sizeof(double));
   1368 		snprintf(pBuffer, zBUfferLength, "%g", D);
   1369 		break;
   1370 	}
   1371 }
   1372 
   1373 static void
   1374 DeserializeFloatInlined(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber)
   1375 {
   1376 	float F;
   1377 	double D;
   1378 	uint32_t U32;
   1379 
   1380 	ASSERT(pBuffer);
   1381 	ASSERT(zBUfferLength > 0);
   1382 	ASSERT(pType);
   1383 	ASSERT(sizeof(F) == sizeof(uint32_t));
   1384 	ASSERT(sizeof(D) == sizeof(uint64_t));
   1385 
   1386 	switch (zDeserializeTypeWidth(pType)) {
   1387 	case WIDTH_64:
   1388 		memcpy(&D, &ulNumber, sizeof(double));
   1389 		snprintf(pBuffer, zBUfferLength, "%g", D);
   1390 		break;
   1391 	case WIDTH_32:
   1392 		/*
   1393 		 * On supported platforms sizeof(float)==sizeof(uint32_t)
   1394 		 * unsigned long is either 32 or 64-bit, cast it to 32-bit
   1395 		 * value in order to call memcpy(3) in an Endian-aware way.
   1396 		 */
   1397 		U32 = STATIC_CAST(uint32_t, ulNumber);
   1398 		memcpy(&F, &U32, sizeof(float));
   1399 		snprintf(pBuffer, zBUfferLength, "%g", F);
   1400 		break;
   1401 	case WIDTH_16:
   1402 		snprintf(pBuffer, zBUfferLength, "Undecoded-16-bit-Floating-Type (%#04" PRIx16 ")", STATIC_CAST(uint16_t, ulNumber));
   1403 		break;
   1404 	}
   1405 }
   1406 #endif
   1407 
   1408 static longest
   1409 llliGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber)
   1410 {
   1411 	size_t zNumberWidth;
   1412 	longest L = 0;
   1413 
   1414 	ASSERT(szLocation);
   1415 	ASSERT(pType);
   1416 
   1417 	zNumberWidth = zDeserializeTypeWidth(pType);
   1418 	switch (zNumberWidth) {
   1419 	default:
   1420 		Report(true, "UBSan: Unexpected %zu-Bit Type in %s\n", zNumberWidth, szLocation);
   1421 		/* NOTREACHED */
   1422 	case WIDTH_128:
   1423 #ifdef __SIZEOF_INT128__
   1424 		memcpy(&L, REINTERPRET_CAST(longest *, ulNumber), sizeof(longest));
   1425 #else
   1426 		Report(true, "UBSan: Unexpected 128-Bit Type in %s\n", szLocation);
   1427 		/* NOTREACHED */
   1428 #endif
   1429 		break;
   1430 	case WIDTH_64:
   1431 		if (sizeof(ulNumber) * CHAR_BIT < WIDTH_64) {
   1432 			L = *REINTERPRET_CAST(int64_t *, ulNumber);
   1433 		} else {
   1434 			L = STATIC_CAST(int64_t, STATIC_CAST(uint64_t, ulNumber));
   1435 		}
   1436 		break;
   1437 	case WIDTH_32:
   1438 		L = STATIC_CAST(int32_t, STATIC_CAST(uint32_t, ulNumber));
   1439 		break;
   1440 	case WIDTH_16:
   1441 		L = STATIC_CAST(int16_t, STATIC_CAST(uint16_t, ulNumber));
   1442 		break;
   1443 	case WIDTH_8:
   1444 		L = STATIC_CAST(int8_t, STATIC_CAST(uint8_t, ulNumber));
   1445 		break;
   1446 	}
   1447 
   1448 	return L;
   1449 }
   1450 
   1451 static ulongest
   1452 llluGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber)
   1453 {
   1454 	size_t zNumberWidth;
   1455 	ulongest UL = 0;
   1456 
   1457 	ASSERT(pType);
   1458 
   1459 	zNumberWidth = zDeserializeTypeWidth(pType);
   1460 	switch (zNumberWidth) {
   1461 	default:
   1462 		Report(true, "UBSan: Unexpected %zu-Bit Type in %s\n", zNumberWidth, szLocation);
   1463 		/* NOTREACHED */
   1464 	case WIDTH_128:
   1465 #ifdef __SIZEOF_INT128__
   1466 		memcpy(&UL, REINTERPRET_CAST(ulongest *, ulNumber), sizeof(ulongest));
   1467 		break;
   1468 #else
   1469 		Report(true, "UBSan: Unexpected 128-Bit Type in %s\n", szLocation);
   1470 		/* NOTREACHED */
   1471 #endif
   1472 	case WIDTH_64:
   1473 		if (sizeof(ulNumber) * CHAR_BIT < WIDTH_64) {
   1474 			UL = *REINTERPRET_CAST(uint64_t *, ulNumber);
   1475 			break;
   1476 		}
   1477 		/* FALLTHROUGH */
   1478 	case WIDTH_32:
   1479 		/* FALLTHROUGH */
   1480 	case WIDTH_16:
   1481 		/* FALLTHROUGH */
   1482 	case WIDTH_8:
   1483 		UL = ulNumber;
   1484 		break;
   1485 	}
   1486 
   1487 	return UL;
   1488 }
   1489 
   1490 #ifndef _KERNEL
   1491 static void
   1492 DeserializeNumberFloat(char *szLocation, char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber)
   1493 {
   1494 	size_t zNumberWidth;
   1495 
   1496 	ASSERT(szLocation);
   1497 	ASSERT(pBuffer);
   1498 	ASSERT(zBUfferLength > 0);
   1499 	ASSERT(pType);
   1500 	ASSERT(pType->mTypeKind == KIND_FLOAT);
   1501 
   1502 	zNumberWidth = zDeserializeTypeWidth(pType);
   1503 	switch (zNumberWidth) {
   1504 	default:
   1505 		Report(true, "UBSan: Unexpected %zu-Bit Type in %s\n", zNumberWidth, szLocation);
   1506 		/* NOTREACHED */
   1507 #ifdef __HAVE_LONG_DOUBLE
   1508 	case WIDTH_128:
   1509 	case WIDTH_96:
   1510 	case WIDTH_80:
   1511 		DeserializeFloatOverPointer(pBuffer, zBUfferLength, pType, REINTERPRET_CAST(unsigned long *, ulNumber));
   1512 		break;
   1513 #endif
   1514 	case WIDTH_64:
   1515 		if (sizeof(ulNumber) * CHAR_BIT < WIDTH_64) {
   1516 			DeserializeFloatOverPointer(pBuffer, zBUfferLength, pType, REINTERPRET_CAST(unsigned long *, ulNumber));
   1517 			break;
   1518 		}
   1519 	case WIDTH_32:
   1520 	case WIDTH_16:
   1521 		DeserializeFloatInlined(pBuffer, zBUfferLength, pType, ulNumber);
   1522 		break;
   1523 	}
   1524 }
   1525 #endif
   1526 
   1527 static void
   1528 DeserializeNumber(char *szLocation, char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber)
   1529 {
   1530 
   1531 	ASSERT(szLocation);
   1532 	ASSERT(pBuffer);
   1533 	ASSERT(zBUfferLength > 0);
   1534 	ASSERT(pType);
   1535 
   1536 	switch(pType->mTypeKind) {
   1537 	case KIND_INTEGER:
   1538 		if (ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT)) {
   1539 			longest L = llliGetNumber(szLocation, pType, ulNumber);
   1540 			DeserializeNumberSigned(pBuffer, zBUfferLength, pType, L);
   1541 		} else {
   1542 			ulongest UL = llluGetNumber(szLocation, pType, ulNumber);
   1543 			DeserializeNumberUnsigned(pBuffer, zBUfferLength, pType, UL);
   1544 		}
   1545 		break;
   1546 	case KIND_FLOAT:
   1547 #ifdef _KERNEL
   1548 		Report(true, "UBSan: Unexpected Float Type in %s\n", szLocation);
   1549 		/* NOTREACHED */
   1550 #else
   1551 		DeserializeNumberFloat(szLocation, pBuffer, zBUfferLength, pType, ulNumber);
   1552 #endif
   1553 		break;
   1554 	case KIND_UNKNOWN:
   1555 		Report(true, "UBSan: Unknown Type in %s\n", szLocation);
   1556 		/* NOTREACHED */
   1557 		break;
   1558 	}
   1559 }
   1560 
   1561 static const char *
   1562 DeserializeTypeCheckKind(uint8_t hhuTypeCheckKind)
   1563 {
   1564 	const char *rgczTypeCheckKinds[] = {
   1565 		"load of",
   1566 		"store to",
   1567 		"reference binding to",
   1568 		"member access within",
   1569 		"member call on",
   1570 		"constructor call on",
   1571 		"downcast of",
   1572 		"downcast of",
   1573 		"upcast of",
   1574 		"cast to virtual base of",
   1575 		"_Nonnull binding to",
   1576 		"dynamic operation on"
   1577 	};
   1578 
   1579 	ASSERT(__arraycount(rgczTypeCheckKinds) > hhuTypeCheckKind);
   1580 
   1581 	return rgczTypeCheckKinds[hhuTypeCheckKind];
   1582 }
   1583 
   1584 static const char *
   1585 DeserializeBuiltinCheckKind(uint8_t hhuBuiltinCheckKind)
   1586 {
   1587 	const char *rgczBuiltinCheckKinds[] = {
   1588 		"ctz()",
   1589 		"clz()"
   1590 	};
   1591 
   1592 	ASSERT(__arraycount(rgczBuiltinCheckKinds) > hhuBuiltinCheckKind);
   1593 
   1594 	return rgczBuiltinCheckKinds[hhuBuiltinCheckKind];
   1595 }
   1596 
   1597 static const char *
   1598 DeserializeCFICheckKind(uint8_t hhuCFICheckKind)
   1599 {
   1600 	const char *rgczCFICheckKinds[] = {
   1601 		"virtual call",					// CFI_VCALL
   1602 		"non-virtual call",				// CFI_NVCALL
   1603 		"base-to-derived cast",				// CFI_DERIVEDCAST
   1604 		"cast to unrelated type",			// CFI_UNRELATEDCAST
   1605 		"indirect function call",			// CFI_ICALL
   1606 		"non-virtual pointer to member function call",	// CFI_NVMFCALL
   1607 		"virtual pointer to member function call",	// CFI_VMFCALL
   1608 	};
   1609 
   1610 	ASSERT(__arraycount(rgczCFICheckKinds) > hhuCFICheckKind);
   1611 
   1612 	return rgczCFICheckKinds[hhuCFICheckKind];
   1613 }
   1614 
   1615 static bool
   1616 isNegativeNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber)
   1617 {
   1618 
   1619 	ASSERT(szLocation);
   1620 	ASSERT(pType);
   1621 	ASSERT(pType->mTypeKind == KIND_INTEGER);
   1622 
   1623 	if (!ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT))
   1624 		return false;
   1625 
   1626 	return llliGetNumber(szLocation, pType, ulNumber) < 0;
   1627 }
   1628 
   1629 static bool
   1630 isShiftExponentTooLarge(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber, size_t zWidth)
   1631 {
   1632 
   1633 	ASSERT(szLocation);
   1634 	ASSERT(pType);
   1635 	ASSERT(pType->mTypeKind == KIND_INTEGER);
   1636 
   1637 	return llluGetNumber(szLocation, pType, ulNumber) >= zWidth;
   1638 }
   1639