xref: /netbsd-src/common/lib/libc/misc/ubsan.c (revision 84176bea914bbc4aba07ac90d280576c7a2439ea)
1*84176beaSandvar /*	$NetBSD: ubsan.c,v 1.12 2023/12/07 07:10:44 andvar Exp $	*/
29aff1076Skamil 
39aff1076Skamil /*-
49aff1076Skamil  * Copyright (c) 2018 The NetBSD Foundation, Inc.
59aff1076Skamil  * All rights reserved.
69aff1076Skamil  *
79aff1076Skamil  * Redistribution and use in source and binary forms, with or without
89aff1076Skamil  * modification, are permitted provided that the following conditions
99aff1076Skamil  * are met:
109aff1076Skamil  * 1. Redistributions of source code must retain the above copyright
119aff1076Skamil  *    notice, this list of conditions and the following disclaimer.
129aff1076Skamil  * 2. Redistributions in binary form must reproduce the above copyright
139aff1076Skamil  *    notice, this list of conditions and the following disclaimer in the
149aff1076Skamil  *    documentation and/or other materials provided with the distribution.
159aff1076Skamil  *
169aff1076Skamil  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
179aff1076Skamil  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
189aff1076Skamil  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
199aff1076Skamil  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
209aff1076Skamil  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
219aff1076Skamil  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
229aff1076Skamil  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
239aff1076Skamil  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
249aff1076Skamil  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
259aff1076Skamil  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
269aff1076Skamil  * POSSIBILITY OF SUCH DAMAGE.
279aff1076Skamil  */
289aff1076Skamil 
299aff1076Skamil 
309aff1076Skamil /*
319aff1076Skamil  * The micro UBSan implementation for the userland (uUBSan) and kernel (kUBSan).
329aff1076Skamil  * The uBSSan versions is suitable for inclusion into libc or used standalone
339aff1076Skamil  * with ATF tests.
349aff1076Skamil  *
35aee9a63fSkamil  * This file due to long symbol names generated by a compiler during the
36aee9a63fSkamil  * instrumentation process does not follow the KNF style with 80-column limit.
379aff1076Skamil  */
389aff1076Skamil 
399aff1076Skamil #include <sys/cdefs.h>
409aff1076Skamil #if defined(_KERNEL)
41*84176beaSandvar __KERNEL_RCSID(0, "$NetBSD: ubsan.c,v 1.12 2023/12/07 07:10:44 andvar Exp $");
429aff1076Skamil #else
43*84176beaSandvar __RCSID("$NetBSD: ubsan.c,v 1.12 2023/12/07 07:10:44 andvar Exp $");
449aff1076Skamil #endif
459aff1076Skamil 
469aff1076Skamil #if defined(_KERNEL)
479aff1076Skamil #include <sys/param.h>
489aff1076Skamil #include <sys/types.h>
499aff1076Skamil #include <sys/stdarg.h>
509aff1076Skamil #define ASSERT(x) KASSERT(x)
519aff1076Skamil #else
529aff1076Skamil #if defined(_LIBC)
539aff1076Skamil #include "namespace.h"
549aff1076Skamil #endif
559aff1076Skamil #include <sys/param.h>
569aff1076Skamil #include <assert.h>
579aff1076Skamil #include <inttypes.h>
589aff1076Skamil #include <math.h>
599aff1076Skamil #include <signal.h>
609aff1076Skamil #include <stdarg.h>
619aff1076Skamil #include <stdbool.h>
629aff1076Skamil #include <stdint.h>
639aff1076Skamil #include <stdio.h>
649aff1076Skamil #include <stdlib.h>
659aff1076Skamil #include <string.h>
669aff1076Skamil #include <syslog.h>
679aff1076Skamil #include <unistd.h>
689aff1076Skamil #if defined(_LIBC)
699aff1076Skamil #include "extern.h"
709aff1076Skamil #define ubsan_vsyslog vsyslog_ss
719aff1076Skamil #define ASSERT(x) _DIAGASSERT(x)
729aff1076Skamil #else
739aff1076Skamil #define ubsan_vsyslog vsyslog_r
749aff1076Skamil #define ASSERT(x) assert(x)
759aff1076Skamil #endif
769aff1076Skamil /* These macros are available in _KERNEL only */
779aff1076Skamil #define SET(t, f)	((t) |= (f))
789aff1076Skamil #define ISSET(t, f)	((t) & (f))
799aff1076Skamil #define CLR(t, f)	((t) &= ~(f))
809aff1076Skamil #endif
819aff1076Skamil 
82f8310280Skamil #ifdef UBSAN_ALWAYS_FATAL
83f8310280Skamil static const bool alwaysFatal = true;
84f8310280Skamil #else
85f8310280Skamil static const bool alwaysFatal = false;
86f8310280Skamil #endif
87f8310280Skamil 
889aff1076Skamil #define REINTERPRET_CAST(__dt, __st)	((__dt)(__st))
899aff1076Skamil #define STATIC_CAST(__dt, __st)		((__dt)(__st))
909aff1076Skamil 
919aff1076Skamil #define ACK_REPORTED	__BIT(31)
929aff1076Skamil 
939aff1076Skamil #define MUL_STRING	"*"
949aff1076Skamil #define PLUS_STRING	"+"
959aff1076Skamil #define MINUS_STRING	"-"
969aff1076Skamil #define DIVREM_STRING	"divrem"
979aff1076Skamil 
989aff1076Skamil #define CFI_VCALL		0
999aff1076Skamil #define CFI_NVCALL		1
1009aff1076Skamil #define CFI_DERIVEDCAST		2
1019aff1076Skamil #define CFI_UNRELATEDCAST	3
1029aff1076Skamil #define CFI_ICALL		4
1039aff1076Skamil #define CFI_NVMFCALL		5
1049aff1076Skamil #define CFI_VMFCALL		6
1059aff1076Skamil 
1069aff1076Skamil #define NUMBER_MAXLEN	128
1079aff1076Skamil #define LOCATION_MAXLEN	(PATH_MAX + 32 /* ':LINE:COLUMN' */)
1089aff1076Skamil 
1099aff1076Skamil #define WIDTH_8		8
1109aff1076Skamil #define WIDTH_16	16
1119aff1076Skamil #define WIDTH_32	32
1129aff1076Skamil #define WIDTH_64	64
1139aff1076Skamil #define WIDTH_80	80
1149aff1076Skamil #define WIDTH_96	96
1159aff1076Skamil #define WIDTH_128	128
1169aff1076Skamil 
1179aff1076Skamil #define NUMBER_SIGNED_BIT	1U
1189aff1076Skamil 
119075cfd7eSkamil #ifdef __SIZEOF_INT128__
1209aff1076Skamil typedef __int128 longest;
1219aff1076Skamil typedef unsigned __int128 ulongest;
1229aff1076Skamil #else
1239aff1076Skamil typedef int64_t longest;
1249aff1076Skamil typedef uint64_t ulongest;
1259aff1076Skamil #endif
1269aff1076Skamil 
1279aff1076Skamil #ifndef _KERNEL
1289aff1076Skamil static int ubsan_flags = -1;
1299aff1076Skamil #define UBSAN_ABORT	__BIT(0)
1309aff1076Skamil #define UBSAN_STDOUT	__BIT(1)
1319aff1076Skamil #define UBSAN_STDERR	__BIT(2)
1329aff1076Skamil #define UBSAN_SYSLOG	__BIT(3)
1339aff1076Skamil #endif
1349aff1076Skamil 
1359aff1076Skamil /* Undefined Behavior specific defines and structures */
1369aff1076Skamil 
1379aff1076Skamil #define KIND_INTEGER	0
1389aff1076Skamil #define KIND_FLOAT	1
1399aff1076Skamil #define KIND_UNKNOWN	UINT16_MAX
1409aff1076Skamil 
1419aff1076Skamil struct CSourceLocation {
1429aff1076Skamil 	char *mFilename;
1439aff1076Skamil 	uint32_t mLine;
1449aff1076Skamil 	uint32_t mColumn;
1459aff1076Skamil };
1469aff1076Skamil 
1479aff1076Skamil struct CTypeDescriptor {
1489aff1076Skamil 	uint16_t mTypeKind;
1499aff1076Skamil 	uint16_t mTypeInfo;
1509aff1076Skamil 	uint8_t mTypeName[1];
1519aff1076Skamil };
1529aff1076Skamil 
1539aff1076Skamil struct COverflowData {
1549aff1076Skamil 	struct CSourceLocation mLocation;
1559aff1076Skamil 	struct CTypeDescriptor *mType;
1569aff1076Skamil };
1579aff1076Skamil 
1589aff1076Skamil struct CUnreachableData {
1599aff1076Skamil 	struct CSourceLocation mLocation;
1609aff1076Skamil };
1619aff1076Skamil 
1629aff1076Skamil struct CCFICheckFailData {
1639aff1076Skamil 	uint8_t mCheckKind;
1649aff1076Skamil 	struct CSourceLocation mLocation;
1659aff1076Skamil 	struct CTypeDescriptor *mType;
1669aff1076Skamil };
1679aff1076Skamil 
1689aff1076Skamil struct CDynamicTypeCacheMissData {
1699aff1076Skamil 	struct CSourceLocation mLocation;
1709aff1076Skamil 	struct CTypeDescriptor *mType;
1719aff1076Skamil 	void *mTypeInfo;
1729aff1076Skamil 	uint8_t mTypeCheckKind;
1739aff1076Skamil };
1749aff1076Skamil 
1759aff1076Skamil struct CFunctionTypeMismatchData {
1769aff1076Skamil 	struct CSourceLocation mLocation;
1779aff1076Skamil 	struct CTypeDescriptor *mType;
1789aff1076Skamil };
1799aff1076Skamil 
1809aff1076Skamil struct CInvalidBuiltinData {
1819aff1076Skamil 	struct CSourceLocation mLocation;
1829aff1076Skamil 	uint8_t mKind;
1839aff1076Skamil };
1849aff1076Skamil 
1859aff1076Skamil struct CInvalidValueData {
1869aff1076Skamil 	struct CSourceLocation mLocation;
1879aff1076Skamil 	struct CTypeDescriptor *mType;
1889aff1076Skamil };
1899aff1076Skamil 
1909aff1076Skamil struct CNonNullArgData {
1919aff1076Skamil 	struct CSourceLocation mLocation;
1929aff1076Skamil 	struct CSourceLocation mAttributeLocation;
1939aff1076Skamil 	int mArgIndex;
1949aff1076Skamil };
1959aff1076Skamil 
1969aff1076Skamil struct CNonNullReturnData {
1979aff1076Skamil 	struct CSourceLocation mAttributeLocation;
1989aff1076Skamil };
1999aff1076Skamil 
2009aff1076Skamil struct COutOfBoundsData {
2019aff1076Skamil 	struct CSourceLocation mLocation;
2029aff1076Skamil 	struct CTypeDescriptor *mArrayType;
2039aff1076Skamil 	struct CTypeDescriptor *mIndexType;
2049aff1076Skamil };
2059aff1076Skamil 
2069aff1076Skamil struct CPointerOverflowData {
2079aff1076Skamil 	struct CSourceLocation mLocation;
2089aff1076Skamil };
2099aff1076Skamil 
2109aff1076Skamil struct CShiftOutOfBoundsData {
2119aff1076Skamil 	struct CSourceLocation mLocation;
2129aff1076Skamil 	struct CTypeDescriptor *mLHSType;
2139aff1076Skamil 	struct CTypeDescriptor *mRHSType;
2149aff1076Skamil };
2159aff1076Skamil 
2169aff1076Skamil struct CTypeMismatchData {
2179aff1076Skamil 	struct CSourceLocation mLocation;
2189aff1076Skamil 	struct CTypeDescriptor *mType;
2199aff1076Skamil 	unsigned long mLogAlignment;
2209aff1076Skamil 	uint8_t mTypeCheckKind;
2219aff1076Skamil };
2229aff1076Skamil 
2239aff1076Skamil struct CTypeMismatchData_v1 {
2249aff1076Skamil 	struct CSourceLocation mLocation;
2259aff1076Skamil 	struct CTypeDescriptor *mType;
2269aff1076Skamil 	uint8_t mLogAlignment;
2279aff1076Skamil 	uint8_t mTypeCheckKind;
2289aff1076Skamil };
2299aff1076Skamil 
2309aff1076Skamil struct CVLABoundData {
2319aff1076Skamil 	struct CSourceLocation mLocation;
2329aff1076Skamil 	struct CTypeDescriptor *mType;
2339aff1076Skamil };
2349aff1076Skamil 
2359aff1076Skamil struct CFloatCastOverflowData {
2369aff1076Skamil 	struct CSourceLocation mLocation;	/* This field exists in this struct since 2015 August 11th */
2379aff1076Skamil 	struct CTypeDescriptor *mFromType;
2389aff1076Skamil 	struct CTypeDescriptor *mToType;
2399aff1076Skamil };
2409aff1076Skamil 
241aeb81341Skamil struct CImplicitConversionData {
242aeb81341Skamil 	struct CSourceLocation mLocation;
243aeb81341Skamil 	struct CTypeDescriptor *mFromType;
244aeb81341Skamil 	struct CTypeDescriptor *mToType;
245aeb81341Skamil 	uint8_t mKind;
246aeb81341Skamil };
247aeb81341Skamil 
2487f5eec67Skamil struct CAlignmentAssumptionData {
2497f5eec67Skamil 	struct CSourceLocation mLocation;
2507f5eec67Skamil 	struct CSourceLocation mAssumptionLocation;
2517f5eec67Skamil 	struct CTypeDescriptor *mType;
2527f5eec67Skamil };
2537f5eec67Skamil 
2549aff1076Skamil /* Local utility functions */
2559aff1076Skamil static void Report(bool isFatal, const char *pFormat, ...) __printflike(2, 3);
2569aff1076Skamil static bool isAlreadyReported(struct CSourceLocation *pLocation);
2579aff1076Skamil static size_t zDeserializeTypeWidth(struct CTypeDescriptor *pType);
2589aff1076Skamil static void DeserializeLocation(char *pBuffer, size_t zBUfferLength, struct CSourceLocation *pLocation);
2599aff1076Skamil #ifdef __SIZEOF_INT128__
2609aff1076Skamil static void DeserializeUINT128(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, __uint128_t U128);
2619aff1076Skamil #endif
2629aff1076Skamil static void DeserializeNumberSigned(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, longest L);
2639aff1076Skamil static void DeserializeNumberUnsigned(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, ulongest L);
2649aff1076Skamil #ifndef _KERNEL
2659aff1076Skamil static void DeserializeFloatOverPointer(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long *pNumber);
2669aff1076Skamil static void DeserializeFloatInlined(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber);
2679aff1076Skamil #endif
2689aff1076Skamil static longest llliGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber);
2699aff1076Skamil static ulongest llluGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber);
2709aff1076Skamil #ifndef _KERNEL
2719aff1076Skamil static void DeserializeNumberFloat(char *szLocation, char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber);
2729aff1076Skamil #endif
2739aff1076Skamil static void DeserializeNumber(char *szLocation, char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber);
2749aff1076Skamil static const char *DeserializeTypeCheckKind(uint8_t hhuTypeCheckKind);
2759aff1076Skamil static const char *DeserializeBuiltinCheckKind(uint8_t hhuBuiltinCheckKind);
2769aff1076Skamil static const char *DeserializeCFICheckKind(uint8_t hhuCFICheckKind);
277aeb81341Skamil static const char *DeserializeImplicitConversionCheckKind(uint8_t hhuImplicitConversionCheckKind);
2789aff1076Skamil static bool isNegativeNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber);
2799aff1076Skamil static bool isShiftExponentTooLarge(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber, size_t zWidth);
2809aff1076Skamil 
2819aff1076Skamil /* Unused in this implementation, emitted by the C++ check dynamic type cast. */
2829aff1076Skamil intptr_t __ubsan_vptr_type_cache[128];
2839aff1076Skamil 
2849aff1076Skamil /* Public symbols used in the instrumentation of the code generation part */
2859aff1076Skamil void __ubsan_handle_add_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
2869aff1076Skamil void __ubsan_handle_add_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
2877f5eec67Skamil void __ubsan_handle_alignment_assumption(struct CAlignmentAssumptionData *pData, unsigned long ulPointer, unsigned long ulAlignment, unsigned long ulOffset);
2887f5eec67Skamil void __ubsan_handle_alignment_assumption_abort(struct CAlignmentAssumptionData *pData, unsigned long ulPointer, unsigned long ulAlignment, unsigned long ulOffset);
2899aff1076Skamil void __ubsan_handle_builtin_unreachable(struct CUnreachableData *pData);
2909aff1076Skamil void __ubsan_handle_cfi_bad_type(struct CCFICheckFailData *pData, unsigned long ulVtable, bool bValidVtable, bool FromUnrecoverableHandler, unsigned long ProgramCounter, unsigned long FramePointer);
2919aff1076Skamil void __ubsan_handle_cfi_check_fail(struct CCFICheckFailData *pData, unsigned long ulValue, unsigned long ulValidVtable);
2929aff1076Skamil void __ubsan_handle_cfi_check_fail_abort(struct CCFICheckFailData *pData, unsigned long ulValue, unsigned long ulValidVtable);
2939aff1076Skamil void __ubsan_handle_divrem_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
2949aff1076Skamil void __ubsan_handle_divrem_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
2959aff1076Skamil void __ubsan_handle_dynamic_type_cache_miss(struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash);
2969aff1076Skamil void __ubsan_handle_dynamic_type_cache_miss_abort(struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash);
2979aff1076Skamil void __ubsan_handle_float_cast_overflow(struct CFloatCastOverflowData *pData, unsigned long ulFrom);
2989aff1076Skamil void __ubsan_handle_float_cast_overflow_abort(struct CFloatCastOverflowData *pData, unsigned long ulFrom);
2999aff1076Skamil void __ubsan_handle_function_type_mismatch(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction);
3009aff1076Skamil void __ubsan_handle_function_type_mismatch_abort(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction);
3010b65214dSkamil void __ubsan_handle_function_type_mismatch_v1(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction, unsigned long ulCalleeRTTI, unsigned long ulFnRTTI);
3020b65214dSkamil void __ubsan_handle_function_type_mismatch_v1_abort(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction, unsigned long ulCalleeRTTI, unsigned long ulFnRTTI);
3039aff1076Skamil void __ubsan_handle_invalid_builtin(struct CInvalidBuiltinData *pData);
3049aff1076Skamil void __ubsan_handle_invalid_builtin_abort(struct CInvalidBuiltinData *pData);
3059aff1076Skamil void __ubsan_handle_load_invalid_value(struct CInvalidValueData *pData, unsigned long ulVal);
3069aff1076Skamil void __ubsan_handle_load_invalid_value_abort(struct CInvalidValueData *pData, unsigned long ulVal);
3079aff1076Skamil void __ubsan_handle_missing_return(struct CUnreachableData *pData);
3089aff1076Skamil void __ubsan_handle_mul_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
3099aff1076Skamil void __ubsan_handle_mul_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
3109aff1076Skamil void __ubsan_handle_negate_overflow(struct COverflowData *pData, unsigned long ulOldVal);
3119aff1076Skamil void __ubsan_handle_negate_overflow_abort(struct COverflowData *pData, unsigned long ulOldVal);
3129aff1076Skamil void __ubsan_handle_nonnull_arg(struct CNonNullArgData *pData);
3139aff1076Skamil void __ubsan_handle_nonnull_arg_abort(struct CNonNullArgData *pData);
3149aff1076Skamil void __ubsan_handle_nonnull_return_v1(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer);
3159aff1076Skamil void __ubsan_handle_nonnull_return_v1_abort(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer);
3169aff1076Skamil void __ubsan_handle_nullability_arg(struct CNonNullArgData *pData);
3179aff1076Skamil void __ubsan_handle_nullability_arg_abort(struct CNonNullArgData *pData);
3189aff1076Skamil void __ubsan_handle_nullability_return_v1(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer);
3199aff1076Skamil void __ubsan_handle_nullability_return_v1_abort(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer);
3209aff1076Skamil void __ubsan_handle_out_of_bounds(struct COutOfBoundsData *pData, unsigned long ulIndex);
3219aff1076Skamil void __ubsan_handle_out_of_bounds_abort(struct COutOfBoundsData *pData, unsigned long ulIndex);
3229aff1076Skamil void __ubsan_handle_pointer_overflow(struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult);
3239aff1076Skamil void __ubsan_handle_pointer_overflow_abort(struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult);
3249aff1076Skamil void __ubsan_handle_shift_out_of_bounds(struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS);
3259aff1076Skamil void __ubsan_handle_shift_out_of_bounds_abort(struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS);
3269aff1076Skamil void __ubsan_handle_sub_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
3279aff1076Skamil void __ubsan_handle_sub_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
3289aff1076Skamil void __ubsan_handle_type_mismatch(struct CTypeMismatchData *pData, unsigned long ulPointer);
3299aff1076Skamil void __ubsan_handle_type_mismatch_abort(struct CTypeMismatchData *pData, unsigned long ulPointer);
3309aff1076Skamil void __ubsan_handle_type_mismatch_v1(struct CTypeMismatchData_v1 *pData, unsigned long ulPointer);
3319aff1076Skamil void __ubsan_handle_type_mismatch_v1_abort(struct CTypeMismatchData_v1 *pData, unsigned long ulPointer);
3329aff1076Skamil void __ubsan_handle_vla_bound_not_positive(struct CVLABoundData *pData, unsigned long ulBound);
3339aff1076Skamil void __ubsan_handle_vla_bound_not_positive_abort(struct CVLABoundData *pData, unsigned long ulBound);
334aeb81341Skamil void __ubsan_handle_implicit_conversion(struct CImplicitConversionData *pData, unsigned long ulFrom, unsigned long ulTo);
335aeb81341Skamil void __ubsan_handle_implicit_conversion_abort(struct CImplicitConversionData *pData, unsigned long ulFrom, unsigned long ulTo);
3369aff1076Skamil void __ubsan_get_current_report_data(const char **ppOutIssueKind, const char **ppOutMessage, const char **ppOutFilename, uint32_t *pOutLine, uint32_t *pOutCol, char **ppOutMemoryAddr);
3379aff1076Skamil 
3389aff1076Skamil static void HandleOverflow(bool isFatal, struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS, const char *szOperation);
3399aff1076Skamil static void HandleNegateOverflow(bool isFatal, struct COverflowData *pData, unsigned long ulOldValue);
3409aff1076Skamil static void HandleBuiltinUnreachable(bool isFatal, struct CUnreachableData *pData);
3419aff1076Skamil static void HandleTypeMismatch(bool isFatal, struct CSourceLocation *mLocation, struct CTypeDescriptor *mType, unsigned long mLogAlignment, uint8_t mTypeCheckKind, unsigned long ulPointer);
3429aff1076Skamil static void HandleVlaBoundNotPositive(bool isFatal, struct CVLABoundData *pData, unsigned long ulBound);
3439aff1076Skamil static void HandleOutOfBounds(bool isFatal, struct COutOfBoundsData *pData, unsigned long ulIndex);
3449aff1076Skamil static void HandleShiftOutOfBounds(bool isFatal, struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS);
3459aff1076Skamil static void HandleLoadInvalidValue(bool isFatal, struct CInvalidValueData *pData, unsigned long ulValue);
3469aff1076Skamil static void HandleInvalidBuiltin(bool isFatal, struct CInvalidBuiltinData *pData);
3479aff1076Skamil static void HandleFunctionTypeMismatch(bool isFatal, struct CFunctionTypeMismatchData *pData, unsigned long ulFunction);
3489aff1076Skamil static void HandleCFIBadType(bool isFatal, struct CCFICheckFailData *pData, unsigned long ulVtable, bool *bValidVtable, bool *FromUnrecoverableHandler, unsigned long *ProgramCounter, unsigned long *FramePointer);
3499aff1076Skamil static void HandleDynamicTypeCacheMiss(bool isFatal, struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash);
3509aff1076Skamil static void HandleFloatCastOverflow(bool isFatal, struct CFloatCastOverflowData *pData, unsigned long ulFrom);
3519aff1076Skamil static void HandleMissingReturn(bool isFatal, struct CUnreachableData *pData);
3529aff1076Skamil static void HandleNonnullArg(bool isFatal, struct CNonNullArgData *pData);
3539aff1076Skamil static void HandleNonnullReturn(bool isFatal, struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer);
3549aff1076Skamil static void HandlePointerOverflow(bool isFatal, struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult);
3557f5eec67Skamil static void HandleAlignmentAssumption(bool isFatal, struct CAlignmentAssumptionData *pData, unsigned long ulPointer, unsigned long ulAlignment, unsigned long ulOffset);
3569aff1076Skamil 
3579aff1076Skamil static void
HandleOverflow(bool isFatal,struct COverflowData * pData,unsigned long ulLHS,unsigned long ulRHS,const char * szOperation)3589aff1076Skamil HandleOverflow(bool isFatal, struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS, const char *szOperation)
3599aff1076Skamil {
3609aff1076Skamil 	char szLocation[LOCATION_MAXLEN];
3619aff1076Skamil 	char szLHS[NUMBER_MAXLEN];
3629aff1076Skamil 	char szRHS[NUMBER_MAXLEN];
3639aff1076Skamil 
3649aff1076Skamil 	ASSERT(pData);
3659aff1076Skamil 
3669aff1076Skamil 	if (isAlreadyReported(&pData->mLocation))
3679aff1076Skamil 		return;
3689aff1076Skamil 
3699aff1076Skamil 	DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
3709aff1076Skamil 	DeserializeNumber(szLocation, szLHS, NUMBER_MAXLEN, pData->mType, ulLHS);
3719aff1076Skamil 	DeserializeNumber(szLocation, szRHS, NUMBER_MAXLEN, pData->mType, ulRHS);
3729aff1076Skamil 
3739aff1076Skamil 	Report(isFatal, "UBSan: Undefined Behavior in %s, %s integer overflow: %s %s %s cannot be represented in type %s\n",
3749aff1076Skamil 	       szLocation, ISSET(pData->mType->mTypeInfo, NUMBER_SIGNED_BIT) ? "signed" : "unsigned", szLHS, szOperation, szRHS, pData->mType->mTypeName);
3759aff1076Skamil }
3769aff1076Skamil 
3779aff1076Skamil static void
HandleNegateOverflow(bool isFatal,struct COverflowData * pData,unsigned long ulOldValue)3789aff1076Skamil HandleNegateOverflow(bool isFatal, struct COverflowData *pData, unsigned long ulOldValue)
3799aff1076Skamil {
3809aff1076Skamil 	char szLocation[LOCATION_MAXLEN];
3819aff1076Skamil 	char szOldValue[NUMBER_MAXLEN];
3829aff1076Skamil 
3839aff1076Skamil 	ASSERT(pData);
3849aff1076Skamil 
3859aff1076Skamil 	if (isAlreadyReported(&pData->mLocation))
3869aff1076Skamil 		return;
3879aff1076Skamil 
3889aff1076Skamil 	DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
3899aff1076Skamil 	DeserializeNumber(szLocation, szOldValue, NUMBER_MAXLEN, pData->mType, ulOldValue);
3909aff1076Skamil 
3919aff1076Skamil 	Report(isFatal, "UBSan: Undefined Behavior in %s, negation of %s cannot be represented in type %s\n",
3929aff1076Skamil 	       szLocation, szOldValue, pData->mType->mTypeName);
3939aff1076Skamil }
3949aff1076Skamil 
3959aff1076Skamil static void
HandleBuiltinUnreachable(bool isFatal,struct CUnreachableData * pData)3969aff1076Skamil HandleBuiltinUnreachable(bool isFatal, struct CUnreachableData *pData)
3979aff1076Skamil {
3989aff1076Skamil 	char szLocation[LOCATION_MAXLEN];
3999aff1076Skamil 
4009aff1076Skamil 	ASSERT(pData);
4019aff1076Skamil 
4029aff1076Skamil 	if (isAlreadyReported(&pData->mLocation))
4039aff1076Skamil 		return;
4049aff1076Skamil 
4059aff1076Skamil 	DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
4069aff1076Skamil 
4079aff1076Skamil 	Report(isFatal, "UBSan: Undefined Behavior in %s, calling __builtin_unreachable()\n",
4089aff1076Skamil 	       szLocation);
4099aff1076Skamil }
4109aff1076Skamil 
4119aff1076Skamil static void
HandleTypeMismatch(bool isFatal,struct CSourceLocation * mLocation,struct CTypeDescriptor * mType,unsigned long mLogAlignment,uint8_t mTypeCheckKind,unsigned long ulPointer)4129aff1076Skamil HandleTypeMismatch(bool isFatal, struct CSourceLocation *mLocation, struct CTypeDescriptor *mType, unsigned long mLogAlignment, uint8_t mTypeCheckKind, unsigned long ulPointer)
4139aff1076Skamil {
4149aff1076Skamil 	char szLocation[LOCATION_MAXLEN];
4159aff1076Skamil 
4169aff1076Skamil 	ASSERT(mLocation);
4179aff1076Skamil 	ASSERT(mType);
4189aff1076Skamil 
4199aff1076Skamil 	if (isAlreadyReported(mLocation))
4209aff1076Skamil 		return;
4219aff1076Skamil 
4229aff1076Skamil 	DeserializeLocation(szLocation, LOCATION_MAXLEN, mLocation);
4239aff1076Skamil 
4249aff1076Skamil 	if (ulPointer == 0) {
4259aff1076Skamil 		Report(isFatal, "UBSan: Undefined Behavior in %s, %s null pointer of type %s\n",
4269aff1076Skamil 		       szLocation, DeserializeTypeCheckKind(mTypeCheckKind), mType->mTypeName);
4279aff1076Skamil 	} else if ((mLogAlignment - 1) & ulPointer) {
4289aff1076Skamil 		Report(isFatal, "UBSan: Undefined Behavior in %s, %s misaligned address %p for type %s which requires %ld byte alignment\n",
4299aff1076Skamil 		       szLocation, DeserializeTypeCheckKind(mTypeCheckKind), REINTERPRET_CAST(void *, ulPointer), mType->mTypeName, mLogAlignment);
4309aff1076Skamil 	} else {
4319aff1076Skamil 		Report(isFatal, "UBSan: Undefined Behavior in %s, %s address %p with insufficient space for an object of type %s\n",
4329aff1076Skamil 		       szLocation, DeserializeTypeCheckKind(mTypeCheckKind), REINTERPRET_CAST(void *, ulPointer), mType->mTypeName);
4339aff1076Skamil 	}
4349aff1076Skamil }
4359aff1076Skamil 
4369aff1076Skamil static void
HandleVlaBoundNotPositive(bool isFatal,struct CVLABoundData * pData,unsigned long ulBound)4379aff1076Skamil HandleVlaBoundNotPositive(bool isFatal, struct CVLABoundData *pData, unsigned long ulBound)
4389aff1076Skamil {
4399aff1076Skamil 	char szLocation[LOCATION_MAXLEN];
4409aff1076Skamil 	char szBound[NUMBER_MAXLEN];
4419aff1076Skamil 
4429aff1076Skamil 	ASSERT(pData);
4439aff1076Skamil 
4449aff1076Skamil 	if (isAlreadyReported(&pData->mLocation))
4459aff1076Skamil 		return;
4469aff1076Skamil 
4479aff1076Skamil 	DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
4489aff1076Skamil 	DeserializeNumber(szLocation, szBound, NUMBER_MAXLEN, pData->mType, ulBound);
4499aff1076Skamil 
4509aff1076Skamil 	Report(isFatal, "UBSan: Undefined Behavior in %s, variable length array bound value %s <= 0\n",
4519aff1076Skamil 	       szLocation, szBound);
4529aff1076Skamil }
4539aff1076Skamil 
4549aff1076Skamil static void
HandleOutOfBounds(bool isFatal,struct COutOfBoundsData * pData,unsigned long ulIndex)4559aff1076Skamil HandleOutOfBounds(bool isFatal, struct COutOfBoundsData *pData, unsigned long ulIndex)
4569aff1076Skamil {
4579aff1076Skamil 	char szLocation[LOCATION_MAXLEN];
4589aff1076Skamil 	char szIndex[NUMBER_MAXLEN];
4599aff1076Skamil 
4609aff1076Skamil 	ASSERT(pData);
4619aff1076Skamil 
4629aff1076Skamil 	if (isAlreadyReported(&pData->mLocation))
4639aff1076Skamil 		return;
4649aff1076Skamil 
4659aff1076Skamil 	DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
4669aff1076Skamil 	DeserializeNumber(szLocation, szIndex, NUMBER_MAXLEN, pData->mIndexType, ulIndex);
4679aff1076Skamil 
4689aff1076Skamil 	Report(isFatal, "UBSan: Undefined Behavior in %s, index %s is out of range for type %s\n",
4699aff1076Skamil 	       szLocation, szIndex, pData->mArrayType->mTypeName);
4709aff1076Skamil }
4719aff1076Skamil 
4729aff1076Skamil static void
HandleShiftOutOfBounds(bool isFatal,struct CShiftOutOfBoundsData * pData,unsigned long ulLHS,unsigned long ulRHS)4739aff1076Skamil HandleShiftOutOfBounds(bool isFatal, struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS)
4749aff1076Skamil {
4759aff1076Skamil 	char szLocation[LOCATION_MAXLEN];
4769aff1076Skamil 	char szLHS[NUMBER_MAXLEN];
4779aff1076Skamil 	char szRHS[NUMBER_MAXLEN];
4789aff1076Skamil 
4799aff1076Skamil 	ASSERT(pData);
4809aff1076Skamil 
4819aff1076Skamil 	if (isAlreadyReported(&pData->mLocation))
4829aff1076Skamil 		return;
4839aff1076Skamil 
4849aff1076Skamil 	DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
4859aff1076Skamil 	DeserializeNumber(szLocation, szLHS, NUMBER_MAXLEN, pData->mLHSType, ulLHS);
4869aff1076Skamil 	DeserializeNumber(szLocation, szRHS, NUMBER_MAXLEN, pData->mRHSType, ulRHS);
4879aff1076Skamil 
4889aff1076Skamil 	if (isNegativeNumber(szLocation, pData->mRHSType, ulRHS))
4899aff1076Skamil 		Report(isFatal, "UBSan: Undefined Behavior in %s, shift exponent %s is negative\n",
4909aff1076Skamil 		       szLocation, szRHS);
4919aff1076Skamil 	else if (isShiftExponentTooLarge(szLocation, pData->mRHSType, ulRHS, zDeserializeTypeWidth(pData->mLHSType)))
4929aff1076Skamil 		Report(isFatal, "UBSan: Undefined Behavior in %s, shift exponent %s is too large for %zu-bit type %s\n",
4939aff1076Skamil 		       szLocation, szRHS, zDeserializeTypeWidth(pData->mLHSType), pData->mLHSType->mTypeName);
4949aff1076Skamil 	else if (isNegativeNumber(szLocation, pData->mLHSType, ulLHS))
4959aff1076Skamil 		Report(isFatal, "UBSan: Undefined Behavior in %s, left shift of negative value %s\n",
4969aff1076Skamil 		       szLocation, szLHS);
4979aff1076Skamil 	else
4989aff1076Skamil 		Report(isFatal, "UBSan: Undefined Behavior in %s, left shift of %s by %s places cannot be represented in type %s\n",
4999aff1076Skamil 		       szLocation, szLHS, szRHS, pData->mLHSType->mTypeName);
5009aff1076Skamil }
5019aff1076Skamil 
5029aff1076Skamil static void
HandleLoadInvalidValue(bool isFatal,struct CInvalidValueData * pData,unsigned long ulValue)5039aff1076Skamil HandleLoadInvalidValue(bool isFatal, struct CInvalidValueData *pData, unsigned long ulValue)
5049aff1076Skamil {
5059aff1076Skamil 	char szLocation[LOCATION_MAXLEN];
5069aff1076Skamil 	char szValue[NUMBER_MAXLEN];
5079aff1076Skamil 
5089aff1076Skamil 	ASSERT(pData);
5099aff1076Skamil 
5109aff1076Skamil 	if (isAlreadyReported(&pData->mLocation))
5119aff1076Skamil 		return;
5129aff1076Skamil 
5139aff1076Skamil 	DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
5149aff1076Skamil 	DeserializeNumber(szLocation, szValue, NUMBER_MAXLEN, pData->mType, ulValue);
5159aff1076Skamil 
5169aff1076Skamil 	Report(isFatal, "UBSan: Undefined Behavior in %s, load of value %s is not a valid value for type %s\n",
5179aff1076Skamil 	       szLocation, szValue, pData->mType->mTypeName);
5189aff1076Skamil }
5199aff1076Skamil 
5209aff1076Skamil static void
HandleInvalidBuiltin(bool isFatal,struct CInvalidBuiltinData * pData)5219aff1076Skamil HandleInvalidBuiltin(bool isFatal, struct CInvalidBuiltinData *pData)
5229aff1076Skamil {
5239aff1076Skamil 	char szLocation[LOCATION_MAXLEN];
5249aff1076Skamil 
5259aff1076Skamil 	ASSERT(pData);
5269aff1076Skamil 
5279aff1076Skamil 	if (isAlreadyReported(&pData->mLocation))
5289aff1076Skamil 		return;
5299aff1076Skamil 
5309aff1076Skamil 	DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
5319aff1076Skamil 
5329aff1076Skamil 	Report(isFatal, "UBSan: Undefined Behavior in %s, passing zero to %s, which is not a valid argument\n",
5339aff1076Skamil 	       szLocation, DeserializeBuiltinCheckKind(pData->mKind));
5349aff1076Skamil }
5359aff1076Skamil 
5369aff1076Skamil static void
HandleFunctionTypeMismatch(bool isFatal,struct CFunctionTypeMismatchData * pData,unsigned long ulFunction)5379aff1076Skamil HandleFunctionTypeMismatch(bool isFatal, struct CFunctionTypeMismatchData *pData, unsigned long ulFunction)
5389aff1076Skamil {
5399aff1076Skamil 	char szLocation[LOCATION_MAXLEN];
5409aff1076Skamil 
5419aff1076Skamil 	/*
5429aff1076Skamil 	 * There is no a portable C solution to translate an address of a
5439aff1076Skamil 	 * function to its name. On the cost of getting this routine simple
5449aff1076Skamil 	 * and portable without ifdefs between the userland and the kernel
5459aff1076Skamil 	 * just print the address of the function as-is.
5469aff1076Skamil 	 *
5479aff1076Skamil 	 * For better diagnostic messages in the userland, users shall use
5489aff1076Skamil 	 * the full upstream version shipped along with the compiler toolchain.
5499aff1076Skamil 	 */
5509aff1076Skamil 
5519aff1076Skamil 	ASSERT(pData);
5529aff1076Skamil 
5539aff1076Skamil 	if (isAlreadyReported(&pData->mLocation))
5549aff1076Skamil 		return;
5559aff1076Skamil 
5569aff1076Skamil 	DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
5579aff1076Skamil 
5589aff1076Skamil 	Report(isFatal, "UBSan: Undefined Behavior in %s, call to function %#lx through pointer to incorrect function type %s\n",
5599aff1076Skamil 	      szLocation, ulFunction, pData->mType->mTypeName);
5609aff1076Skamil }
5619aff1076Skamil 
5629aff1076Skamil static void
HandleCFIBadType(bool isFatal,struct CCFICheckFailData * pData,unsigned long ulVtable,bool * bValidVtable,bool * FromUnrecoverableHandler,unsigned long * ProgramCounter,unsigned long * FramePointer)5639aff1076Skamil HandleCFIBadType(bool isFatal, struct CCFICheckFailData *pData, unsigned long ulVtable, bool *bValidVtable, bool *FromUnrecoverableHandler, unsigned long *ProgramCounter, unsigned long *FramePointer)
5649aff1076Skamil {
5659aff1076Skamil 	char szLocation[LOCATION_MAXLEN];
5669aff1076Skamil 
5679aff1076Skamil 	/*
5689aff1076Skamil 	 * This is a minimal implementation without diving into C++
5699aff1076Skamil 	 * specifics and (Itanium) ABI deserialization.
5709aff1076Skamil 	 */
5719aff1076Skamil 
5729aff1076Skamil 	ASSERT(pData);
5739aff1076Skamil 
5749aff1076Skamil 	if (isAlreadyReported(&pData->mLocation))
5759aff1076Skamil 		return;
5769aff1076Skamil 
5779aff1076Skamil 	DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
5789aff1076Skamil 
5799aff1076Skamil 	if (pData->mCheckKind == CFI_ICALL || pData->mCheckKind == CFI_VMFCALL) {
5809aff1076Skamil 		Report(isFatal, "UBSan: Undefined Behavior in %s, control flow integrity check for type %s failed during %s (vtable address %#lx)\n",
5819aff1076Skamil 		      szLocation, pData->mType->mTypeName, DeserializeCFICheckKind(pData->mCheckKind), ulVtable);
5829aff1076Skamil 	} else {
5839aff1076Skamil 		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",
5849aff1076Skamil 		      szLocation, pData->mType->mTypeName, DeserializeCFICheckKind(pData->mCheckKind), ulVtable, *bValidVtable ? "valid" : "invalid", *FromUnrecoverableHandler ? "unrecoverable" : "recoverable", *ProgramCounter, *FramePointer);
5859aff1076Skamil 	}
5869aff1076Skamil }
5879aff1076Skamil 
5889aff1076Skamil static void
HandleDynamicTypeCacheMiss(bool isFatal,struct CDynamicTypeCacheMissData * pData,unsigned long ulPointer,unsigned long ulHash)5899aff1076Skamil HandleDynamicTypeCacheMiss(bool isFatal, struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash)
5909aff1076Skamil {
5919aff1076Skamil #if 0
5929aff1076Skamil 	char szLocation[LOCATION_MAXLEN];
5939aff1076Skamil 
5949aff1076Skamil 	/*
5959aff1076Skamil 	 * Unimplemented.
5969aff1076Skamil 	 *
5979aff1076Skamil 	 * This UBSan handler is special as the check has to be impelemented
5989aff1076Skamil 	 * in an implementation. In order to handle it there is need to
5999aff1076Skamil 	 * introspect into C++ ABI internals (RTTI) and use low-level
6009aff1076Skamil 	 * C++ runtime interfaces.
6019aff1076Skamil 	 */
6029aff1076Skamil 
6039aff1076Skamil 	ASSERT(pData);
6049aff1076Skamil 
6059aff1076Skamil 	if (isAlreadyReported(&pData->mLocation))
6069aff1076Skamil 		return;
6079aff1076Skamil 
6089aff1076Skamil 	DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
6099aff1076Skamil 
6109aff1076Skamil 	Report(isFatal, "UBSan: Undefined Behavior in %s, %s address %#lx which might not point to an object of type %s\n"
6119aff1076Skamil 	      szLocation, DeserializeTypeCheckKind(pData->mTypeCheckKind), ulPointer, pData->mType);
6129aff1076Skamil #endif
6139aff1076Skamil }
6149aff1076Skamil 
6159aff1076Skamil static void
HandleFloatCastOverflow(bool isFatal,struct CFloatCastOverflowData * pData,unsigned long ulFrom)6169aff1076Skamil HandleFloatCastOverflow(bool isFatal, struct CFloatCastOverflowData *pData, unsigned long ulFrom)
6179aff1076Skamil {
6189aff1076Skamil 	char szLocation[LOCATION_MAXLEN];
6199aff1076Skamil 	char szFrom[NUMBER_MAXLEN];
6209aff1076Skamil 
6219aff1076Skamil 	ASSERT(pData);
6229aff1076Skamil 
6239aff1076Skamil 	if (isAlreadyReported(&pData->mLocation))
6249aff1076Skamil 		return;
6259aff1076Skamil 
6269aff1076Skamil 	DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
6279aff1076Skamil 	DeserializeNumber(szLocation, szFrom, NUMBER_MAXLEN, pData->mFromType, ulFrom);
6289aff1076Skamil 
6299aff1076Skamil 	Report(isFatal, "UBSan: Undefined Behavior in %s, %s (of type %s) is outside the range of representable values of type %s\n",
6309aff1076Skamil 	       szLocation, szFrom, pData->mFromType->mTypeName, pData->mToType->mTypeName);
6319aff1076Skamil }
6329aff1076Skamil 
6339aff1076Skamil static void
HandleMissingReturn(bool isFatal,struct CUnreachableData * pData)6349aff1076Skamil HandleMissingReturn(bool isFatal, struct CUnreachableData *pData)
6359aff1076Skamil {
6369aff1076Skamil 	char szLocation[LOCATION_MAXLEN];
6379aff1076Skamil 
6389aff1076Skamil 	ASSERT(pData);
6399aff1076Skamil 
6409aff1076Skamil 	if (isAlreadyReported(&pData->mLocation))
6419aff1076Skamil 		return;
6429aff1076Skamil 
6439aff1076Skamil 	DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
6449aff1076Skamil 
6459aff1076Skamil 	Report(isFatal, "UBSan: Undefined Behavior in %s, execution reached the end of a value-returning function without returning a value\n",
6469aff1076Skamil 	       szLocation);
6479aff1076Skamil }
6489aff1076Skamil 
6499aff1076Skamil static void
HandleNonnullArg(bool isFatal,struct CNonNullArgData * pData)6509aff1076Skamil HandleNonnullArg(bool isFatal, struct CNonNullArgData *pData)
6519aff1076Skamil {
6529aff1076Skamil 	char szLocation[LOCATION_MAXLEN];
6539aff1076Skamil 	char szAttributeLocation[LOCATION_MAXLEN];
6549aff1076Skamil 
6559aff1076Skamil 	ASSERT(pData);
6569aff1076Skamil 
6579aff1076Skamil 	if (isAlreadyReported(&pData->mLocation))
6589aff1076Skamil 		return;
6599aff1076Skamil 
6609aff1076Skamil 	DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
6619aff1076Skamil 	if (pData->mAttributeLocation.mFilename)
6629aff1076Skamil 		DeserializeLocation(szAttributeLocation, LOCATION_MAXLEN, &pData->mAttributeLocation);
6639aff1076Skamil 	else
6649aff1076Skamil 		szAttributeLocation[0] = '\0';
6659aff1076Skamil 
6669aff1076Skamil 	Report(isFatal, "UBSan: Undefined Behavior in %s, null pointer passed as argument %d, which is declared to never be null%s%s\n",
6679aff1076Skamil 	       szLocation, pData->mArgIndex, pData->mAttributeLocation.mFilename ? ", nonnull/_Nonnull specified in " : "", szAttributeLocation);
6689aff1076Skamil }
6699aff1076Skamil 
6709aff1076Skamil static void
HandleNonnullReturn(bool isFatal,struct CNonNullReturnData * pData,struct CSourceLocation * pLocationPointer)6719aff1076Skamil HandleNonnullReturn(bool isFatal, struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
6729aff1076Skamil {
6739aff1076Skamil 	char szLocation[LOCATION_MAXLEN];
6749aff1076Skamil 	char szAttributeLocation[LOCATION_MAXLEN];
6759aff1076Skamil 
6769aff1076Skamil 	ASSERT(pData);
6779aff1076Skamil 	ASSERT(pLocationPointer);
6789aff1076Skamil 
6799aff1076Skamil 	if (isAlreadyReported(pLocationPointer))
6809aff1076Skamil 		return;
6819aff1076Skamil 
6829aff1076Skamil 	DeserializeLocation(szLocation, LOCATION_MAXLEN, pLocationPointer);
6839aff1076Skamil 	if (pData->mAttributeLocation.mFilename)
6849aff1076Skamil 		DeserializeLocation(szAttributeLocation, LOCATION_MAXLEN, &pData->mAttributeLocation);
6859aff1076Skamil 	else
6869aff1076Skamil 		szAttributeLocation[0] = '\0';
6879aff1076Skamil 
6889aff1076Skamil 	Report(isFatal, "UBSan: Undefined Behavior in %s, null pointer returned from function declared to never return null%s%s\n",
6899aff1076Skamil 	       szLocation, pData->mAttributeLocation.mFilename ? ", nonnull/_Nonnull specified in " : "", szAttributeLocation);
6909aff1076Skamil }
6919aff1076Skamil 
6929aff1076Skamil static void
HandlePointerOverflow(bool isFatal,struct CPointerOverflowData * pData,unsigned long ulBase,unsigned long ulResult)6939aff1076Skamil HandlePointerOverflow(bool isFatal, struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult)
6949aff1076Skamil {
6959aff1076Skamil 	char szLocation[LOCATION_MAXLEN];
6969aff1076Skamil 
6979aff1076Skamil 	ASSERT(pData);
6989aff1076Skamil 
6999aff1076Skamil 	if (isAlreadyReported(&pData->mLocation))
7009aff1076Skamil 		return;
7019aff1076Skamil 
7029aff1076Skamil 	DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
7039aff1076Skamil 
7049aff1076Skamil 	Report(isFatal, "UBSan: Undefined Behavior in %s, pointer expression with base %#lx overflowed to %#lx\n",
7059aff1076Skamil 	       szLocation, ulBase, ulResult);
7069aff1076Skamil }
7079aff1076Skamil 
708aeb81341Skamil static void
HandleImplicitConversion(bool isFatal,struct CImplicitConversionData * pData,unsigned long ulFrom,unsigned long ulTo)709aeb81341Skamil HandleImplicitConversion(bool isFatal, struct CImplicitConversionData *pData, unsigned long ulFrom, unsigned long ulTo)
710aeb81341Skamil {
711aeb81341Skamil 	char szLocation[LOCATION_MAXLEN];
712aeb81341Skamil 	char szFrom[NUMBER_MAXLEN];
713aeb81341Skamil 	char szTo[NUMBER_MAXLEN];
714aeb81341Skamil 
715aeb81341Skamil 	ASSERT(pData);
716aeb81341Skamil 
717aeb81341Skamil 	if (isAlreadyReported(&pData->mLocation))
718aeb81341Skamil 		return;
719aeb81341Skamil 
720aeb81341Skamil 	DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
721aeb81341Skamil 	DeserializeNumber(szLocation, szFrom, NUMBER_MAXLEN, pData->mFromType, ulFrom);
722aeb81341Skamil 	DeserializeNumber(szLocation, szTo, NUMBER_MAXLEN, pData->mToType, ulTo);
723aeb81341Skamil 
724aeb81341Skamil 	Report(isFatal, "UBSan: Undefined Behavior in %s, %s from %s %zu-bit %s (%s) to %s changed the value to %s %zu-bit %s\n",
725aeb81341Skamil 	       szLocation, DeserializeImplicitConversionCheckKind(pData->mKind), szFrom, zDeserializeTypeWidth(pData->mFromType), ISSET(pData->mFromType->mTypeInfo, NUMBER_SIGNED_BIT) ? "signed" : "unsigned", pData->mFromType->mTypeName, pData->mToType->mTypeName, szTo, zDeserializeTypeWidth(pData->mToType), ISSET(pData->mToType->mTypeInfo, NUMBER_SIGNED_BIT) ? "signed" : "unsigned");
726aeb81341Skamil }
727aeb81341Skamil 
7287f5eec67Skamil static void
HandleAlignmentAssumption(bool isFatal,struct CAlignmentAssumptionData * pData,unsigned long ulPointer,unsigned long ulAlignment,unsigned long ulOffset)7297f5eec67Skamil HandleAlignmentAssumption(bool isFatal, struct CAlignmentAssumptionData *pData, unsigned long ulPointer, unsigned long ulAlignment, unsigned long ulOffset)
7307f5eec67Skamil {
7317f5eec67Skamil 	char szLocation[LOCATION_MAXLEN];
7327f5eec67Skamil 	char szAssumptionLocation[LOCATION_MAXLEN];
7337f5eec67Skamil 	unsigned long ulRealPointer;
7347f5eec67Skamil 
7357f5eec67Skamil 	ASSERT(pData);
7367f5eec67Skamil 
7377f5eec67Skamil 	if (isAlreadyReported(&pData->mLocation))
7387f5eec67Skamil 		return;
7397f5eec67Skamil 
7407f5eec67Skamil 	DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
7417f5eec67Skamil 
7427f5eec67Skamil 	ulRealPointer = ulPointer - ulOffset;
7437f5eec67Skamil 
7447f5eec67Skamil 	if (pData->mAssumptionLocation.mFilename != NULL) {
7457f5eec67Skamil 		DeserializeLocation(szAssumptionLocation, LOCATION_MAXLEN,
7467f5eec67Skamil 		    &pData->mAssumptionLocation);
747a136e22aSandvar 		Report(isFatal, "UBSan: Undefined Behavior in %s, alignment assumption of %#lx for pointer %#lx (offset %#lx), assumption made in %s\n",
7487f5eec67Skamil 		    szLocation, ulAlignment, ulRealPointer, ulOffset,
7497f5eec67Skamil 		    szAssumptionLocation);
7507f5eec67Skamil 	} else {
7517f5eec67Skamil 		Report(isFatal, "UBSan: Undefined Behavior in %s, alignment assumption of %#lx for pointer %#lx (offset %#lx)\n",
7527f5eec67Skamil 		    szLocation, ulAlignment, ulRealPointer, ulOffset);
7537f5eec67Skamil 	}
7547f5eec67Skamil }
7557f5eec67Skamil 
7569aff1076Skamil /* Definions of public symbols emitted by the instrumentation code */
7579aff1076Skamil void
__ubsan_handle_add_overflow(struct COverflowData * pData,unsigned long ulLHS,unsigned long ulRHS)7589aff1076Skamil __ubsan_handle_add_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
7599aff1076Skamil {
7609aff1076Skamil 
7619aff1076Skamil 	ASSERT(pData);
7629aff1076Skamil 
7639aff1076Skamil 	HandleOverflow(false, pData, ulLHS, ulRHS, PLUS_STRING);
7649aff1076Skamil }
7659aff1076Skamil 
7669aff1076Skamil void
__ubsan_handle_add_overflow_abort(struct COverflowData * pData,unsigned long ulLHS,unsigned long ulRHS)7679aff1076Skamil __ubsan_handle_add_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
7689aff1076Skamil {
7699aff1076Skamil 
7709aff1076Skamil 	ASSERT(pData);
7719aff1076Skamil 
7729aff1076Skamil 	HandleOverflow(true, pData, ulLHS, ulRHS, PLUS_STRING);
7739aff1076Skamil }
7749aff1076Skamil 
7759aff1076Skamil void
__ubsan_handle_alignment_assumption(struct CAlignmentAssumptionData * pData,unsigned long ulPointer,unsigned long ulAlignment,unsigned long ulOffset)7767f5eec67Skamil __ubsan_handle_alignment_assumption(struct CAlignmentAssumptionData *pData, unsigned long ulPointer, unsigned long ulAlignment, unsigned long ulOffset)
7777f5eec67Skamil {
7787f5eec67Skamil 
7797f5eec67Skamil 	ASSERT(pData);
7807f5eec67Skamil 
7817f5eec67Skamil 	HandleAlignmentAssumption(false, pData, ulPointer, ulAlignment, ulOffset);
7827f5eec67Skamil }
7837f5eec67Skamil 
7847f5eec67Skamil void
__ubsan_handle_alignment_assumption_abort(struct CAlignmentAssumptionData * pData,unsigned long ulPointer,unsigned long ulAlignment,unsigned long ulOffset)7857f5eec67Skamil __ubsan_handle_alignment_assumption_abort(struct CAlignmentAssumptionData *pData, unsigned long ulPointer, unsigned long ulAlignment, unsigned long ulOffset)
7867f5eec67Skamil {
7877f5eec67Skamil 
7887f5eec67Skamil 	ASSERT(pData);
7897f5eec67Skamil 
7907f5eec67Skamil 	HandleAlignmentAssumption(true, pData, ulPointer, ulAlignment, ulOffset);
7917f5eec67Skamil }
7927f5eec67Skamil 
7937f5eec67Skamil void
__ubsan_handle_builtin_unreachable(struct CUnreachableData * pData)7949aff1076Skamil __ubsan_handle_builtin_unreachable(struct CUnreachableData *pData)
7959aff1076Skamil {
7969aff1076Skamil 
7979aff1076Skamil 	ASSERT(pData);
7989aff1076Skamil 
7999aff1076Skamil 	HandleBuiltinUnreachable(true, pData);
8009aff1076Skamil }
8019aff1076Skamil 
8029aff1076Skamil void
__ubsan_handle_cfi_bad_type(struct CCFICheckFailData * pData,unsigned long ulVtable,bool bValidVtable,bool FromUnrecoverableHandler,unsigned long ProgramCounter,unsigned long FramePointer)8039aff1076Skamil __ubsan_handle_cfi_bad_type(struct CCFICheckFailData *pData, unsigned long ulVtable, bool bValidVtable, bool FromUnrecoverableHandler, unsigned long ProgramCounter, unsigned long FramePointer)
8049aff1076Skamil {
8059aff1076Skamil 
8069aff1076Skamil 	ASSERT(pData);
8079aff1076Skamil 
8089aff1076Skamil 	HandleCFIBadType(false, pData, ulVtable, &bValidVtable, &FromUnrecoverableHandler, &ProgramCounter, &FramePointer);
8099aff1076Skamil }
8109aff1076Skamil 
8119aff1076Skamil void
__ubsan_handle_cfi_check_fail(struct CCFICheckFailData * pData,unsigned long ulValue,unsigned long ulValidVtable)8129aff1076Skamil __ubsan_handle_cfi_check_fail(struct CCFICheckFailData *pData, unsigned long ulValue, unsigned long ulValidVtable)
8139aff1076Skamil {
8149aff1076Skamil 
8159aff1076Skamil 	ASSERT(pData);
8169aff1076Skamil 
8179aff1076Skamil 	HandleCFIBadType(false, pData, ulValue, 0, 0, 0, 0);
8189aff1076Skamil }
8199aff1076Skamil 
8209aff1076Skamil void
__ubsan_handle_cfi_check_fail_abort(struct CCFICheckFailData * pData,unsigned long ulValue,unsigned long ulValidVtable)8219aff1076Skamil __ubsan_handle_cfi_check_fail_abort(struct CCFICheckFailData *pData, unsigned long ulValue, unsigned long ulValidVtable)
8229aff1076Skamil {
8239aff1076Skamil 
8249aff1076Skamil 	ASSERT(pData);
8259aff1076Skamil 
8269aff1076Skamil 	HandleCFIBadType(true, pData, ulValue, 0, 0, 0, 0);
8279aff1076Skamil }
8289aff1076Skamil 
8299aff1076Skamil void
__ubsan_handle_divrem_overflow(struct COverflowData * pData,unsigned long ulLHS,unsigned long ulRHS)8309aff1076Skamil __ubsan_handle_divrem_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
8319aff1076Skamil {
8329aff1076Skamil 
8339aff1076Skamil 	ASSERT(pData);
8349aff1076Skamil 
8359aff1076Skamil 	HandleOverflow(false, pData, ulLHS, ulRHS, DIVREM_STRING);
8369aff1076Skamil }
8379aff1076Skamil 
8389aff1076Skamil void
__ubsan_handle_divrem_overflow_abort(struct COverflowData * pData,unsigned long ulLHS,unsigned long ulRHS)8399aff1076Skamil __ubsan_handle_divrem_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
8409aff1076Skamil {
8419aff1076Skamil 
8429aff1076Skamil 	ASSERT(pData);
8439aff1076Skamil 
8449aff1076Skamil 	HandleOverflow(true, pData, ulLHS, ulRHS, DIVREM_STRING);
8459aff1076Skamil }
8469aff1076Skamil 
8479aff1076Skamil void
__ubsan_handle_dynamic_type_cache_miss(struct CDynamicTypeCacheMissData * pData,unsigned long ulPointer,unsigned long ulHash)8489aff1076Skamil __ubsan_handle_dynamic_type_cache_miss(struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash)
8499aff1076Skamil {
8509aff1076Skamil 
8519aff1076Skamil 	ASSERT(pData);
8529aff1076Skamil 
8539aff1076Skamil 	HandleDynamicTypeCacheMiss(false, pData, ulPointer, ulHash);
8549aff1076Skamil }
8559aff1076Skamil 
8569aff1076Skamil void
__ubsan_handle_dynamic_type_cache_miss_abort(struct CDynamicTypeCacheMissData * pData,unsigned long ulPointer,unsigned long ulHash)8579aff1076Skamil __ubsan_handle_dynamic_type_cache_miss_abort(struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash)
8589aff1076Skamil {
8599aff1076Skamil 
8609aff1076Skamil 	ASSERT(pData);
8619aff1076Skamil 
8629aff1076Skamil 	HandleDynamicTypeCacheMiss(false, pData, ulPointer, ulHash);
8639aff1076Skamil }
8649aff1076Skamil 
8659aff1076Skamil void
__ubsan_handle_float_cast_overflow(struct CFloatCastOverflowData * pData,unsigned long ulFrom)8669aff1076Skamil __ubsan_handle_float_cast_overflow(struct CFloatCastOverflowData *pData, unsigned long ulFrom)
8679aff1076Skamil {
8689aff1076Skamil 
8699aff1076Skamil 	ASSERT(pData);
8709aff1076Skamil 
8719aff1076Skamil 	HandleFloatCastOverflow(false, pData, ulFrom);
8729aff1076Skamil }
8739aff1076Skamil 
8749aff1076Skamil void
__ubsan_handle_float_cast_overflow_abort(struct CFloatCastOverflowData * pData,unsigned long ulFrom)8759aff1076Skamil __ubsan_handle_float_cast_overflow_abort(struct CFloatCastOverflowData *pData, unsigned long ulFrom)
8769aff1076Skamil {
8779aff1076Skamil 
8789aff1076Skamil 	ASSERT(pData);
8799aff1076Skamil 
8809aff1076Skamil 	HandleFloatCastOverflow(true, pData, ulFrom);
8819aff1076Skamil }
8829aff1076Skamil 
8839aff1076Skamil void
__ubsan_handle_function_type_mismatch(struct CFunctionTypeMismatchData * pData,unsigned long ulFunction)8849aff1076Skamil __ubsan_handle_function_type_mismatch(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction)
8859aff1076Skamil {
8869aff1076Skamil 
8879aff1076Skamil 	ASSERT(pData);
8889aff1076Skamil 
8899aff1076Skamil 	HandleFunctionTypeMismatch(false, pData, ulFunction);
8909aff1076Skamil }
8919aff1076Skamil 
8929aff1076Skamil void
__ubsan_handle_function_type_mismatch_abort(struct CFunctionTypeMismatchData * pData,unsigned long ulFunction)8939aff1076Skamil __ubsan_handle_function_type_mismatch_abort(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction)
8949aff1076Skamil {
8959aff1076Skamil 
8969aff1076Skamil 	ASSERT(pData);
8979aff1076Skamil 
8980b65214dSkamil 	HandleFunctionTypeMismatch(true, pData, ulFunction);
8990b65214dSkamil }
9000b65214dSkamil 
9010b65214dSkamil void
__ubsan_handle_function_type_mismatch_v1(struct CFunctionTypeMismatchData * pData,unsigned long ulFunction,unsigned long ulCalleeRTTI,unsigned long ulFnRTTI)9020b65214dSkamil __ubsan_handle_function_type_mismatch_v1(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction, unsigned long ulCalleeRTTI, unsigned long ulFnRTTI)
9030b65214dSkamil {
9040b65214dSkamil 
9050b65214dSkamil 	ASSERT(pData);
9060b65214dSkamil #if 0
9070b65214dSkamil 	/*
9080b65214dSkamil 	 * Unimplemented.
9090b65214dSkamil 	 *
9100b65214dSkamil 	 * This UBSan handler is special as the check has to be impelemented
9110b65214dSkamil 	 * in an implementation. In order to handle it there is need to
9120b65214dSkamil 	 * introspect into C++ ABI internals (RTTI) and use low-level
9130b65214dSkamil 	 * C++ runtime interfaces.
9140b65214dSkamil 	 */
9150b65214dSkamil 
9169aff1076Skamil 	HandleFunctionTypeMismatch(false, pData, ulFunction);
9170b65214dSkamil #endif
9180b65214dSkamil }
9190b65214dSkamil 
9200b65214dSkamil void
__ubsan_handle_function_type_mismatch_v1_abort(struct CFunctionTypeMismatchData * pData,unsigned long ulFunction,unsigned long ulCalleeRTTI,unsigned long ulFnRTTI)9210b65214dSkamil __ubsan_handle_function_type_mismatch_v1_abort(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction, unsigned long ulCalleeRTTI, unsigned long ulFnRTTI)
9220b65214dSkamil {
9230b65214dSkamil 
9240b65214dSkamil 	ASSERT(pData);
9250b65214dSkamil #if 0
9260b65214dSkamil 	/*
9270b65214dSkamil 	 * Unimplemented.
9280b65214dSkamil 	 *
9290b65214dSkamil 	 * This UBSan handler is special as the check has to be impelemented
9300b65214dSkamil 	 * in an implementation. In order to handle it there is need to
9310b65214dSkamil 	 * introspect into C++ ABI internals (RTTI) and use low-level
9320b65214dSkamil 	 * C++ runtime interfaces.
9330b65214dSkamil 	 */
9340b65214dSkamil 
9350b65214dSkamil 	HandleFunctionTypeMismatch(true, pData, ulFunction);
9360b65214dSkamil #endif
9379aff1076Skamil }
9389aff1076Skamil 
9399aff1076Skamil void
__ubsan_handle_invalid_builtin(struct CInvalidBuiltinData * pData)9409aff1076Skamil __ubsan_handle_invalid_builtin(struct CInvalidBuiltinData *pData)
9419aff1076Skamil {
9429aff1076Skamil 
9439aff1076Skamil 	ASSERT(pData);
9449aff1076Skamil 
9459aff1076Skamil 	HandleInvalidBuiltin(true, pData);
9469aff1076Skamil }
9479aff1076Skamil 
9489aff1076Skamil void
__ubsan_handle_invalid_builtin_abort(struct CInvalidBuiltinData * pData)9499aff1076Skamil __ubsan_handle_invalid_builtin_abort(struct CInvalidBuiltinData *pData)
9509aff1076Skamil {
9519aff1076Skamil 
9529aff1076Skamil 	ASSERT(pData);
9539aff1076Skamil 
9549aff1076Skamil 	HandleInvalidBuiltin(true, pData);
9559aff1076Skamil }
9569aff1076Skamil 
9579aff1076Skamil void
__ubsan_handle_load_invalid_value(struct CInvalidValueData * pData,unsigned long ulValue)9589aff1076Skamil __ubsan_handle_load_invalid_value(struct CInvalidValueData *pData, unsigned long ulValue)
9599aff1076Skamil {
9609aff1076Skamil 
9619aff1076Skamil 	ASSERT(pData);
9629aff1076Skamil 
9639aff1076Skamil 	HandleLoadInvalidValue(false, pData, ulValue);
9649aff1076Skamil }
9659aff1076Skamil 
9669aff1076Skamil void
__ubsan_handle_load_invalid_value_abort(struct CInvalidValueData * pData,unsigned long ulValue)9679aff1076Skamil __ubsan_handle_load_invalid_value_abort(struct CInvalidValueData *pData, unsigned long ulValue)
9689aff1076Skamil {
9699aff1076Skamil 
9709aff1076Skamil 	ASSERT(pData);
9719aff1076Skamil 
9729aff1076Skamil 	HandleLoadInvalidValue(true, pData, ulValue);
9739aff1076Skamil }
9749aff1076Skamil 
9759aff1076Skamil void
__ubsan_handle_missing_return(struct CUnreachableData * pData)9769aff1076Skamil __ubsan_handle_missing_return(struct CUnreachableData *pData)
9779aff1076Skamil {
9789aff1076Skamil 
9799aff1076Skamil 	ASSERT(pData);
9809aff1076Skamil 
9819aff1076Skamil 	HandleMissingReturn(true, pData);
9829aff1076Skamil }
9839aff1076Skamil 
9849aff1076Skamil void
__ubsan_handle_mul_overflow(struct COverflowData * pData,unsigned long ulLHS,unsigned long ulRHS)9859aff1076Skamil __ubsan_handle_mul_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
9869aff1076Skamil {
9879aff1076Skamil 
9889aff1076Skamil 	ASSERT(pData);
9899aff1076Skamil 
9909aff1076Skamil 	HandleOverflow(false, pData, ulLHS, ulRHS, MUL_STRING);
9919aff1076Skamil }
9929aff1076Skamil 
9939aff1076Skamil void
__ubsan_handle_mul_overflow_abort(struct COverflowData * pData,unsigned long ulLHS,unsigned long ulRHS)9949aff1076Skamil __ubsan_handle_mul_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
9959aff1076Skamil {
9969aff1076Skamil 
9979aff1076Skamil 	ASSERT(pData);
9989aff1076Skamil 
9999aff1076Skamil 	HandleOverflow(true, pData, ulLHS, ulRHS, MUL_STRING);
10009aff1076Skamil }
10019aff1076Skamil 
10029aff1076Skamil void
__ubsan_handle_negate_overflow(struct COverflowData * pData,unsigned long ulOldValue)10039aff1076Skamil __ubsan_handle_negate_overflow(struct COverflowData *pData, unsigned long ulOldValue)
10049aff1076Skamil {
10059aff1076Skamil 
10069aff1076Skamil 	ASSERT(pData);
10079aff1076Skamil 
10089aff1076Skamil 	HandleNegateOverflow(false, pData, ulOldValue);
10099aff1076Skamil }
10109aff1076Skamil 
10119aff1076Skamil void
__ubsan_handle_negate_overflow_abort(struct COverflowData * pData,unsigned long ulOldValue)10129aff1076Skamil __ubsan_handle_negate_overflow_abort(struct COverflowData *pData, unsigned long ulOldValue)
10139aff1076Skamil {
10149aff1076Skamil 
10159aff1076Skamil 	ASSERT(pData);
10169aff1076Skamil 
10179aff1076Skamil 	HandleNegateOverflow(true, pData, ulOldValue);
10189aff1076Skamil }
10199aff1076Skamil 
10209aff1076Skamil void
__ubsan_handle_nonnull_arg(struct CNonNullArgData * pData)10219aff1076Skamil __ubsan_handle_nonnull_arg(struct CNonNullArgData *pData)
10229aff1076Skamil {
10239aff1076Skamil 
10249aff1076Skamil 	ASSERT(pData);
10259aff1076Skamil 
10269aff1076Skamil 	HandleNonnullArg(false, pData);
10279aff1076Skamil }
10289aff1076Skamil 
10299aff1076Skamil void
__ubsan_handle_nonnull_arg_abort(struct CNonNullArgData * pData)10309aff1076Skamil __ubsan_handle_nonnull_arg_abort(struct CNonNullArgData *pData)
10319aff1076Skamil {
10329aff1076Skamil 
10339aff1076Skamil 	ASSERT(pData);
10349aff1076Skamil 
10359aff1076Skamil 	HandleNonnullArg(true, pData);
10369aff1076Skamil }
10379aff1076Skamil 
10389aff1076Skamil void
__ubsan_handle_nonnull_return_v1(struct CNonNullReturnData * pData,struct CSourceLocation * pLocationPointer)10399aff1076Skamil __ubsan_handle_nonnull_return_v1(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
10409aff1076Skamil {
10419aff1076Skamil 
10429aff1076Skamil 	ASSERT(pData);
10439aff1076Skamil 	ASSERT(pLocationPointer);
10449aff1076Skamil 
10459aff1076Skamil 	HandleNonnullReturn(false, pData, pLocationPointer);
10469aff1076Skamil }
10479aff1076Skamil 
10489aff1076Skamil void
__ubsan_handle_nonnull_return_v1_abort(struct CNonNullReturnData * pData,struct CSourceLocation * pLocationPointer)10499aff1076Skamil __ubsan_handle_nonnull_return_v1_abort(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
10509aff1076Skamil {
10519aff1076Skamil 
10529aff1076Skamil 	ASSERT(pData);
10539aff1076Skamil 	ASSERT(pLocationPointer);
10549aff1076Skamil 
10559aff1076Skamil 	HandleNonnullReturn(true, pData, pLocationPointer);
10569aff1076Skamil }
10579aff1076Skamil 
10589aff1076Skamil void
__ubsan_handle_nullability_arg(struct CNonNullArgData * pData)10599aff1076Skamil __ubsan_handle_nullability_arg(struct CNonNullArgData *pData)
10609aff1076Skamil {
10619aff1076Skamil 
10629aff1076Skamil 	ASSERT(pData);
10639aff1076Skamil 
10649aff1076Skamil 	HandleNonnullArg(false, pData);
10659aff1076Skamil }
10669aff1076Skamil 
10679aff1076Skamil void
__ubsan_handle_nullability_arg_abort(struct CNonNullArgData * pData)10689aff1076Skamil __ubsan_handle_nullability_arg_abort(struct CNonNullArgData *pData)
10699aff1076Skamil {
10709aff1076Skamil 
10719aff1076Skamil 	ASSERT(pData);
10729aff1076Skamil 
10739aff1076Skamil 	HandleNonnullArg(true, pData);
10749aff1076Skamil }
10759aff1076Skamil 
10769aff1076Skamil void
__ubsan_handle_nullability_return_v1(struct CNonNullReturnData * pData,struct CSourceLocation * pLocationPointer)10779aff1076Skamil __ubsan_handle_nullability_return_v1(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
10789aff1076Skamil {
10799aff1076Skamil 
10809aff1076Skamil 	ASSERT(pData);
10819aff1076Skamil 	ASSERT(pLocationPointer);
10829aff1076Skamil 
10839aff1076Skamil 	HandleNonnullReturn(false, pData, pLocationPointer);
10849aff1076Skamil }
10859aff1076Skamil 
10869aff1076Skamil void
__ubsan_handle_nullability_return_v1_abort(struct CNonNullReturnData * pData,struct CSourceLocation * pLocationPointer)10879aff1076Skamil __ubsan_handle_nullability_return_v1_abort(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
10889aff1076Skamil {
10899aff1076Skamil 
10909aff1076Skamil 	ASSERT(pData);
10919aff1076Skamil 	ASSERT(pLocationPointer);
10929aff1076Skamil 
10939aff1076Skamil 	HandleNonnullReturn(true, pData, pLocationPointer);
10949aff1076Skamil }
10959aff1076Skamil 
10969aff1076Skamil void
__ubsan_handle_out_of_bounds(struct COutOfBoundsData * pData,unsigned long ulIndex)10979aff1076Skamil __ubsan_handle_out_of_bounds(struct COutOfBoundsData *pData, unsigned long ulIndex)
10989aff1076Skamil {
10999aff1076Skamil 
11009aff1076Skamil 	ASSERT(pData);
11019aff1076Skamil 
11029aff1076Skamil 	HandleOutOfBounds(false, pData, ulIndex);
11039aff1076Skamil }
11049aff1076Skamil 
11059aff1076Skamil void
__ubsan_handle_out_of_bounds_abort(struct COutOfBoundsData * pData,unsigned long ulIndex)11069aff1076Skamil __ubsan_handle_out_of_bounds_abort(struct COutOfBoundsData *pData, unsigned long ulIndex)
11079aff1076Skamil {
11089aff1076Skamil 
11099aff1076Skamil 	ASSERT(pData);
11109aff1076Skamil 
11119aff1076Skamil 	HandleOutOfBounds(true, pData, ulIndex);
11129aff1076Skamil }
11139aff1076Skamil 
11149aff1076Skamil void
__ubsan_handle_pointer_overflow(struct CPointerOverflowData * pData,unsigned long ulBase,unsigned long ulResult)11159aff1076Skamil __ubsan_handle_pointer_overflow(struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult)
11169aff1076Skamil {
11179aff1076Skamil 
11189aff1076Skamil 	ASSERT(pData);
11199aff1076Skamil 
11209aff1076Skamil 	HandlePointerOverflow(false, pData, ulBase, ulResult);
11219aff1076Skamil }
11229aff1076Skamil 
11239aff1076Skamil void
__ubsan_handle_pointer_overflow_abort(struct CPointerOverflowData * pData,unsigned long ulBase,unsigned long ulResult)11249aff1076Skamil __ubsan_handle_pointer_overflow_abort(struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult)
11259aff1076Skamil {
11269aff1076Skamil 
11279aff1076Skamil 	ASSERT(pData);
11289aff1076Skamil 
11299aff1076Skamil 	HandlePointerOverflow(true, pData, ulBase, ulResult);
11309aff1076Skamil }
11319aff1076Skamil 
11329aff1076Skamil void
__ubsan_handle_shift_out_of_bounds(struct CShiftOutOfBoundsData * pData,unsigned long ulLHS,unsigned long ulRHS)11339aff1076Skamil __ubsan_handle_shift_out_of_bounds(struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS)
11349aff1076Skamil {
11359aff1076Skamil 
11369aff1076Skamil 	ASSERT(pData);
11379aff1076Skamil 
11389aff1076Skamil 	HandleShiftOutOfBounds(false, pData, ulLHS, ulRHS);
11399aff1076Skamil }
11409aff1076Skamil 
11419aff1076Skamil void
__ubsan_handle_shift_out_of_bounds_abort(struct CShiftOutOfBoundsData * pData,unsigned long ulLHS,unsigned long ulRHS)11429aff1076Skamil __ubsan_handle_shift_out_of_bounds_abort(struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS)
11439aff1076Skamil {
11449aff1076Skamil 
11459aff1076Skamil 	ASSERT(pData);
11469aff1076Skamil 
11479aff1076Skamil 	HandleShiftOutOfBounds(true, pData, ulLHS, ulRHS);
11489aff1076Skamil }
11499aff1076Skamil 
11509aff1076Skamil void
__ubsan_handle_sub_overflow(struct COverflowData * pData,unsigned long ulLHS,unsigned long ulRHS)11519aff1076Skamil __ubsan_handle_sub_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
11529aff1076Skamil {
11539aff1076Skamil 
11549aff1076Skamil 	ASSERT(pData);
11559aff1076Skamil 
11569aff1076Skamil 	HandleOverflow(false, pData, ulLHS, ulRHS, MINUS_STRING);
11579aff1076Skamil }
11589aff1076Skamil 
11599aff1076Skamil void
__ubsan_handle_sub_overflow_abort(struct COverflowData * pData,unsigned long ulLHS,unsigned long ulRHS)11609aff1076Skamil __ubsan_handle_sub_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
11619aff1076Skamil {
11629aff1076Skamil 
11639aff1076Skamil 	ASSERT(pData);
11649aff1076Skamil 
11659aff1076Skamil 	HandleOverflow(true, pData, ulLHS, ulRHS, MINUS_STRING);
11669aff1076Skamil }
11679aff1076Skamil 
11689aff1076Skamil void
__ubsan_handle_type_mismatch(struct CTypeMismatchData * pData,unsigned long ulPointer)11699aff1076Skamil __ubsan_handle_type_mismatch(struct CTypeMismatchData *pData, unsigned long ulPointer)
11709aff1076Skamil {
11719aff1076Skamil 
11729aff1076Skamil 	ASSERT(pData);
11739aff1076Skamil 
11749aff1076Skamil 	HandleTypeMismatch(false, &pData->mLocation, pData->mType, pData->mLogAlignment, pData->mTypeCheckKind, ulPointer);
11759aff1076Skamil }
11769aff1076Skamil 
11779aff1076Skamil void
__ubsan_handle_type_mismatch_abort(struct CTypeMismatchData * pData,unsigned long ulPointer)11789aff1076Skamil __ubsan_handle_type_mismatch_abort(struct CTypeMismatchData *pData, unsigned long ulPointer)
11799aff1076Skamil {
11809aff1076Skamil 
11819aff1076Skamil 	ASSERT(pData);
11829aff1076Skamil 
11839aff1076Skamil 	HandleTypeMismatch(true, &pData->mLocation, pData->mType, pData->mLogAlignment, pData->mTypeCheckKind, ulPointer);
11849aff1076Skamil }
11859aff1076Skamil 
11869aff1076Skamil void
__ubsan_handle_type_mismatch_v1(struct CTypeMismatchData_v1 * pData,unsigned long ulPointer)11879aff1076Skamil __ubsan_handle_type_mismatch_v1(struct CTypeMismatchData_v1 *pData, unsigned long ulPointer)
11889aff1076Skamil {
11899aff1076Skamil 
11909aff1076Skamil 	ASSERT(pData);
11919aff1076Skamil 
11929aff1076Skamil 	HandleTypeMismatch(false, &pData->mLocation, pData->mType, __BIT(pData->mLogAlignment), pData->mTypeCheckKind, ulPointer);
11939aff1076Skamil }
11949aff1076Skamil 
11959aff1076Skamil void
__ubsan_handle_type_mismatch_v1_abort(struct CTypeMismatchData_v1 * pData,unsigned long ulPointer)11969aff1076Skamil __ubsan_handle_type_mismatch_v1_abort(struct CTypeMismatchData_v1 *pData, unsigned long ulPointer)
11979aff1076Skamil {
11989aff1076Skamil 
11999aff1076Skamil 	ASSERT(pData);
12009aff1076Skamil 
12019aff1076Skamil 	HandleTypeMismatch(true, &pData->mLocation, pData->mType, __BIT(pData->mLogAlignment), pData->mTypeCheckKind, ulPointer);
12029aff1076Skamil }
12039aff1076Skamil 
12049aff1076Skamil void
__ubsan_handle_vla_bound_not_positive(struct CVLABoundData * pData,unsigned long ulBound)12059aff1076Skamil __ubsan_handle_vla_bound_not_positive(struct CVLABoundData *pData, unsigned long ulBound)
12069aff1076Skamil {
12079aff1076Skamil 
12089aff1076Skamil 	ASSERT(pData);
12099aff1076Skamil 
12109aff1076Skamil 	HandleVlaBoundNotPositive(false, pData, ulBound);
12119aff1076Skamil }
12129aff1076Skamil 
12139aff1076Skamil void
__ubsan_handle_vla_bound_not_positive_abort(struct CVLABoundData * pData,unsigned long ulBound)12149aff1076Skamil __ubsan_handle_vla_bound_not_positive_abort(struct CVLABoundData *pData, unsigned long ulBound)
12159aff1076Skamil {
12169aff1076Skamil 
12179aff1076Skamil 	ASSERT(pData);
12189aff1076Skamil 
12199aff1076Skamil 	HandleVlaBoundNotPositive(true, pData, ulBound);
12209aff1076Skamil }
12219aff1076Skamil 
12229aff1076Skamil void
__ubsan_handle_implicit_conversion(struct CImplicitConversionData * pData,unsigned long ulFrom,unsigned long ulTo)1223aeb81341Skamil __ubsan_handle_implicit_conversion(struct CImplicitConversionData *pData, unsigned long ulFrom, unsigned long ulTo)
1224aeb81341Skamil {
1225aeb81341Skamil 
1226aeb81341Skamil 	ASSERT(pData);
1227aeb81341Skamil 
1228aeb81341Skamil 	HandleImplicitConversion(false, pData, ulFrom, ulTo);
1229aeb81341Skamil }
1230aeb81341Skamil 
1231aeb81341Skamil void
__ubsan_handle_implicit_conversion_abort(struct CImplicitConversionData * pData,unsigned long ulFrom,unsigned long ulTo)1232aeb81341Skamil __ubsan_handle_implicit_conversion_abort(struct CImplicitConversionData *pData, unsigned long ulFrom, unsigned long ulTo)
1233aeb81341Skamil {
1234aeb81341Skamil 	ASSERT(pData);
1235aeb81341Skamil 
1236aeb81341Skamil 	HandleImplicitConversion(true, pData, ulFrom, ulTo);
1237aeb81341Skamil }
1238aeb81341Skamil 
1239aeb81341Skamil void
__ubsan_get_current_report_data(const char ** ppOutIssueKind,const char ** ppOutMessage,const char ** ppOutFilename,uint32_t * pOutLine,uint32_t * pOutCol,char ** ppOutMemoryAddr)12409aff1076Skamil __ubsan_get_current_report_data(const char **ppOutIssueKind, const char **ppOutMessage, const char **ppOutFilename, uint32_t *pOutLine, uint32_t *pOutCol, char **ppOutMemoryAddr)
12419aff1076Skamil {
12429aff1076Skamil 	/*
12439aff1076Skamil 	 * Unimplemented.
12449aff1076Skamil 	 *
12459aff1076Skamil 	 * The __ubsan_on_report() feature is non trivial to implement in a
12469aff1076Skamil 	 * shared code between the kernel and userland. It's also opening
12479aff1076Skamil 	 * new sets of potential problems as we are not expected to slow down
12489aff1076Skamil 	 * execution of certain kernel subsystems (synchronization issues,
12499aff1076Skamil 	 * interrupt handling etc).
12509aff1076Skamil 	 *
12519aff1076Skamil 	 * A proper solution would need probably a lock-free bounded queue built
1252*84176beaSandvar 	 * with atomic operations with the property of multiple consumers and
12539aff1076Skamil 	 * multiple producers. Maintaining and validating such code is not
12549aff1076Skamil 	 * worth the effort.
12559aff1076Skamil 	 *
12569aff1076Skamil 	 * A legitimate user - besides testing framework - is a debugger plugin
12579aff1076Skamil 	 * intercepting reports from the UBSan instrumentation. For such
12589aff1076Skamil 	 * scenarios it is better to run the Clang/GCC version.
12599aff1076Skamil 	 */
12609aff1076Skamil }
12619aff1076Skamil 
12629aff1076Skamil /* Local utility functions */
12639aff1076Skamil 
12649aff1076Skamil static void
Report(bool isFatal,const char * pFormat,...)12659aff1076Skamil Report(bool isFatal, const char *pFormat, ...)
12669aff1076Skamil {
12679aff1076Skamil 	va_list ap;
12689aff1076Skamil 
12699aff1076Skamil 	ASSERT(pFormat);
12709aff1076Skamil 
12719aff1076Skamil 	va_start(ap, pFormat);
12729aff1076Skamil #if defined(_KERNEL)
1273f8310280Skamil 	if (isFatal || alwaysFatal)
12749aff1076Skamil 		vpanic(pFormat, ap);
12759aff1076Skamil 	else
12769aff1076Skamil 		vprintf(pFormat, ap);
12779aff1076Skamil #else
12789aff1076Skamil 	if (ubsan_flags == -1) {
12799aff1076Skamil 		char buf[1024];
12809aff1076Skamil 		char *p;
12819aff1076Skamil 
12829aff1076Skamil 		ubsan_flags = UBSAN_STDERR;
12839aff1076Skamil 
12849aff1076Skamil 		if (getenv_r("LIBC_UBSAN", buf, sizeof(buf)) != -1) {
12859aff1076Skamil 			for (p = buf; *p; p++) {
12869aff1076Skamil 				switch (*p) {
12879aff1076Skamil 				case 'a':
12889aff1076Skamil 					SET(ubsan_flags, UBSAN_ABORT);
12899aff1076Skamil 					break;
12909aff1076Skamil 				case 'A':
12919aff1076Skamil 					CLR(ubsan_flags, UBSAN_ABORT);
12929aff1076Skamil 					break;
12939aff1076Skamil 				case 'e':
12949aff1076Skamil 					SET(ubsan_flags, UBSAN_STDERR);
12959aff1076Skamil 					break;
12969aff1076Skamil 				case 'E':
12979aff1076Skamil 					CLR(ubsan_flags, UBSAN_STDERR);
12989aff1076Skamil 					break;
12999aff1076Skamil 				case 'l':
13009aff1076Skamil 					SET(ubsan_flags, UBSAN_SYSLOG);
13019aff1076Skamil 					break;
13029aff1076Skamil 				case 'L':
13039aff1076Skamil 					CLR(ubsan_flags, UBSAN_SYSLOG);
13049aff1076Skamil 					break;
13059aff1076Skamil 				case 'o':
13069aff1076Skamil 					SET(ubsan_flags, UBSAN_STDOUT);
13079aff1076Skamil 					break;
13089aff1076Skamil 				case 'O':
13099aff1076Skamil 					CLR(ubsan_flags, UBSAN_STDOUT);
13109aff1076Skamil 					break;
13119aff1076Skamil 				default:
13129aff1076Skamil 					break;
13139aff1076Skamil 				}
13149aff1076Skamil 			}
13159aff1076Skamil 		}
13169aff1076Skamil 	}
13179aff1076Skamil 
13189aff1076Skamil 	// The *v*print* functions can flush the va_list argument.
13199aff1076Skamil 	// Create a local copy for each call to prevent invalid read.
13209aff1076Skamil 	if (ISSET(ubsan_flags, UBSAN_STDOUT)) {
13219aff1076Skamil 		va_list tmp;
13229aff1076Skamil 		va_copy(tmp, ap);
13239aff1076Skamil 		vprintf(pFormat, tmp);
13249aff1076Skamil 		va_end(tmp);
13259aff1076Skamil 		fflush(stdout);
13269aff1076Skamil 	}
13279aff1076Skamil 	if (ISSET(ubsan_flags, UBSAN_STDERR)) {
13289aff1076Skamil 		va_list tmp;
13299aff1076Skamil 		va_copy(tmp, ap);
13309aff1076Skamil 		vfprintf(stderr, pFormat, tmp);
13319aff1076Skamil 		va_end(tmp);
13329aff1076Skamil 		fflush(stderr);
13339aff1076Skamil 	}
13349aff1076Skamil 	if (ISSET(ubsan_flags, UBSAN_SYSLOG)) {
13359aff1076Skamil 		va_list tmp;
13369aff1076Skamil 		va_copy(tmp, ap);
13379aff1076Skamil 		struct syslog_data SyslogData = SYSLOG_DATA_INIT;
13389aff1076Skamil 		ubsan_vsyslog(LOG_DEBUG | LOG_USER, &SyslogData, pFormat, tmp);
13399aff1076Skamil 		va_end(tmp);
13409aff1076Skamil 	}
1341f8310280Skamil 	if (isFatal || alwaysFatal || ISSET(ubsan_flags, UBSAN_ABORT)) {
13429aff1076Skamil 		abort();
1343075cfd7eSkamil 		__unreachable();
13449aff1076Skamil 		/* NOTREACHED */
13459aff1076Skamil 	}
13469aff1076Skamil #endif
13479aff1076Skamil 	va_end(ap);
13489aff1076Skamil }
13499aff1076Skamil 
13509aff1076Skamil static bool
isAlreadyReported(struct CSourceLocation * pLocation)13519aff1076Skamil isAlreadyReported(struct CSourceLocation *pLocation)
13529aff1076Skamil {
13539aff1076Skamil 	/*
13549aff1076Skamil 	 * This code is shared between libc, kernel and standalone usage.
13559aff1076Skamil 	 * It shall work in early bootstrap phase of both of them.
13569aff1076Skamil 	 */
13579aff1076Skamil 
13589aff1076Skamil 	uint32_t siOldValue;
13599aff1076Skamil 	volatile uint32_t *pLine;
13609aff1076Skamil 
13619aff1076Skamil 	ASSERT(pLocation);
13629aff1076Skamil 
13639aff1076Skamil 	pLine = &pLocation->mLine;
13649aff1076Skamil 
13659aff1076Skamil 	do {
13669aff1076Skamil 		siOldValue = *pLine;
13679aff1076Skamil 	} while (__sync_val_compare_and_swap(pLine, siOldValue, siOldValue | ACK_REPORTED) != siOldValue);
13689aff1076Skamil 
13699aff1076Skamil 	return ISSET(siOldValue, ACK_REPORTED);
13709aff1076Skamil }
13719aff1076Skamil 
13729aff1076Skamil static size_t
zDeserializeTypeWidth(struct CTypeDescriptor * pType)13739aff1076Skamil zDeserializeTypeWidth(struct CTypeDescriptor *pType)
13749aff1076Skamil {
13759aff1076Skamil 	size_t zWidth = 0;
13769aff1076Skamil 
13779aff1076Skamil 	ASSERT(pType);
13789aff1076Skamil 
13799aff1076Skamil 	switch (pType->mTypeKind) {
13809aff1076Skamil 	case KIND_INTEGER:
13819aff1076Skamil 		zWidth = __BIT(__SHIFTOUT(pType->mTypeInfo, ~NUMBER_SIGNED_BIT));
13829aff1076Skamil 		break;
13839aff1076Skamil 	case KIND_FLOAT:
13849aff1076Skamil 		zWidth = pType->mTypeInfo;
13859aff1076Skamil 		break;
13869aff1076Skamil 	default:
13879aff1076Skamil 		Report(true, "UBSan: Unknown variable type %#04" PRIx16 "\n", pType->mTypeKind);
1388da4bf28dSmrg 		__unreachable();
13899aff1076Skamil 		/* NOTREACHED */
13909aff1076Skamil 	}
13919aff1076Skamil 
13929aff1076Skamil 	/* Invalid width will be transformed to 0 */
13939aff1076Skamil 	ASSERT(zWidth > 0);
13949aff1076Skamil 
13959aff1076Skamil 	return zWidth;
13969aff1076Skamil }
13979aff1076Skamil 
13989aff1076Skamil static void
DeserializeLocation(char * pBuffer,size_t zBUfferLength,struct CSourceLocation * pLocation)13999aff1076Skamil DeserializeLocation(char *pBuffer, size_t zBUfferLength, struct CSourceLocation *pLocation)
14009aff1076Skamil {
14019aff1076Skamil 
14029aff1076Skamil 	ASSERT(pLocation);
14039aff1076Skamil 	ASSERT(pLocation->mFilename);
14049aff1076Skamil 
14059aff1076Skamil 	snprintf(pBuffer, zBUfferLength, "%s:%" PRIu32 ":%" PRIu32, pLocation->mFilename, pLocation->mLine & (uint32_t)~ACK_REPORTED, pLocation->mColumn);
14069aff1076Skamil }
14079aff1076Skamil 
14089aff1076Skamil #ifdef __SIZEOF_INT128__
14099aff1076Skamil static void
DeserializeUINT128(char * pBuffer,size_t zBUfferLength,struct CTypeDescriptor * pType,__uint128_t U128)14109aff1076Skamil DeserializeUINT128(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, __uint128_t U128)
14119aff1076Skamil {
14129aff1076Skamil 	char szBuf[3]; /* 'XX\0' */
14139aff1076Skamil 	char rgNumber[sizeof(ulongest)];
14149aff1076Skamil 	ssize_t zI;
14159aff1076Skamil 
14169aff1076Skamil 	memcpy(rgNumber, &U128, sizeof(U128));
14179aff1076Skamil 
14189aff1076Skamil 	strlcpy(pBuffer, "Undecoded-128-bit-Integer-Type (0x", zBUfferLength);
14199aff1076Skamil #if BYTE_ORDER == LITTLE_ENDIAN
14209aff1076Skamil 	for (zI = sizeof(ulongest) - 1; zI >= 0; zI--) {
14219aff1076Skamil #else
1422a36fdb10Skamil 	for (zI = 0; zI < (ssize_t)sizeof(ulongest); zI++) {
14239aff1076Skamil #endif
14249aff1076Skamil 		snprintf(szBuf, sizeof(szBuf), "%02" PRIx8, rgNumber[zI]);
14259aff1076Skamil 		strlcat(pBuffer, szBuf, zBUfferLength);
14269aff1076Skamil 	}
14279aff1076Skamil 	strlcat(pBuffer, ")", zBUfferLength);
14289aff1076Skamil }
14299aff1076Skamil #endif
14309aff1076Skamil 
14319aff1076Skamil static void
14329aff1076Skamil DeserializeNumberSigned(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, longest L)
14339aff1076Skamil {
14349aff1076Skamil 
14359aff1076Skamil 	ASSERT(pBuffer);
14369aff1076Skamil 	ASSERT(zBUfferLength > 0);
14379aff1076Skamil 	ASSERT(pType);
14389aff1076Skamil 	ASSERT(ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT));
14399aff1076Skamil 
14409aff1076Skamil 	switch (zDeserializeTypeWidth(pType)) {
14419aff1076Skamil 	default:
14429aff1076Skamil 		ASSERT(0 && "Invalid codepath");
1443075cfd7eSkamil 		__unreachable();
14449aff1076Skamil 		/* NOTREACHED */
14459aff1076Skamil #ifdef __SIZEOF_INT128__
14469aff1076Skamil 	case WIDTH_128:
14479aff1076Skamil 		DeserializeUINT128(pBuffer, zBUfferLength, pType, STATIC_CAST(__uint128_t, L));
14489aff1076Skamil 		break;
14499aff1076Skamil #endif
14509aff1076Skamil 	case WIDTH_64:
1451075cfd7eSkamil 		/* FALLTHROUGH */
14529aff1076Skamil 	case WIDTH_32:
1453075cfd7eSkamil 		/* FALLTHROUGH */
14549aff1076Skamil 	case WIDTH_16:
1455075cfd7eSkamil 		/* FALLTHROUGH */
14569aff1076Skamil 	case WIDTH_8:
14579aff1076Skamil 		snprintf(pBuffer, zBUfferLength, "%" PRId64, STATIC_CAST(int64_t, L));
14589aff1076Skamil 		break;
14599aff1076Skamil 	}
14609aff1076Skamil }
14619aff1076Skamil 
14629aff1076Skamil static void
14639aff1076Skamil DeserializeNumberUnsigned(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, ulongest L)
14649aff1076Skamil {
14659aff1076Skamil 
14669aff1076Skamil 	ASSERT(pBuffer);
14679aff1076Skamil 	ASSERT(zBUfferLength > 0);
14689aff1076Skamil 	ASSERT(pType);
14699aff1076Skamil 	ASSERT(!ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT));
14709aff1076Skamil 
14719aff1076Skamil 	switch (zDeserializeTypeWidth(pType)) {
14729aff1076Skamil 	default:
14739aff1076Skamil 		ASSERT(0 && "Invalid codepath");
1474075cfd7eSkamil 		__unreachable();
14759aff1076Skamil 		/* NOTREACHED */
14769aff1076Skamil #ifdef __SIZEOF_INT128__
14779aff1076Skamil 	case WIDTH_128:
14789aff1076Skamil 		DeserializeUINT128(pBuffer, zBUfferLength, pType, STATIC_CAST(__uint128_t, L));
14799aff1076Skamil 		break;
14809aff1076Skamil #endif
14819aff1076Skamil 	case WIDTH_64:
1482075cfd7eSkamil 		/* FALLTHROUGH */
14839aff1076Skamil 	case WIDTH_32:
1484075cfd7eSkamil 		/* FALLTHROUGH */
14859aff1076Skamil 	case WIDTH_16:
1486075cfd7eSkamil 		/* FALLTHROUGH */
14879aff1076Skamil 	case WIDTH_8:
14889aff1076Skamil 		snprintf(pBuffer, zBUfferLength, "%" PRIu64, STATIC_CAST(uint64_t, L));
14899aff1076Skamil 		break;
14909aff1076Skamil 	}
14919aff1076Skamil }
14929aff1076Skamil 
14939aff1076Skamil #ifndef _KERNEL
14949aff1076Skamil static void
14959aff1076Skamil DeserializeFloatOverPointer(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long *pNumber)
14969aff1076Skamil {
14979aff1076Skamil 	double D;
14989aff1076Skamil #ifdef __HAVE_LONG_DOUBLE
14999aff1076Skamil 	long double LD;
15009aff1076Skamil #endif
15019aff1076Skamil 
15029aff1076Skamil 	ASSERT(pBuffer);
15039aff1076Skamil 	ASSERT(zBUfferLength > 0);
15049aff1076Skamil 	ASSERT(pType);
15059aff1076Skamil 	ASSERT(pNumber);
15069aff1076Skamil 	/*
15079aff1076Skamil 	 * This function handles 64-bit number over a pointer on 32-bit CPUs.
15089aff1076Skamil 	 */
15099aff1076Skamil 	ASSERT((sizeof(*pNumber) * CHAR_BIT < WIDTH_64) || (zDeserializeTypeWidth(pType) >= WIDTH_64));
15109aff1076Skamil 	ASSERT(sizeof(D) == sizeof(uint64_t));
15119aff1076Skamil #ifdef __HAVE_LONG_DOUBLE
15129aff1076Skamil 	ASSERT(sizeof(LD) > sizeof(uint64_t));
15139aff1076Skamil #endif
15149aff1076Skamil 
15159aff1076Skamil 	switch (zDeserializeTypeWidth(pType)) {
15169aff1076Skamil #ifdef __HAVE_LONG_DOUBLE
15179aff1076Skamil 	case WIDTH_128:
1518075cfd7eSkamil 		/* FALLTHROUGH */
15199aff1076Skamil 	case WIDTH_96:
1520075cfd7eSkamil 		/* FALLTHROUGH */
15219aff1076Skamil 	case WIDTH_80:
15229aff1076Skamil 		memcpy(&LD, pNumber, sizeof(long double));
15239aff1076Skamil 		snprintf(pBuffer, zBUfferLength, "%Lg", LD);
15249aff1076Skamil 		break;
15259aff1076Skamil #endif
15269aff1076Skamil 	case WIDTH_64:
15279aff1076Skamil 		memcpy(&D, pNumber, sizeof(double));
15289aff1076Skamil 		snprintf(pBuffer, zBUfferLength, "%g", D);
15299aff1076Skamil 		break;
15309aff1076Skamil 	}
15319aff1076Skamil }
15329aff1076Skamil 
15339aff1076Skamil static void
15349aff1076Skamil DeserializeFloatInlined(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber)
15359aff1076Skamil {
15369aff1076Skamil 	float F;
15379aff1076Skamil 	double D;
15389aff1076Skamil 	uint32_t U32;
15399aff1076Skamil 
15409aff1076Skamil 	ASSERT(pBuffer);
15419aff1076Skamil 	ASSERT(zBUfferLength > 0);
15429aff1076Skamil 	ASSERT(pType);
15439aff1076Skamil 	ASSERT(sizeof(F) == sizeof(uint32_t));
15449aff1076Skamil 	ASSERT(sizeof(D) == sizeof(uint64_t));
15459aff1076Skamil 
15469aff1076Skamil 	switch (zDeserializeTypeWidth(pType)) {
15479aff1076Skamil 	case WIDTH_64:
15488c38a0deSmrg 		ASSERT(sizeof(D) == sizeof(ulNumber));
15498c38a0deSmrg 		memcpy(&D, &ulNumber, sizeof(ulNumber));
15509aff1076Skamil 		snprintf(pBuffer, zBUfferLength, "%g", D);
15519aff1076Skamil 		break;
15529aff1076Skamil 	case WIDTH_32:
15539aff1076Skamil 		/*
15549aff1076Skamil 		 * On supported platforms sizeof(float)==sizeof(uint32_t)
15559aff1076Skamil 		 * unsigned long is either 32 or 64-bit, cast it to 32-bit
15569aff1076Skamil 		 * value in order to call memcpy(3) in an Endian-aware way.
15579aff1076Skamil 		 */
15589aff1076Skamil 		U32 = STATIC_CAST(uint32_t, ulNumber);
15599aff1076Skamil 		memcpy(&F, &U32, sizeof(float));
15609aff1076Skamil 		snprintf(pBuffer, zBUfferLength, "%g", F);
15619aff1076Skamil 		break;
15629aff1076Skamil 	case WIDTH_16:
15639aff1076Skamil 		snprintf(pBuffer, zBUfferLength, "Undecoded-16-bit-Floating-Type (%#04" PRIx16 ")", STATIC_CAST(uint16_t, ulNumber));
15649aff1076Skamil 		break;
15659aff1076Skamil 	}
15669aff1076Skamil }
15679aff1076Skamil #endif
15689aff1076Skamil 
15699aff1076Skamil static longest
15709aff1076Skamil llliGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber)
15719aff1076Skamil {
15729aff1076Skamil 	size_t zNumberWidth;
15739aff1076Skamil 	longest L = 0;
15749aff1076Skamil 
15759aff1076Skamil 	ASSERT(szLocation);
15769aff1076Skamil 	ASSERT(pType);
15779aff1076Skamil 
15789aff1076Skamil 	zNumberWidth = zDeserializeTypeWidth(pType);
15799aff1076Skamil 	switch (zNumberWidth) {
15809aff1076Skamil 	default:
15819aff1076Skamil 		Report(true, "UBSan: Unexpected %zu-Bit Type in %s\n", zNumberWidth, szLocation);
1582da4bf28dSmrg 		__unreachable();
15839aff1076Skamil 		/* NOTREACHED */
15849aff1076Skamil 	case WIDTH_128:
15859aff1076Skamil #ifdef __SIZEOF_INT128__
15869aff1076Skamil 		memcpy(&L, REINTERPRET_CAST(longest *, ulNumber), sizeof(longest));
1587da4bf28dSmrg 		break;
15889aff1076Skamil #else
15899aff1076Skamil 		Report(true, "UBSan: Unexpected 128-Bit Type in %s\n", szLocation);
1590da4bf28dSmrg 		__unreachable();
15919aff1076Skamil 		/* NOTREACHED */
15929aff1076Skamil #endif
15939aff1076Skamil 	case WIDTH_64:
15949aff1076Skamil 		if (sizeof(ulNumber) * CHAR_BIT < WIDTH_64) {
15959aff1076Skamil 			L = *REINTERPRET_CAST(int64_t *, ulNumber);
15969aff1076Skamil 		} else {
15979aff1076Skamil 			L = STATIC_CAST(int64_t, STATIC_CAST(uint64_t, ulNumber));
15989aff1076Skamil 		}
15999aff1076Skamil 		break;
16009aff1076Skamil 	case WIDTH_32:
16019aff1076Skamil 		L = STATIC_CAST(int32_t, STATIC_CAST(uint32_t, ulNumber));
16029aff1076Skamil 		break;
16039aff1076Skamil 	case WIDTH_16:
16049aff1076Skamil 		L = STATIC_CAST(int16_t, STATIC_CAST(uint16_t, ulNumber));
16059aff1076Skamil 		break;
16069aff1076Skamil 	case WIDTH_8:
16079aff1076Skamil 		L = STATIC_CAST(int8_t, STATIC_CAST(uint8_t, ulNumber));
16089aff1076Skamil 		break;
16099aff1076Skamil 	}
16109aff1076Skamil 
16119aff1076Skamil 	return L;
16129aff1076Skamil }
16139aff1076Skamil 
16149aff1076Skamil static ulongest
16159aff1076Skamil llluGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber)
16169aff1076Skamil {
16179aff1076Skamil 	size_t zNumberWidth;
16189aff1076Skamil 	ulongest UL = 0;
16199aff1076Skamil 
16209aff1076Skamil 	ASSERT(pType);
16219aff1076Skamil 
16229aff1076Skamil 	zNumberWidth = zDeserializeTypeWidth(pType);
16239aff1076Skamil 	switch (zNumberWidth) {
16249aff1076Skamil 	default:
16259aff1076Skamil 		Report(true, "UBSan: Unexpected %zu-Bit Type in %s\n", zNumberWidth, szLocation);
1626da4bf28dSmrg 		__unreachable();
16279aff1076Skamil 		/* NOTREACHED */
16289aff1076Skamil 	case WIDTH_128:
16299aff1076Skamil #ifdef __SIZEOF_INT128__
16309aff1076Skamil 		memcpy(&UL, REINTERPRET_CAST(ulongest *, ulNumber), sizeof(ulongest));
16319aff1076Skamil 		break;
16329aff1076Skamil #else
16339aff1076Skamil 		Report(true, "UBSan: Unexpected 128-Bit Type in %s\n", szLocation);
1634da4bf28dSmrg 		__unreachable();
16359aff1076Skamil 		/* NOTREACHED */
16369aff1076Skamil #endif
16379aff1076Skamil 	case WIDTH_64:
16389aff1076Skamil 		if (sizeof(ulNumber) * CHAR_BIT < WIDTH_64) {
16399aff1076Skamil 			UL = *REINTERPRET_CAST(uint64_t *, ulNumber);
16409aff1076Skamil 			break;
16419aff1076Skamil 		}
16429aff1076Skamil 		/* FALLTHROUGH */
16439aff1076Skamil 	case WIDTH_32:
16449aff1076Skamil 		/* FALLTHROUGH */
16459aff1076Skamil 	case WIDTH_16:
16469aff1076Skamil 		/* FALLTHROUGH */
16479aff1076Skamil 	case WIDTH_8:
16489aff1076Skamil 		UL = ulNumber;
16499aff1076Skamil 		break;
16509aff1076Skamil 	}
16519aff1076Skamil 
16529aff1076Skamil 	return UL;
16539aff1076Skamil }
16549aff1076Skamil 
16559aff1076Skamil #ifndef _KERNEL
16569aff1076Skamil static void
16579aff1076Skamil DeserializeNumberFloat(char *szLocation, char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber)
16589aff1076Skamil {
16599aff1076Skamil 	size_t zNumberWidth;
16609aff1076Skamil 
16619aff1076Skamil 	ASSERT(szLocation);
16629aff1076Skamil 	ASSERT(pBuffer);
16639aff1076Skamil 	ASSERT(zBUfferLength > 0);
16649aff1076Skamil 	ASSERT(pType);
16659aff1076Skamil 	ASSERT(pType->mTypeKind == KIND_FLOAT);
16669aff1076Skamil 
16679aff1076Skamil 	zNumberWidth = zDeserializeTypeWidth(pType);
16689aff1076Skamil 	switch (zNumberWidth) {
16699aff1076Skamil 	default:
16709aff1076Skamil 		Report(true, "UBSan: Unexpected %zu-Bit Type in %s\n", zNumberWidth, szLocation);
1671da4bf28dSmrg 		__unreachable();
16729aff1076Skamil 		/* NOTREACHED */
16739aff1076Skamil #ifdef __HAVE_LONG_DOUBLE
16749aff1076Skamil 	case WIDTH_128:
1675075cfd7eSkamil 		/* FALLTHROUGH */
16769aff1076Skamil 	case WIDTH_96:
1677075cfd7eSkamil 		/* FALLTHROUGH */
16789aff1076Skamil 	case WIDTH_80:
16799aff1076Skamil 		DeserializeFloatOverPointer(pBuffer, zBUfferLength, pType, REINTERPRET_CAST(unsigned long *, ulNumber));
16809aff1076Skamil 		break;
16819aff1076Skamil #endif
16829aff1076Skamil 	case WIDTH_64:
16839aff1076Skamil 		if (sizeof(ulNumber) * CHAR_BIT < WIDTH_64) {
16849aff1076Skamil 			DeserializeFloatOverPointer(pBuffer, zBUfferLength, pType, REINTERPRET_CAST(unsigned long *, ulNumber));
16859aff1076Skamil 			break;
16869aff1076Skamil 		}
1687da4bf28dSmrg 		/* FALLTHROUGH */
16889aff1076Skamil 	case WIDTH_32:
1689075cfd7eSkamil 		/* FALLTHROUGH */
16909aff1076Skamil 	case WIDTH_16:
16919aff1076Skamil 		DeserializeFloatInlined(pBuffer, zBUfferLength, pType, ulNumber);
16929aff1076Skamil 		break;
16939aff1076Skamil 	}
16949aff1076Skamil }
16959aff1076Skamil #endif
16969aff1076Skamil 
16979aff1076Skamil static void
16989aff1076Skamil DeserializeNumber(char *szLocation, char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber)
16999aff1076Skamil {
17009aff1076Skamil 
17019aff1076Skamil 	ASSERT(szLocation);
17029aff1076Skamil 	ASSERT(pBuffer);
17039aff1076Skamil 	ASSERT(zBUfferLength > 0);
17049aff1076Skamil 	ASSERT(pType);
17059aff1076Skamil 
17069aff1076Skamil 	switch(pType->mTypeKind) {
17079aff1076Skamil 	case KIND_INTEGER:
17089aff1076Skamil 		if (ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT)) {
17099aff1076Skamil 			longest L = llliGetNumber(szLocation, pType, ulNumber);
17109aff1076Skamil 			DeserializeNumberSigned(pBuffer, zBUfferLength, pType, L);
17119aff1076Skamil 		} else {
17129aff1076Skamil 			ulongest UL = llluGetNumber(szLocation, pType, ulNumber);
17139aff1076Skamil 			DeserializeNumberUnsigned(pBuffer, zBUfferLength, pType, UL);
17149aff1076Skamil 		}
17159aff1076Skamil 		break;
17169aff1076Skamil 	case KIND_FLOAT:
17179aff1076Skamil #ifdef _KERNEL
17189aff1076Skamil 		Report(true, "UBSan: Unexpected Float Type in %s\n", szLocation);
1719da4bf28dSmrg 		__unreachable();
17209aff1076Skamil 		/* NOTREACHED */
17219aff1076Skamil #else
17229aff1076Skamil 		DeserializeNumberFloat(szLocation, pBuffer, zBUfferLength, pType, ulNumber);
17239aff1076Skamil 		break;
1724da4bf28dSmrg #endif
17259aff1076Skamil 	case KIND_UNKNOWN:
17269aff1076Skamil 		Report(true, "UBSan: Unknown Type in %s\n", szLocation);
1727da4bf28dSmrg 		__unreachable();
17289aff1076Skamil 		/* NOTREACHED */
17299aff1076Skamil 	}
17309aff1076Skamil }
17319aff1076Skamil 
17329aff1076Skamil static const char *
17339aff1076Skamil DeserializeTypeCheckKind(uint8_t hhuTypeCheckKind)
17349aff1076Skamil {
17359aff1076Skamil 	const char *rgczTypeCheckKinds[] = {
17369aff1076Skamil 		"load of",
17379aff1076Skamil 		"store to",
17389aff1076Skamil 		"reference binding to",
17399aff1076Skamil 		"member access within",
17409aff1076Skamil 		"member call on",
17419aff1076Skamil 		"constructor call on",
17429aff1076Skamil 		"downcast of",
17439aff1076Skamil 		"downcast of",
17449aff1076Skamil 		"upcast of",
17459aff1076Skamil 		"cast to virtual base of",
17469aff1076Skamil 		"_Nonnull binding to",
17479aff1076Skamil 		"dynamic operation on"
17489aff1076Skamil 	};
17499aff1076Skamil 
17509aff1076Skamil 	ASSERT(__arraycount(rgczTypeCheckKinds) > hhuTypeCheckKind);
17519aff1076Skamil 
17529aff1076Skamil 	return rgczTypeCheckKinds[hhuTypeCheckKind];
17539aff1076Skamil }
17549aff1076Skamil 
17559aff1076Skamil static const char *
17569aff1076Skamil DeserializeBuiltinCheckKind(uint8_t hhuBuiltinCheckKind)
17579aff1076Skamil {
17589aff1076Skamil 	const char *rgczBuiltinCheckKinds[] = {
17599aff1076Skamil 		"ctz()",
17609aff1076Skamil 		"clz()"
17619aff1076Skamil 	};
17629aff1076Skamil 
17639aff1076Skamil 	ASSERT(__arraycount(rgczBuiltinCheckKinds) > hhuBuiltinCheckKind);
17649aff1076Skamil 
17659aff1076Skamil 	return rgczBuiltinCheckKinds[hhuBuiltinCheckKind];
17669aff1076Skamil }
17679aff1076Skamil 
17689aff1076Skamil static const char *
17699aff1076Skamil DeserializeCFICheckKind(uint8_t hhuCFICheckKind)
17709aff1076Skamil {
17719aff1076Skamil 	const char *rgczCFICheckKinds[] = {
17729aff1076Skamil 		"virtual call",					// CFI_VCALL
17739aff1076Skamil 		"non-virtual call",				// CFI_NVCALL
17749aff1076Skamil 		"base-to-derived cast",				// CFI_DERIVEDCAST
17759aff1076Skamil 		"cast to unrelated type",			// CFI_UNRELATEDCAST
17769aff1076Skamil 		"indirect function call",			// CFI_ICALL
17779aff1076Skamil 		"non-virtual pointer to member function call",	// CFI_NVMFCALL
17789aff1076Skamil 		"virtual pointer to member function call",	// CFI_VMFCALL
17799aff1076Skamil 	};
17809aff1076Skamil 
17819aff1076Skamil 	ASSERT(__arraycount(rgczCFICheckKinds) > hhuCFICheckKind);
17829aff1076Skamil 
17839aff1076Skamil 	return rgczCFICheckKinds[hhuCFICheckKind];
17849aff1076Skamil }
17859aff1076Skamil 
1786aeb81341Skamil static const char *
1787aeb81341Skamil DeserializeImplicitConversionCheckKind(uint8_t hhuImplicitConversionCheckKind)
1788aeb81341Skamil {
1789aeb81341Skamil 	const char *rgczImplicitConversionCheckKind[] = {
1790aeb81341Skamil 		"integer truncation",			/* Not used since 2018 October 11th */
1791aeb81341Skamil 		"unsigned integer truncation",
1792aeb81341Skamil 		"signed integer truncation",
1793aeb81341Skamil 		"integer sign change",
1794aeb81341Skamil 		"signed integer trunctation or sign change",
1795aeb81341Skamil 	};
1796aeb81341Skamil 
1797aeb81341Skamil 	ASSERT(__arraycount(rgczImplicitConversionCheckKind) > hhuImplicitConversionCheckKind);
1798aeb81341Skamil 
1799aeb81341Skamil 	return rgczImplicitConversionCheckKind[hhuImplicitConversionCheckKind];
1800aeb81341Skamil }
1801aeb81341Skamil 
18029aff1076Skamil static bool
18039aff1076Skamil isNegativeNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber)
18049aff1076Skamil {
18059aff1076Skamil 
18069aff1076Skamil 	ASSERT(szLocation);
18079aff1076Skamil 	ASSERT(pType);
18089aff1076Skamil 	ASSERT(pType->mTypeKind == KIND_INTEGER);
18099aff1076Skamil 
18109aff1076Skamil 	if (!ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT))
18119aff1076Skamil 		return false;
18129aff1076Skamil 
18139aff1076Skamil 	return llliGetNumber(szLocation, pType, ulNumber) < 0;
18149aff1076Skamil }
18159aff1076Skamil 
18169aff1076Skamil static bool
18179aff1076Skamil isShiftExponentTooLarge(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber, size_t zWidth)
18189aff1076Skamil {
18199aff1076Skamil 
18209aff1076Skamil 	ASSERT(szLocation);
18219aff1076Skamil 	ASSERT(pType);
18229aff1076Skamil 	ASSERT(pType->mTypeKind == KIND_INTEGER);
18239aff1076Skamil 
18249aff1076Skamil 	return llluGetNumber(szLocation, pType, ulNumber) >= zWidth;
18259aff1076Skamil }
1826