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