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