xref: /freebsd/sys/kern/kern_ubsan.c (revision 685dc743dc3b5645e34836464128e1c0558b404b)
10645126fSAndrew Turner /*	$NetBSD: ubsan.c,v 1.3 2018/08/03 16:31:04 kamil Exp $	*/
20645126fSAndrew Turner 
30645126fSAndrew Turner /*-
40645126fSAndrew Turner  * Copyright (c) 2018 The NetBSD Foundation, Inc.
50645126fSAndrew Turner  * All rights reserved.
60645126fSAndrew Turner  *
70645126fSAndrew Turner  * Redistribution and use in source and binary forms, with or without
80645126fSAndrew Turner  * modification, are permitted provided that the following conditions
90645126fSAndrew Turner  * are met:
100645126fSAndrew Turner  * 1. Redistributions of source code must retain the above copyright
110645126fSAndrew Turner  *    notice, this list of conditions and the following disclaimer.
120645126fSAndrew Turner  * 2. Redistributions in binary form must reproduce the above copyright
130645126fSAndrew Turner  *    notice, this list of conditions and the following disclaimer in the
140645126fSAndrew Turner  *    documentation and/or other materials provided with the distribution.
150645126fSAndrew Turner  *
160645126fSAndrew Turner  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
170645126fSAndrew Turner  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
180645126fSAndrew Turner  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
190645126fSAndrew Turner  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
200645126fSAndrew Turner  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
210645126fSAndrew Turner  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
220645126fSAndrew Turner  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
230645126fSAndrew Turner  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
240645126fSAndrew Turner  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
250645126fSAndrew Turner  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
260645126fSAndrew Turner  * POSSIBILITY OF SUCH DAMAGE.
270645126fSAndrew Turner  */
280645126fSAndrew Turner 
290645126fSAndrew Turner /*
300645126fSAndrew Turner  * The micro UBSan implementation for the userland (uUBSan) and kernel (kUBSan).
310645126fSAndrew Turner  * The uBSSan versions is suitable for inclusion into libc or used standalone
320645126fSAndrew Turner  * with ATF tests.
330645126fSAndrew Turner  *
340645126fSAndrew Turner  * This file due to long symbol names generated by a compiler during the
350645126fSAndrew Turner  * instrumentation process does not follow the KNF style with 80-column limit.
360645126fSAndrew Turner  */
370645126fSAndrew Turner 
380645126fSAndrew Turner #include <sys/cdefs.h>
394ea56599SAndrew Turner #ifdef __FreeBSD__
404ea56599SAndrew Turner #else
410645126fSAndrew Turner #if defined(_KERNEL)
420645126fSAndrew Turner __KERNEL_RCSID(0, "$NetBSD: ubsan.c,v 1.3 2018/08/03 16:31:04 kamil Exp $");
430645126fSAndrew Turner #else
440645126fSAndrew Turner __RCSID("$NetBSD: ubsan.c,v 1.3 2018/08/03 16:31:04 kamil Exp $");
450645126fSAndrew Turner #endif
464ea56599SAndrew Turner #endif
470645126fSAndrew Turner 
480645126fSAndrew Turner #if defined(_KERNEL)
490645126fSAndrew Turner #include <sys/param.h>
500645126fSAndrew Turner #include <sys/types.h>
514ea56599SAndrew Turner #include <sys/limits.h>
524ea56599SAndrew Turner #include <sys/systm.h>
534ea56599SAndrew Turner #include <machine/_inttypes.h>
544ea56599SAndrew Turner #include <machine/stdarg.h>
554ea56599SAndrew Turner #define	ASSERT(x) KASSERT(x, ("%s: " __STRING(x) " failed", __func__))
564ea56599SAndrew Turner #define	__arraycount(x) nitems(x)
574ea56599SAndrew Turner #define	ISSET(x, y)	((x) & (y))
584ea56599SAndrew Turner #define	__BIT(x)	((uintmax_t)1 << (uintmax_t)(x))
594ea56599SAndrew Turner #define	__LOWEST_SET_BIT(__mask) ((((__mask) - 1) & (__mask)) ^ (__mask))
604ea56599SAndrew Turner #define	__SHIFTOUT(__x, __mask) (((__x) & (__mask)) / __LOWEST_SET_BIT(__mask))
610645126fSAndrew Turner #else
620645126fSAndrew Turner #if defined(_LIBC)
630645126fSAndrew Turner #include "namespace.h"
640645126fSAndrew Turner #endif
650645126fSAndrew Turner #include <sys/param.h>
660645126fSAndrew Turner #include <assert.h>
670645126fSAndrew Turner #include <inttypes.h>
680645126fSAndrew Turner #include <math.h>
690645126fSAndrew Turner #include <signal.h>
700645126fSAndrew Turner #include <stdarg.h>
710645126fSAndrew Turner #include <stdbool.h>
720645126fSAndrew Turner #include <stdint.h>
730645126fSAndrew Turner #include <stdio.h>
740645126fSAndrew Turner #include <stdlib.h>
750645126fSAndrew Turner #include <string.h>
760645126fSAndrew Turner #include <syslog.h>
770645126fSAndrew Turner #include <unistd.h>
780645126fSAndrew Turner #if defined(_LIBC)
790645126fSAndrew Turner #include "extern.h"
800645126fSAndrew Turner #define ubsan_vsyslog vsyslog_ss
810645126fSAndrew Turner #define ASSERT(x) _DIAGASSERT(x)
820645126fSAndrew Turner #else
830645126fSAndrew Turner #define ubsan_vsyslog vsyslog_r
840645126fSAndrew Turner #define ASSERT(x) assert(x)
850645126fSAndrew Turner #endif
860645126fSAndrew Turner /* These macros are available in _KERNEL only */
870645126fSAndrew Turner #define SET(t, f)	((t) |= (f))
880645126fSAndrew Turner #define ISSET(t, f)	((t) & (f))
890645126fSAndrew Turner #define CLR(t, f)	((t) &= ~(f))
900645126fSAndrew Turner #endif
910645126fSAndrew Turner 
920645126fSAndrew Turner #define REINTERPRET_CAST(__dt, __st)	((__dt)(__st))
930645126fSAndrew Turner #define STATIC_CAST(__dt, __st)		((__dt)(__st))
940645126fSAndrew Turner 
950645126fSAndrew Turner #define ACK_REPORTED	__BIT(31)
960645126fSAndrew Turner 
970645126fSAndrew Turner #define MUL_STRING	"*"
980645126fSAndrew Turner #define PLUS_STRING	"+"
990645126fSAndrew Turner #define MINUS_STRING	"-"
1000645126fSAndrew Turner #define DIVREM_STRING	"divrem"
1010645126fSAndrew Turner 
1020645126fSAndrew Turner #define CFI_VCALL		0
1030645126fSAndrew Turner #define CFI_NVCALL		1
1040645126fSAndrew Turner #define CFI_DERIVEDCAST		2
1050645126fSAndrew Turner #define CFI_UNRELATEDCAST	3
1060645126fSAndrew Turner #define CFI_ICALL		4
1070645126fSAndrew Turner #define CFI_NVMFCALL		5
1080645126fSAndrew Turner #define CFI_VMFCALL		6
1090645126fSAndrew Turner 
1100645126fSAndrew Turner #define NUMBER_MAXLEN	128
1110645126fSAndrew Turner #define LOCATION_MAXLEN	(PATH_MAX + 32 /* ':LINE:COLUMN' */)
1120645126fSAndrew Turner 
1130645126fSAndrew Turner #define WIDTH_8		8
1140645126fSAndrew Turner #define WIDTH_16	16
1150645126fSAndrew Turner #define WIDTH_32	32
1160645126fSAndrew Turner #define WIDTH_64	64
1170645126fSAndrew Turner #define WIDTH_80	80
1180645126fSAndrew Turner #define WIDTH_96	96
1190645126fSAndrew Turner #define WIDTH_128	128
1200645126fSAndrew Turner 
1210645126fSAndrew Turner #define NUMBER_SIGNED_BIT	1U
1220645126fSAndrew Turner 
1230645126fSAndrew Turner #if __SIZEOF_INT128__
1240645126fSAndrew Turner typedef __int128 longest;
1250645126fSAndrew Turner typedef unsigned __int128 ulongest;
1260645126fSAndrew Turner #else
1270645126fSAndrew Turner typedef int64_t longest;
1280645126fSAndrew Turner typedef uint64_t ulongest;
1290645126fSAndrew Turner #endif
1300645126fSAndrew Turner 
1310645126fSAndrew Turner #ifndef _KERNEL
1320645126fSAndrew Turner static int ubsan_flags = -1;
1330645126fSAndrew Turner #define UBSAN_ABORT	__BIT(0)
1340645126fSAndrew Turner #define UBSAN_STDOUT	__BIT(1)
1350645126fSAndrew Turner #define UBSAN_STDERR	__BIT(2)
1360645126fSAndrew Turner #define UBSAN_SYSLOG	__BIT(3)
1370645126fSAndrew Turner #endif
1380645126fSAndrew Turner 
1390645126fSAndrew Turner /* Undefined Behavior specific defines and structures */
1400645126fSAndrew Turner 
1410645126fSAndrew Turner #define KIND_INTEGER	0
1420645126fSAndrew Turner #define KIND_FLOAT	1
1430645126fSAndrew Turner #define KIND_UNKNOWN	UINT16_MAX
1440645126fSAndrew Turner 
1450645126fSAndrew Turner struct CSourceLocation {
1460645126fSAndrew Turner 	char *mFilename;
1470645126fSAndrew Turner 	uint32_t mLine;
1480645126fSAndrew Turner 	uint32_t mColumn;
1490645126fSAndrew Turner };
1500645126fSAndrew Turner 
1510645126fSAndrew Turner struct CTypeDescriptor {
1520645126fSAndrew Turner 	uint16_t mTypeKind;
1530645126fSAndrew Turner 	uint16_t mTypeInfo;
1540645126fSAndrew Turner 	uint8_t mTypeName[1];
1550645126fSAndrew Turner };
1560645126fSAndrew Turner 
1570645126fSAndrew Turner struct COverflowData {
1580645126fSAndrew Turner 	struct CSourceLocation mLocation;
1590645126fSAndrew Turner 	struct CTypeDescriptor *mType;
1600645126fSAndrew Turner };
1610645126fSAndrew Turner 
1620645126fSAndrew Turner struct CUnreachableData {
1630645126fSAndrew Turner 	struct CSourceLocation mLocation;
1640645126fSAndrew Turner };
1650645126fSAndrew Turner 
1660645126fSAndrew Turner struct CCFICheckFailData {
1670645126fSAndrew Turner 	uint8_t mCheckKind;
1680645126fSAndrew Turner 	struct CSourceLocation mLocation;
1690645126fSAndrew Turner 	struct CTypeDescriptor *mType;
1700645126fSAndrew Turner };
1710645126fSAndrew Turner 
1720645126fSAndrew Turner struct CDynamicTypeCacheMissData {
1730645126fSAndrew Turner 	struct CSourceLocation mLocation;
1740645126fSAndrew Turner 	struct CTypeDescriptor *mType;
1750645126fSAndrew Turner 	void *mTypeInfo;
1760645126fSAndrew Turner 	uint8_t mTypeCheckKind;
1770645126fSAndrew Turner };
1780645126fSAndrew Turner 
1790645126fSAndrew Turner struct CFunctionTypeMismatchData {
1800645126fSAndrew Turner 	struct CSourceLocation mLocation;
1810645126fSAndrew Turner 	struct CTypeDescriptor *mType;
1820645126fSAndrew Turner };
1830645126fSAndrew Turner 
1840645126fSAndrew Turner struct CInvalidBuiltinData {
1850645126fSAndrew Turner 	struct CSourceLocation mLocation;
1860645126fSAndrew Turner 	uint8_t mKind;
1870645126fSAndrew Turner };
1880645126fSAndrew Turner 
1890645126fSAndrew Turner struct CInvalidValueData {
1900645126fSAndrew Turner 	struct CSourceLocation mLocation;
1910645126fSAndrew Turner 	struct CTypeDescriptor *mType;
1920645126fSAndrew Turner };
1930645126fSAndrew Turner 
1940645126fSAndrew Turner struct CNonNullArgData {
1950645126fSAndrew Turner 	struct CSourceLocation mLocation;
1960645126fSAndrew Turner 	struct CSourceLocation mAttributeLocation;
1970645126fSAndrew Turner 	int mArgIndex;
1980645126fSAndrew Turner };
1990645126fSAndrew Turner 
2000645126fSAndrew Turner struct CNonNullReturnData {
2010645126fSAndrew Turner 	struct CSourceLocation mAttributeLocation;
2020645126fSAndrew Turner };
2030645126fSAndrew Turner 
2040645126fSAndrew Turner struct COutOfBoundsData {
2050645126fSAndrew Turner 	struct CSourceLocation mLocation;
2060645126fSAndrew Turner 	struct CTypeDescriptor *mArrayType;
2070645126fSAndrew Turner 	struct CTypeDescriptor *mIndexType;
2080645126fSAndrew Turner };
2090645126fSAndrew Turner 
2100645126fSAndrew Turner struct CPointerOverflowData {
2110645126fSAndrew Turner 	struct CSourceLocation mLocation;
2120645126fSAndrew Turner };
2130645126fSAndrew Turner 
2140645126fSAndrew Turner struct CShiftOutOfBoundsData {
2150645126fSAndrew Turner 	struct CSourceLocation mLocation;
2160645126fSAndrew Turner 	struct CTypeDescriptor *mLHSType;
2170645126fSAndrew Turner 	struct CTypeDescriptor *mRHSType;
2180645126fSAndrew Turner };
2190645126fSAndrew Turner 
2200645126fSAndrew Turner struct CTypeMismatchData {
2210645126fSAndrew Turner 	struct CSourceLocation mLocation;
2220645126fSAndrew Turner 	struct CTypeDescriptor *mType;
2230645126fSAndrew Turner 	unsigned long mLogAlignment;
2240645126fSAndrew Turner 	uint8_t mTypeCheckKind;
2250645126fSAndrew Turner };
2260645126fSAndrew Turner 
2270645126fSAndrew Turner struct CTypeMismatchData_v1 {
2280645126fSAndrew Turner 	struct CSourceLocation mLocation;
2290645126fSAndrew Turner 	struct CTypeDescriptor *mType;
2300645126fSAndrew Turner 	uint8_t mLogAlignment;
2310645126fSAndrew Turner 	uint8_t mTypeCheckKind;
2320645126fSAndrew Turner };
2330645126fSAndrew Turner 
2340645126fSAndrew Turner struct CVLABoundData {
2350645126fSAndrew Turner 	struct CSourceLocation mLocation;
2360645126fSAndrew Turner 	struct CTypeDescriptor *mType;
2370645126fSAndrew Turner };
2380645126fSAndrew Turner 
2390645126fSAndrew Turner struct CFloatCastOverflowData {
2400645126fSAndrew Turner 	struct CSourceLocation mLocation;	/* This field exists in this struct since 2015 August 11th */
2410645126fSAndrew Turner 	struct CTypeDescriptor *mFromType;
2420645126fSAndrew Turner 	struct CTypeDescriptor *mToType;
2430645126fSAndrew Turner };
2440645126fSAndrew Turner 
2455393cbceSAndrew Turner struct CAlignmentAssumptionData {
2465393cbceSAndrew Turner 	struct CSourceLocation mLocation;
2475393cbceSAndrew Turner 	struct CSourceLocation mAssumptionLocation;
2485393cbceSAndrew Turner 	struct CTypeDescriptor *mType;
2495393cbceSAndrew Turner };
2505393cbceSAndrew Turner 
2510645126fSAndrew Turner /* Local utility functions */
2520645126fSAndrew Turner static void Report(bool isFatal, const char *pFormat, ...) __printflike(2, 3);
2530645126fSAndrew Turner static bool isAlreadyReported(struct CSourceLocation *pLocation);
2540645126fSAndrew Turner static size_t zDeserializeTypeWidth(struct CTypeDescriptor *pType);
2550645126fSAndrew Turner static void DeserializeLocation(char *pBuffer, size_t zBUfferLength, struct CSourceLocation *pLocation);
2560645126fSAndrew Turner #ifdef __SIZEOF_INT128__
2570645126fSAndrew Turner static void DeserializeUINT128(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, __uint128_t U128);
2580645126fSAndrew Turner #endif
2590645126fSAndrew Turner static void DeserializeNumberSigned(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, longest L);
2600645126fSAndrew Turner static void DeserializeNumberUnsigned(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, ulongest L);
2610645126fSAndrew Turner #ifndef _KERNEL
2620645126fSAndrew Turner static void DeserializeFloatOverPointer(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long *pNumber);
2630645126fSAndrew Turner static void DeserializeFloatInlined(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber);
2640645126fSAndrew Turner #endif
2650645126fSAndrew Turner static longest llliGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber);
2660645126fSAndrew Turner static ulongest llluGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber);
2670645126fSAndrew Turner #ifndef _KERNEL
2680645126fSAndrew Turner static void DeserializeNumberFloat(char *szLocation, char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber);
2690645126fSAndrew Turner #endif
2700645126fSAndrew Turner static void DeserializeNumber(char *szLocation, char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber);
2710645126fSAndrew Turner static const char *DeserializeTypeCheckKind(uint8_t hhuTypeCheckKind);
2720645126fSAndrew Turner static const char *DeserializeBuiltinCheckKind(uint8_t hhuBuiltinCheckKind);
2730645126fSAndrew Turner static const char *DeserializeCFICheckKind(uint8_t hhuCFICheckKind);
2740645126fSAndrew Turner static bool isNegativeNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber);
2750645126fSAndrew Turner static bool isShiftExponentTooLarge(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber, size_t zWidth);
2760645126fSAndrew Turner 
2770645126fSAndrew Turner /* Unused in this implementation, emitted by the C++ check dynamic type cast. */
2780645126fSAndrew Turner intptr_t __ubsan_vptr_type_cache[128];
2790645126fSAndrew Turner 
2800645126fSAndrew Turner /* Public symbols used in the instrumentation of the code generation part */
2810645126fSAndrew Turner void __ubsan_handle_add_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
2820645126fSAndrew Turner void __ubsan_handle_add_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
2835393cbceSAndrew Turner void __ubsan_handle_alignment_assumption(struct CAlignmentAssumptionData *pData, unsigned long ulPointer, unsigned long ulAlignment, unsigned long ulOffset);
2845393cbceSAndrew Turner void __ubsan_handle_alignment_assumption_abort(struct CAlignmentAssumptionData *pData, unsigned long ulPointer, unsigned long ulAlignment, unsigned long ulOffset);
2850645126fSAndrew Turner void __ubsan_handle_builtin_unreachable(struct CUnreachableData *pData);
2860645126fSAndrew Turner void __ubsan_handle_cfi_bad_type(struct CCFICheckFailData *pData, unsigned long ulVtable, bool bValidVtable, bool FromUnrecoverableHandler, unsigned long ProgramCounter, unsigned long FramePointer);
2870645126fSAndrew Turner void __ubsan_handle_cfi_check_fail(struct CCFICheckFailData *pData, unsigned long ulValue, unsigned long ulValidVtable);
2880645126fSAndrew Turner void __ubsan_handle_cfi_check_fail_abort(struct CCFICheckFailData *pData, unsigned long ulValue, unsigned long ulValidVtable);
2890645126fSAndrew Turner void __ubsan_handle_divrem_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
2900645126fSAndrew Turner void __ubsan_handle_divrem_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
2910645126fSAndrew Turner void __ubsan_handle_dynamic_type_cache_miss(struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash);
2920645126fSAndrew Turner void __ubsan_handle_dynamic_type_cache_miss_abort(struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash);
2930645126fSAndrew Turner void __ubsan_handle_float_cast_overflow(struct CFloatCastOverflowData *pData, unsigned long ulFrom);
2940645126fSAndrew Turner void __ubsan_handle_float_cast_overflow_abort(struct CFloatCastOverflowData *pData, unsigned long ulFrom);
2950645126fSAndrew Turner void __ubsan_handle_function_type_mismatch(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction);
2960645126fSAndrew Turner void __ubsan_handle_function_type_mismatch_abort(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction);
2970645126fSAndrew Turner void __ubsan_handle_invalid_builtin(struct CInvalidBuiltinData *pData);
2980645126fSAndrew Turner void __ubsan_handle_invalid_builtin_abort(struct CInvalidBuiltinData *pData);
2990645126fSAndrew Turner void __ubsan_handle_load_invalid_value(struct CInvalidValueData *pData, unsigned long ulVal);
3000645126fSAndrew Turner void __ubsan_handle_load_invalid_value_abort(struct CInvalidValueData *pData, unsigned long ulVal);
3010645126fSAndrew Turner void __ubsan_handle_missing_return(struct CUnreachableData *pData);
3020645126fSAndrew Turner void __ubsan_handle_mul_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
3030645126fSAndrew Turner void __ubsan_handle_mul_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
3040645126fSAndrew Turner void __ubsan_handle_negate_overflow(struct COverflowData *pData, unsigned long ulOldVal);
3050645126fSAndrew Turner void __ubsan_handle_negate_overflow_abort(struct COverflowData *pData, unsigned long ulOldVal);
3060645126fSAndrew Turner void __ubsan_handle_nonnull_arg(struct CNonNullArgData *pData);
3070645126fSAndrew Turner void __ubsan_handle_nonnull_arg_abort(struct CNonNullArgData *pData);
3080645126fSAndrew Turner void __ubsan_handle_nonnull_return_v1(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer);
3090645126fSAndrew Turner void __ubsan_handle_nonnull_return_v1_abort(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer);
3100645126fSAndrew Turner void __ubsan_handle_nullability_arg(struct CNonNullArgData *pData);
3110645126fSAndrew Turner void __ubsan_handle_nullability_arg_abort(struct CNonNullArgData *pData);
3120645126fSAndrew Turner void __ubsan_handle_nullability_return_v1(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer);
3130645126fSAndrew Turner void __ubsan_handle_nullability_return_v1_abort(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer);
3140645126fSAndrew Turner void __ubsan_handle_out_of_bounds(struct COutOfBoundsData *pData, unsigned long ulIndex);
3150645126fSAndrew Turner void __ubsan_handle_out_of_bounds_abort(struct COutOfBoundsData *pData, unsigned long ulIndex);
3160645126fSAndrew Turner void __ubsan_handle_pointer_overflow(struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult);
3170645126fSAndrew Turner void __ubsan_handle_pointer_overflow_abort(struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult);
3180645126fSAndrew Turner void __ubsan_handle_shift_out_of_bounds(struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS);
3190645126fSAndrew Turner void __ubsan_handle_shift_out_of_bounds_abort(struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS);
3200645126fSAndrew Turner void __ubsan_handle_sub_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
3210645126fSAndrew Turner void __ubsan_handle_sub_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
3220645126fSAndrew Turner void __ubsan_handle_type_mismatch(struct CTypeMismatchData *pData, unsigned long ulPointer);
3230645126fSAndrew Turner void __ubsan_handle_type_mismatch_abort(struct CTypeMismatchData *pData, unsigned long ulPointer);
3240645126fSAndrew Turner void __ubsan_handle_type_mismatch_v1(struct CTypeMismatchData_v1 *pData, unsigned long ulPointer);
3250645126fSAndrew Turner void __ubsan_handle_type_mismatch_v1_abort(struct CTypeMismatchData_v1 *pData, unsigned long ulPointer);
3260645126fSAndrew Turner void __ubsan_handle_vla_bound_not_positive(struct CVLABoundData *pData, unsigned long ulBound);
3270645126fSAndrew Turner void __ubsan_handle_vla_bound_not_positive_abort(struct CVLABoundData *pData, unsigned long ulBound);
3280645126fSAndrew Turner void __ubsan_get_current_report_data(const char **ppOutIssueKind, const char **ppOutMessage, const char **ppOutFilename, uint32_t *pOutLine, uint32_t *pOutCol, char **ppOutMemoryAddr);
3290645126fSAndrew Turner 
3300645126fSAndrew Turner static void HandleOverflow(bool isFatal, struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS, const char *szOperation);
3310645126fSAndrew Turner static void HandleNegateOverflow(bool isFatal, struct COverflowData *pData, unsigned long ulOldValue);
3320645126fSAndrew Turner static void HandleBuiltinUnreachable(bool isFatal, struct CUnreachableData *pData);
3330645126fSAndrew Turner static void HandleTypeMismatch(bool isFatal, struct CSourceLocation *mLocation, struct CTypeDescriptor *mType, unsigned long mLogAlignment, uint8_t mTypeCheckKind, unsigned long ulPointer);
3340645126fSAndrew Turner static void HandleVlaBoundNotPositive(bool isFatal, struct CVLABoundData *pData, unsigned long ulBound);
3350645126fSAndrew Turner static void HandleOutOfBounds(bool isFatal, struct COutOfBoundsData *pData, unsigned long ulIndex);
3360645126fSAndrew Turner static void HandleShiftOutOfBounds(bool isFatal, struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS);
3370645126fSAndrew Turner static void HandleLoadInvalidValue(bool isFatal, struct CInvalidValueData *pData, unsigned long ulValue);
3380645126fSAndrew Turner static void HandleInvalidBuiltin(bool isFatal, struct CInvalidBuiltinData *pData);
3390645126fSAndrew Turner static void HandleFunctionTypeMismatch(bool isFatal, struct CFunctionTypeMismatchData *pData, unsigned long ulFunction);
3400645126fSAndrew Turner static void HandleCFIBadType(bool isFatal, struct CCFICheckFailData *pData, unsigned long ulVtable, bool *bValidVtable, bool *FromUnrecoverableHandler, unsigned long *ProgramCounter, unsigned long *FramePointer);
3410645126fSAndrew Turner static void HandleDynamicTypeCacheMiss(bool isFatal, struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash);
3420645126fSAndrew Turner static void HandleFloatCastOverflow(bool isFatal, struct CFloatCastOverflowData *pData, unsigned long ulFrom);
3430645126fSAndrew Turner static void HandleMissingReturn(bool isFatal, struct CUnreachableData *pData);
3440645126fSAndrew Turner static void HandleNonnullArg(bool isFatal, struct CNonNullArgData *pData);
3450645126fSAndrew Turner static void HandleNonnullReturn(bool isFatal, struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer);
3460645126fSAndrew Turner static void HandlePointerOverflow(bool isFatal, struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult);
3475393cbceSAndrew Turner static void HandleAlignmentAssumption(bool isFatal, struct CAlignmentAssumptionData *pData, unsigned long ulPointer, unsigned long ulAlignment, unsigned long ulOffset);
3480645126fSAndrew Turner 
3490645126fSAndrew Turner static void
HandleOverflow(bool isFatal,struct COverflowData * pData,unsigned long ulLHS,unsigned long ulRHS,const char * szOperation)3500645126fSAndrew Turner HandleOverflow(bool isFatal, struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS, const char *szOperation)
3510645126fSAndrew Turner {
3520645126fSAndrew Turner 	char szLocation[LOCATION_MAXLEN];
3530645126fSAndrew Turner 	char szLHS[NUMBER_MAXLEN];
3540645126fSAndrew Turner 	char szRHS[NUMBER_MAXLEN];
3550645126fSAndrew Turner 
3560645126fSAndrew Turner 	ASSERT(pData);
3570645126fSAndrew Turner 
3580645126fSAndrew Turner 	if (isAlreadyReported(&pData->mLocation))
3590645126fSAndrew Turner 		return;
3600645126fSAndrew Turner 
3610645126fSAndrew Turner 	DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
3620645126fSAndrew Turner 	DeserializeNumber(szLocation, szLHS, NUMBER_MAXLEN, pData->mType, ulLHS);
3630645126fSAndrew Turner 	DeserializeNumber(szLocation, szRHS, NUMBER_MAXLEN, pData->mType, ulRHS);
3640645126fSAndrew Turner 
3650645126fSAndrew Turner 	Report(isFatal, "UBSan: Undefined Behavior in %s, %s integer overflow: %s %s %s cannot be represented in type %s\n",
3660645126fSAndrew Turner 	       szLocation, ISSET(pData->mType->mTypeInfo, NUMBER_SIGNED_BIT) ? "signed" : "unsigned", szLHS, szOperation, szRHS, pData->mType->mTypeName);
3670645126fSAndrew Turner }
3680645126fSAndrew Turner 
3690645126fSAndrew Turner static void
HandleNegateOverflow(bool isFatal,struct COverflowData * pData,unsigned long ulOldValue)3700645126fSAndrew Turner HandleNegateOverflow(bool isFatal, struct COverflowData *pData, unsigned long ulOldValue)
3710645126fSAndrew Turner {
3720645126fSAndrew Turner 	char szLocation[LOCATION_MAXLEN];
3730645126fSAndrew Turner 	char szOldValue[NUMBER_MAXLEN];
3740645126fSAndrew Turner 
3750645126fSAndrew Turner 	ASSERT(pData);
3760645126fSAndrew Turner 
3770645126fSAndrew Turner 	if (isAlreadyReported(&pData->mLocation))
3780645126fSAndrew Turner 		return;
3790645126fSAndrew Turner 
3800645126fSAndrew Turner 	DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
3810645126fSAndrew Turner 	DeserializeNumber(szLocation, szOldValue, NUMBER_MAXLEN, pData->mType, ulOldValue);
3820645126fSAndrew Turner 
3830645126fSAndrew Turner 	Report(isFatal, "UBSan: Undefined Behavior in %s, negation of %s cannot be represented in type %s\n",
3840645126fSAndrew Turner 	       szLocation, szOldValue, pData->mType->mTypeName);
3850645126fSAndrew Turner }
3860645126fSAndrew Turner 
3870645126fSAndrew Turner static void
HandleBuiltinUnreachable(bool isFatal,struct CUnreachableData * pData)3880645126fSAndrew Turner HandleBuiltinUnreachable(bool isFatal, struct CUnreachableData *pData)
3890645126fSAndrew Turner {
3900645126fSAndrew Turner 	char szLocation[LOCATION_MAXLEN];
3910645126fSAndrew Turner 
3920645126fSAndrew Turner 	ASSERT(pData);
3930645126fSAndrew Turner 
3940645126fSAndrew Turner 	if (isAlreadyReported(&pData->mLocation))
3950645126fSAndrew Turner 		return;
3960645126fSAndrew Turner 
3970645126fSAndrew Turner 	DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
3980645126fSAndrew Turner 
3990645126fSAndrew Turner 	Report(isFatal, "UBSan: Undefined Behavior in %s, calling __builtin_unreachable()\n",
4000645126fSAndrew Turner 	       szLocation);
4010645126fSAndrew Turner }
4020645126fSAndrew Turner 
4030645126fSAndrew Turner static void
HandleTypeMismatch(bool isFatal,struct CSourceLocation * mLocation,struct CTypeDescriptor * mType,unsigned long mLogAlignment,uint8_t mTypeCheckKind,unsigned long ulPointer)4040645126fSAndrew Turner HandleTypeMismatch(bool isFatal, struct CSourceLocation *mLocation, struct CTypeDescriptor *mType, unsigned long mLogAlignment, uint8_t mTypeCheckKind, unsigned long ulPointer)
4050645126fSAndrew Turner {
4060645126fSAndrew Turner 	char szLocation[LOCATION_MAXLEN];
4070645126fSAndrew Turner 
4080645126fSAndrew Turner 	ASSERT(mLocation);
4090645126fSAndrew Turner 	ASSERT(mType);
4100645126fSAndrew Turner 
4110645126fSAndrew Turner 	if (isAlreadyReported(mLocation))
4120645126fSAndrew Turner 		return;
4130645126fSAndrew Turner 
4140645126fSAndrew Turner 	DeserializeLocation(szLocation, LOCATION_MAXLEN, mLocation);
4150645126fSAndrew Turner 
4160645126fSAndrew Turner 	if (ulPointer == 0) {
4170645126fSAndrew Turner 		Report(isFatal, "UBSan: Undefined Behavior in %s, %s null pointer of type %s\n",
4180645126fSAndrew Turner 		       szLocation, DeserializeTypeCheckKind(mTypeCheckKind), mType->mTypeName);
4190645126fSAndrew Turner 	} else if ((mLogAlignment - 1) & ulPointer) {
4200645126fSAndrew Turner 		Report(isFatal, "UBSan: Undefined Behavior in %s, %s misaligned address %p for type %s which requires %ld byte alignment\n",
4210645126fSAndrew Turner 		       szLocation, DeserializeTypeCheckKind(mTypeCheckKind), REINTERPRET_CAST(void *, ulPointer), mType->mTypeName, mLogAlignment);
4220645126fSAndrew Turner 	} else {
4230645126fSAndrew Turner 		Report(isFatal, "UBSan: Undefined Behavior in %s, %s address %p with insufficient space for an object of type %s\n",
4240645126fSAndrew Turner 		       szLocation, DeserializeTypeCheckKind(mTypeCheckKind), REINTERPRET_CAST(void *, ulPointer), mType->mTypeName);
4250645126fSAndrew Turner 	}
4260645126fSAndrew Turner }
4270645126fSAndrew Turner 
4280645126fSAndrew Turner static void
HandleVlaBoundNotPositive(bool isFatal,struct CVLABoundData * pData,unsigned long ulBound)4290645126fSAndrew Turner HandleVlaBoundNotPositive(bool isFatal, struct CVLABoundData *pData, unsigned long ulBound)
4300645126fSAndrew Turner {
4310645126fSAndrew Turner 	char szLocation[LOCATION_MAXLEN];
4320645126fSAndrew Turner 	char szBound[NUMBER_MAXLEN];
4330645126fSAndrew Turner 
4340645126fSAndrew Turner 	ASSERT(pData);
4350645126fSAndrew Turner 
4360645126fSAndrew Turner 	if (isAlreadyReported(&pData->mLocation))
4370645126fSAndrew Turner 		return;
4380645126fSAndrew Turner 
4390645126fSAndrew Turner 	DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
4400645126fSAndrew Turner 	DeserializeNumber(szLocation, szBound, NUMBER_MAXLEN, pData->mType, ulBound);
4410645126fSAndrew Turner 
4420645126fSAndrew Turner 	Report(isFatal, "UBSan: Undefined Behavior in %s, variable length array bound value %s <= 0\n",
4430645126fSAndrew Turner 	       szLocation, szBound);
4440645126fSAndrew Turner }
4450645126fSAndrew Turner 
4460645126fSAndrew Turner static void
HandleOutOfBounds(bool isFatal,struct COutOfBoundsData * pData,unsigned long ulIndex)4470645126fSAndrew Turner HandleOutOfBounds(bool isFatal, struct COutOfBoundsData *pData, unsigned long ulIndex)
4480645126fSAndrew Turner {
4490645126fSAndrew Turner 	char szLocation[LOCATION_MAXLEN];
4500645126fSAndrew Turner 	char szIndex[NUMBER_MAXLEN];
4510645126fSAndrew Turner 
4520645126fSAndrew Turner 	ASSERT(pData);
4530645126fSAndrew Turner 
4540645126fSAndrew Turner 	if (isAlreadyReported(&pData->mLocation))
4550645126fSAndrew Turner 		return;
4560645126fSAndrew Turner 
4570645126fSAndrew Turner 	DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
4580645126fSAndrew Turner 	DeserializeNumber(szLocation, szIndex, NUMBER_MAXLEN, pData->mIndexType, ulIndex);
4590645126fSAndrew Turner 
4600645126fSAndrew Turner 	Report(isFatal, "UBSan: Undefined Behavior in %s, index %s is out of range for type %s\n",
4610645126fSAndrew Turner 	       szLocation, szIndex, pData->mArrayType->mTypeName);
4620645126fSAndrew Turner }
4630645126fSAndrew Turner 
4640645126fSAndrew Turner static void
HandleShiftOutOfBounds(bool isFatal,struct CShiftOutOfBoundsData * pData,unsigned long ulLHS,unsigned long ulRHS)4650645126fSAndrew Turner HandleShiftOutOfBounds(bool isFatal, struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS)
4660645126fSAndrew Turner {
4670645126fSAndrew Turner 	char szLocation[LOCATION_MAXLEN];
4680645126fSAndrew Turner 	char szLHS[NUMBER_MAXLEN];
4690645126fSAndrew Turner 	char szRHS[NUMBER_MAXLEN];
4700645126fSAndrew Turner 
4710645126fSAndrew Turner 	ASSERT(pData);
4720645126fSAndrew Turner 
4730645126fSAndrew Turner 	if (isAlreadyReported(&pData->mLocation))
4740645126fSAndrew Turner 		return;
4750645126fSAndrew Turner 
4760645126fSAndrew Turner 	DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
4770645126fSAndrew Turner 	DeserializeNumber(szLocation, szLHS, NUMBER_MAXLEN, pData->mLHSType, ulLHS);
4780645126fSAndrew Turner 	DeserializeNumber(szLocation, szRHS, NUMBER_MAXLEN, pData->mRHSType, ulRHS);
4790645126fSAndrew Turner 
4800645126fSAndrew Turner 	if (isNegativeNumber(szLocation, pData->mRHSType, ulRHS))
4810645126fSAndrew Turner 		Report(isFatal, "UBSan: Undefined Behavior in %s, shift exponent %s is negative\n",
4820645126fSAndrew Turner 		       szLocation, szRHS);
4830645126fSAndrew Turner 	else if (isShiftExponentTooLarge(szLocation, pData->mRHSType, ulRHS, zDeserializeTypeWidth(pData->mLHSType)))
4840645126fSAndrew Turner 		Report(isFatal, "UBSan: Undefined Behavior in %s, shift exponent %s is too large for %zu-bit type %s\n",
4850645126fSAndrew Turner 		       szLocation, szRHS, zDeserializeTypeWidth(pData->mLHSType), pData->mLHSType->mTypeName);
4860645126fSAndrew Turner 	else if (isNegativeNumber(szLocation, pData->mLHSType, ulLHS))
4870645126fSAndrew Turner 		Report(isFatal, "UBSan: Undefined Behavior in %s, left shift of negative value %s\n",
4880645126fSAndrew Turner 		       szLocation, szLHS);
4890645126fSAndrew Turner 	else
4900645126fSAndrew Turner 		Report(isFatal, "UBSan: Undefined Behavior in %s, left shift of %s by %s places cannot be represented in type %s\n",
4910645126fSAndrew Turner 		       szLocation, szLHS, szRHS, pData->mLHSType->mTypeName);
4920645126fSAndrew Turner }
4930645126fSAndrew Turner 
4940645126fSAndrew Turner static void
HandleLoadInvalidValue(bool isFatal,struct CInvalidValueData * pData,unsigned long ulValue)4950645126fSAndrew Turner HandleLoadInvalidValue(bool isFatal, struct CInvalidValueData *pData, unsigned long ulValue)
4960645126fSAndrew Turner {
4970645126fSAndrew Turner 	char szLocation[LOCATION_MAXLEN];
4980645126fSAndrew Turner 	char szValue[NUMBER_MAXLEN];
4990645126fSAndrew Turner 
5000645126fSAndrew Turner 	ASSERT(pData);
5010645126fSAndrew Turner 
5020645126fSAndrew Turner 	if (isAlreadyReported(&pData->mLocation))
5030645126fSAndrew Turner 		return;
5040645126fSAndrew Turner 
5050645126fSAndrew Turner 	DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
5060645126fSAndrew Turner 	DeserializeNumber(szLocation, szValue, NUMBER_MAXLEN, pData->mType, ulValue);
5070645126fSAndrew Turner 
5080645126fSAndrew Turner 	Report(isFatal, "UBSan: Undefined Behavior in %s, load of value %s is not a valid value for type %s\n",
5090645126fSAndrew Turner 	       szLocation, szValue, pData->mType->mTypeName);
5100645126fSAndrew Turner }
5110645126fSAndrew Turner 
5120645126fSAndrew Turner static void
HandleInvalidBuiltin(bool isFatal,struct CInvalidBuiltinData * pData)5130645126fSAndrew Turner HandleInvalidBuiltin(bool isFatal, struct CInvalidBuiltinData *pData)
5140645126fSAndrew Turner {
5150645126fSAndrew Turner 	char szLocation[LOCATION_MAXLEN];
5160645126fSAndrew Turner 
5170645126fSAndrew Turner 	ASSERT(pData);
5180645126fSAndrew Turner 
5190645126fSAndrew Turner 	if (isAlreadyReported(&pData->mLocation))
5200645126fSAndrew Turner 		return;
5210645126fSAndrew Turner 
5220645126fSAndrew Turner 	DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
5230645126fSAndrew Turner 
5240645126fSAndrew Turner 	Report(isFatal, "UBSan: Undefined Behavior in %s, passing zero to %s, which is not a valid argument\n",
5250645126fSAndrew Turner 	       szLocation, DeserializeBuiltinCheckKind(pData->mKind));
5260645126fSAndrew Turner }
5270645126fSAndrew Turner 
5280645126fSAndrew Turner static void
HandleFunctionTypeMismatch(bool isFatal,struct CFunctionTypeMismatchData * pData,unsigned long ulFunction)5290645126fSAndrew Turner HandleFunctionTypeMismatch(bool isFatal, struct CFunctionTypeMismatchData *pData, unsigned long ulFunction)
5300645126fSAndrew Turner {
5310645126fSAndrew Turner 	char szLocation[LOCATION_MAXLEN];
5320645126fSAndrew Turner 
5330645126fSAndrew Turner 	/*
5340645126fSAndrew Turner 	 * There is no a portable C solution to translate an address of a
5350645126fSAndrew Turner 	 * function to its name. On the cost of getting this routine simple
5360645126fSAndrew Turner 	 * and portable without ifdefs between the userland and the kernel
5370645126fSAndrew Turner 	 * just print the address of the function as-is.
5380645126fSAndrew Turner 	 *
5390645126fSAndrew Turner 	 * For better diagnostic messages in the userland, users shall use
5400645126fSAndrew Turner 	 * the full upstream version shipped along with the compiler toolchain.
5410645126fSAndrew Turner 	 */
5420645126fSAndrew Turner 
5430645126fSAndrew Turner 	ASSERT(pData);
5440645126fSAndrew Turner 
5450645126fSAndrew Turner 	if (isAlreadyReported(&pData->mLocation))
5460645126fSAndrew Turner 		return;
5470645126fSAndrew Turner 
5480645126fSAndrew Turner 	DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
5490645126fSAndrew Turner 
5500645126fSAndrew Turner 	Report(isFatal, "UBSan: Undefined Behavior in %s, call to function %#lx through pointer to incorrect function type %s\n",
5510645126fSAndrew Turner 	      szLocation, ulFunction, pData->mType->mTypeName);
5520645126fSAndrew Turner }
5530645126fSAndrew Turner 
5540645126fSAndrew Turner static void
HandleCFIBadType(bool isFatal,struct CCFICheckFailData * pData,unsigned long ulVtable,bool * bValidVtable,bool * FromUnrecoverableHandler,unsigned long * ProgramCounter,unsigned long * FramePointer)5550645126fSAndrew Turner HandleCFIBadType(bool isFatal, struct CCFICheckFailData *pData, unsigned long ulVtable, bool *bValidVtable, bool *FromUnrecoverableHandler, unsigned long *ProgramCounter, unsigned long *FramePointer)
5560645126fSAndrew Turner {
5570645126fSAndrew Turner 	char szLocation[LOCATION_MAXLEN];
5580645126fSAndrew Turner 
5590645126fSAndrew Turner 	/*
5600645126fSAndrew Turner 	 * This is a minimal implementation without diving into C++
5610645126fSAndrew Turner 	 * specifics and (Itanium) ABI deserialization.
5620645126fSAndrew Turner 	 */
5630645126fSAndrew Turner 
5640645126fSAndrew Turner 	ASSERT(pData);
5650645126fSAndrew Turner 
5660645126fSAndrew Turner 	if (isAlreadyReported(&pData->mLocation))
5670645126fSAndrew Turner 		return;
5680645126fSAndrew Turner 
5690645126fSAndrew Turner 	DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
5700645126fSAndrew Turner 
5710645126fSAndrew Turner 	if (pData->mCheckKind == CFI_ICALL || pData->mCheckKind == CFI_VMFCALL) {
5720645126fSAndrew Turner 		Report(isFatal, "UBSan: Undefined Behavior in %s, control flow integrity check for type %s failed during %s (vtable address %#lx)\n",
5730645126fSAndrew Turner 		      szLocation, pData->mType->mTypeName, DeserializeCFICheckKind(pData->mCheckKind), ulVtable);
5740645126fSAndrew Turner 	} else {
5750645126fSAndrew Turner 		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",
5760645126fSAndrew Turner 		      szLocation, pData->mType->mTypeName, DeserializeCFICheckKind(pData->mCheckKind), ulVtable, *bValidVtable ? "valid" : "invalid", *FromUnrecoverableHandler ? "unrecoverable" : "recoverable", *ProgramCounter, *FramePointer);
5770645126fSAndrew Turner 	}
5780645126fSAndrew Turner }
5790645126fSAndrew Turner 
5800645126fSAndrew Turner static void
HandleDynamicTypeCacheMiss(bool isFatal,struct CDynamicTypeCacheMissData * pData,unsigned long ulPointer,unsigned long ulHash)5810645126fSAndrew Turner HandleDynamicTypeCacheMiss(bool isFatal, struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash)
5820645126fSAndrew Turner {
5830645126fSAndrew Turner #if 0
5840645126fSAndrew Turner 	char szLocation[LOCATION_MAXLEN];
5850645126fSAndrew Turner 
5860645126fSAndrew Turner 	/*
5870645126fSAndrew Turner 	 * Unimplemented.
5880645126fSAndrew Turner 	 *
5890645126fSAndrew Turner 	 * This UBSan handler is special as the check has to be impelemented
5900645126fSAndrew Turner 	 * in an implementation. In order to handle it there is need to
5910645126fSAndrew Turner 	 * introspect into C++ ABI internals (RTTI) and use low-level
5920645126fSAndrew Turner 	 * C++ runtime interfaces.
5930645126fSAndrew Turner 	 */
5940645126fSAndrew Turner 
5950645126fSAndrew Turner 	ASSERT(pData);
5960645126fSAndrew Turner 
5970645126fSAndrew Turner 	if (isAlreadyReported(&pData->mLocation))
5980645126fSAndrew Turner 		return;
5990645126fSAndrew Turner 
6000645126fSAndrew Turner 	DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
6010645126fSAndrew Turner 
6020645126fSAndrew Turner 	Report(isFatal, "UBSan: Undefined Behavior in %s, %s address %#lx which might not point to an object of type %s\n"
6030645126fSAndrew Turner 	      szLocation, DeserializeTypeCheckKind(pData->mTypeCheckKind), ulPointer, pData->mType);
6040645126fSAndrew Turner #endif
6050645126fSAndrew Turner }
6060645126fSAndrew Turner 
6070645126fSAndrew Turner static void
HandleFloatCastOverflow(bool isFatal,struct CFloatCastOverflowData * pData,unsigned long ulFrom)6080645126fSAndrew Turner HandleFloatCastOverflow(bool isFatal, struct CFloatCastOverflowData *pData, unsigned long ulFrom)
6090645126fSAndrew Turner {
6100645126fSAndrew Turner 	char szLocation[LOCATION_MAXLEN];
6110645126fSAndrew Turner 	char szFrom[NUMBER_MAXLEN];
6120645126fSAndrew Turner 
6130645126fSAndrew Turner 	ASSERT(pData);
6140645126fSAndrew Turner 
6150645126fSAndrew Turner 	if (isAlreadyReported(&pData->mLocation))
6160645126fSAndrew Turner 		return;
6170645126fSAndrew Turner 
6180645126fSAndrew Turner 	DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
6190645126fSAndrew Turner 	DeserializeNumber(szLocation, szFrom, NUMBER_MAXLEN, pData->mFromType, ulFrom);
6200645126fSAndrew Turner 
6210645126fSAndrew Turner 	Report(isFatal, "UBSan: Undefined Behavior in %s, %s (of type %s) is outside the range of representable values of type %s\n",
6220645126fSAndrew Turner 	       szLocation, szFrom, pData->mFromType->mTypeName, pData->mToType->mTypeName);
6230645126fSAndrew Turner }
6240645126fSAndrew Turner 
6250645126fSAndrew Turner static void
HandleMissingReturn(bool isFatal,struct CUnreachableData * pData)6260645126fSAndrew Turner HandleMissingReturn(bool isFatal, struct CUnreachableData *pData)
6270645126fSAndrew Turner {
6280645126fSAndrew Turner 	char szLocation[LOCATION_MAXLEN];
6290645126fSAndrew Turner 
6300645126fSAndrew Turner 	ASSERT(pData);
6310645126fSAndrew Turner 
6320645126fSAndrew Turner 	if (isAlreadyReported(&pData->mLocation))
6330645126fSAndrew Turner 		return;
6340645126fSAndrew Turner 
6350645126fSAndrew Turner 	DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
6360645126fSAndrew Turner 
6370645126fSAndrew Turner 	Report(isFatal, "UBSan: Undefined Behavior in %s, execution reached the end of a value-returning function without returning a value\n",
6380645126fSAndrew Turner 	       szLocation);
6390645126fSAndrew Turner }
6400645126fSAndrew Turner 
6410645126fSAndrew Turner static void
HandleNonnullArg(bool isFatal,struct CNonNullArgData * pData)6420645126fSAndrew Turner HandleNonnullArg(bool isFatal, struct CNonNullArgData *pData)
6430645126fSAndrew Turner {
6440645126fSAndrew Turner 	char szLocation[LOCATION_MAXLEN];
6450645126fSAndrew Turner 	char szAttributeLocation[LOCATION_MAXLEN];
6460645126fSAndrew Turner 
6470645126fSAndrew Turner 	ASSERT(pData);
6480645126fSAndrew Turner 
6490645126fSAndrew Turner 	if (isAlreadyReported(&pData->mLocation))
6500645126fSAndrew Turner 		return;
6510645126fSAndrew Turner 
6520645126fSAndrew Turner 	DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
6530645126fSAndrew Turner 	if (pData->mAttributeLocation.mFilename)
6540645126fSAndrew Turner 		DeserializeLocation(szAttributeLocation, LOCATION_MAXLEN, &pData->mAttributeLocation);
6550645126fSAndrew Turner 	else
6560645126fSAndrew Turner 		szAttributeLocation[0] = '\0';
6570645126fSAndrew Turner 
6580645126fSAndrew Turner 	Report(isFatal, "UBSan: Undefined Behavior in %s, null pointer passed as argument %d, which is declared to never be null%s%s\n",
6590645126fSAndrew Turner 	       szLocation, pData->mArgIndex, pData->mAttributeLocation.mFilename ? ", nonnull/_Nonnull specified in " : "", szAttributeLocation);
6600645126fSAndrew Turner }
6610645126fSAndrew Turner 
6620645126fSAndrew Turner static void
HandleNonnullReturn(bool isFatal,struct CNonNullReturnData * pData,struct CSourceLocation * pLocationPointer)6630645126fSAndrew Turner HandleNonnullReturn(bool isFatal, struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
6640645126fSAndrew Turner {
6650645126fSAndrew Turner 	char szLocation[LOCATION_MAXLEN];
6660645126fSAndrew Turner 	char szAttributeLocation[LOCATION_MAXLEN];
6670645126fSAndrew Turner 
6680645126fSAndrew Turner 	ASSERT(pData);
6690645126fSAndrew Turner 	ASSERT(pLocationPointer);
6700645126fSAndrew Turner 
6710645126fSAndrew Turner 	if (isAlreadyReported(pLocationPointer))
6720645126fSAndrew Turner 		return;
6730645126fSAndrew Turner 
6740645126fSAndrew Turner 	DeserializeLocation(szLocation, LOCATION_MAXLEN, pLocationPointer);
6750645126fSAndrew Turner 	if (pData->mAttributeLocation.mFilename)
6760645126fSAndrew Turner 		DeserializeLocation(szAttributeLocation, LOCATION_MAXLEN, &pData->mAttributeLocation);
6770645126fSAndrew Turner 	else
6780645126fSAndrew Turner 		szAttributeLocation[0] = '\0';
6790645126fSAndrew Turner 
6800645126fSAndrew Turner 	Report(isFatal, "UBSan: Undefined Behavior in %s, null pointer returned from function declared to never return null%s%s\n",
6810645126fSAndrew Turner 	       szLocation, pData->mAttributeLocation.mFilename ? ", nonnull/_Nonnull specified in " : "", szAttributeLocation);
6820645126fSAndrew Turner }
6830645126fSAndrew Turner 
6840645126fSAndrew Turner static void
HandlePointerOverflow(bool isFatal,struct CPointerOverflowData * pData,unsigned long ulBase,unsigned long ulResult)6850645126fSAndrew Turner HandlePointerOverflow(bool isFatal, struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult)
6860645126fSAndrew Turner {
6870645126fSAndrew Turner 	char szLocation[LOCATION_MAXLEN];
6880645126fSAndrew Turner 
6890645126fSAndrew Turner 	ASSERT(pData);
6900645126fSAndrew Turner 
6910645126fSAndrew Turner 	if (isAlreadyReported(&pData->mLocation))
6920645126fSAndrew Turner 		return;
6930645126fSAndrew Turner 
6940645126fSAndrew Turner 	DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
6950645126fSAndrew Turner 
6960645126fSAndrew Turner 	Report(isFatal, "UBSan: Undefined Behavior in %s, pointer expression with base %#lx overflowed to %#lx\n",
6970645126fSAndrew Turner 	       szLocation, ulBase, ulResult);
6980645126fSAndrew Turner }
6990645126fSAndrew Turner 
7005393cbceSAndrew Turner static void
HandleAlignmentAssumption(bool isFatal,struct CAlignmentAssumptionData * pData,unsigned long ulPointer,unsigned long ulAlignment,unsigned long ulOffset)7015393cbceSAndrew Turner HandleAlignmentAssumption(bool isFatal, struct CAlignmentAssumptionData *pData, unsigned long ulPointer, unsigned long ulAlignment, unsigned long ulOffset)
7025393cbceSAndrew Turner {
7035393cbceSAndrew Turner 	char szLocation[LOCATION_MAXLEN];
7045393cbceSAndrew Turner 	char szAssumptionLocation[LOCATION_MAXLEN];
7055393cbceSAndrew Turner 	unsigned long ulRealPointer;
7065393cbceSAndrew Turner 
7075393cbceSAndrew Turner 	ASSERT(pData);
7085393cbceSAndrew Turner 
7095393cbceSAndrew Turner 	if (isAlreadyReported(&pData->mLocation))
7105393cbceSAndrew Turner 		return;
7115393cbceSAndrew Turner 
7125393cbceSAndrew Turner 	DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
7135393cbceSAndrew Turner 
7145393cbceSAndrew Turner 	ulRealPointer = ulPointer - ulOffset;
7155393cbceSAndrew Turner 
7165393cbceSAndrew Turner 	if (pData->mAssumptionLocation.mFilename != NULL) {
7175393cbceSAndrew Turner 		DeserializeLocation(szAssumptionLocation, LOCATION_MAXLEN,
7185393cbceSAndrew Turner 		    &pData->mAssumptionLocation);
719*2aad9062SGordon Bergling 		Report(isFatal, "UBSan: Undefined Behavior in %s, alignment assumption of %#lx for pointer %#lx (offset %#lx), assumption made in %s\n",
7205393cbceSAndrew Turner 		    szLocation, ulAlignment, ulRealPointer, ulOffset,
7215393cbceSAndrew Turner 		    szAssumptionLocation);
7225393cbceSAndrew Turner 	} else {
7235393cbceSAndrew Turner 		Report(isFatal, "UBSan: Undefined Behavior in %s, alignment assumption of %#lx for pointer %#lx (offset %#lx)\n",
7245393cbceSAndrew Turner 		    szLocation, ulAlignment, ulRealPointer, ulOffset);
7255393cbceSAndrew Turner 	}
7265393cbceSAndrew Turner }
7275393cbceSAndrew Turner 
7280645126fSAndrew Turner /* Definions of public symbols emitted by the instrumentation code */
7290645126fSAndrew Turner void
__ubsan_handle_add_overflow(struct COverflowData * pData,unsigned long ulLHS,unsigned long ulRHS)7300645126fSAndrew Turner __ubsan_handle_add_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
7310645126fSAndrew Turner {
7320645126fSAndrew Turner 
7330645126fSAndrew Turner 	ASSERT(pData);
7340645126fSAndrew Turner 
7350645126fSAndrew Turner 	HandleOverflow(false, pData, ulLHS, ulRHS, PLUS_STRING);
7360645126fSAndrew Turner }
7370645126fSAndrew Turner 
7380645126fSAndrew Turner void
__ubsan_handle_add_overflow_abort(struct COverflowData * pData,unsigned long ulLHS,unsigned long ulRHS)7390645126fSAndrew Turner __ubsan_handle_add_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
7400645126fSAndrew Turner {
7410645126fSAndrew Turner 
7420645126fSAndrew Turner 	ASSERT(pData);
7430645126fSAndrew Turner 
7440645126fSAndrew Turner 	HandleOverflow(true, pData, ulLHS, ulRHS, PLUS_STRING);
7450645126fSAndrew Turner }
7460645126fSAndrew Turner 
7470645126fSAndrew Turner void
__ubsan_handle_alignment_assumption(struct CAlignmentAssumptionData * pData,unsigned long ulPointer,unsigned long ulAlignment,unsigned long ulOffset)7485393cbceSAndrew Turner __ubsan_handle_alignment_assumption(struct CAlignmentAssumptionData *pData, unsigned long ulPointer, unsigned long ulAlignment, unsigned long ulOffset)
7495393cbceSAndrew Turner {
7505393cbceSAndrew Turner 
7515393cbceSAndrew Turner 	ASSERT(pData);
7525393cbceSAndrew Turner 
7535393cbceSAndrew Turner 	HandleAlignmentAssumption(false, pData, ulPointer, ulAlignment, ulOffset);
7545393cbceSAndrew Turner }
7555393cbceSAndrew Turner 
7565393cbceSAndrew Turner void
__ubsan_handle_alignment_assumption_abort(struct CAlignmentAssumptionData * pData,unsigned long ulPointer,unsigned long ulAlignment,unsigned long ulOffset)7575393cbceSAndrew Turner __ubsan_handle_alignment_assumption_abort(struct CAlignmentAssumptionData *pData, unsigned long ulPointer, unsigned long ulAlignment, unsigned long ulOffset)
7585393cbceSAndrew Turner {
7595393cbceSAndrew Turner 
7605393cbceSAndrew Turner 	ASSERT(pData);
7615393cbceSAndrew Turner 
7625393cbceSAndrew Turner 	HandleAlignmentAssumption(true, pData, ulPointer, ulAlignment, ulOffset);
7635393cbceSAndrew Turner }
7645393cbceSAndrew Turner 
7655393cbceSAndrew Turner void
__ubsan_handle_builtin_unreachable(struct CUnreachableData * pData)7660645126fSAndrew Turner __ubsan_handle_builtin_unreachable(struct CUnreachableData *pData)
7670645126fSAndrew Turner {
7680645126fSAndrew Turner 
7690645126fSAndrew Turner 	ASSERT(pData);
7700645126fSAndrew Turner 
7710645126fSAndrew Turner 	HandleBuiltinUnreachable(true, pData);
7720645126fSAndrew Turner }
7730645126fSAndrew Turner 
7740645126fSAndrew Turner void
__ubsan_handle_cfi_bad_type(struct CCFICheckFailData * pData,unsigned long ulVtable,bool bValidVtable,bool FromUnrecoverableHandler,unsigned long ProgramCounter,unsigned long FramePointer)7750645126fSAndrew Turner __ubsan_handle_cfi_bad_type(struct CCFICheckFailData *pData, unsigned long ulVtable, bool bValidVtable, bool FromUnrecoverableHandler, unsigned long ProgramCounter, unsigned long FramePointer)
7760645126fSAndrew Turner {
7770645126fSAndrew Turner 
7780645126fSAndrew Turner 	ASSERT(pData);
7790645126fSAndrew Turner 
7800645126fSAndrew Turner 	HandleCFIBadType(false, pData, ulVtable, &bValidVtable, &FromUnrecoverableHandler, &ProgramCounter, &FramePointer);
7810645126fSAndrew Turner }
7820645126fSAndrew Turner 
7830645126fSAndrew Turner void
__ubsan_handle_cfi_check_fail(struct CCFICheckFailData * pData,unsigned long ulValue,unsigned long ulValidVtable)7840645126fSAndrew Turner __ubsan_handle_cfi_check_fail(struct CCFICheckFailData *pData, unsigned long ulValue, unsigned long ulValidVtable)
7850645126fSAndrew Turner {
7860645126fSAndrew Turner 
7870645126fSAndrew Turner 	ASSERT(pData);
7880645126fSAndrew Turner 
7890645126fSAndrew Turner 	HandleCFIBadType(false, pData, ulValue, 0, 0, 0, 0);
7900645126fSAndrew Turner }
7910645126fSAndrew Turner 
7920645126fSAndrew Turner void
__ubsan_handle_cfi_check_fail_abort(struct CCFICheckFailData * pData,unsigned long ulValue,unsigned long ulValidVtable)7930645126fSAndrew Turner __ubsan_handle_cfi_check_fail_abort(struct CCFICheckFailData *pData, unsigned long ulValue, unsigned long ulValidVtable)
7940645126fSAndrew Turner {
7950645126fSAndrew Turner 
7960645126fSAndrew Turner 	ASSERT(pData);
7970645126fSAndrew Turner 
7980645126fSAndrew Turner 	HandleCFIBadType(true, pData, ulValue, 0, 0, 0, 0);
7990645126fSAndrew Turner }
8000645126fSAndrew Turner 
8010645126fSAndrew Turner void
__ubsan_handle_divrem_overflow(struct COverflowData * pData,unsigned long ulLHS,unsigned long ulRHS)8020645126fSAndrew Turner __ubsan_handle_divrem_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
8030645126fSAndrew Turner {
8040645126fSAndrew Turner 
8050645126fSAndrew Turner 	ASSERT(pData);
8060645126fSAndrew Turner 
8070645126fSAndrew Turner 	HandleOverflow(false, pData, ulLHS, ulRHS, DIVREM_STRING);
8080645126fSAndrew Turner }
8090645126fSAndrew Turner 
8100645126fSAndrew Turner void
__ubsan_handle_divrem_overflow_abort(struct COverflowData * pData,unsigned long ulLHS,unsigned long ulRHS)8110645126fSAndrew Turner __ubsan_handle_divrem_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
8120645126fSAndrew Turner {
8130645126fSAndrew Turner 
8140645126fSAndrew Turner 	ASSERT(pData);
8150645126fSAndrew Turner 
8160645126fSAndrew Turner 	HandleOverflow(true, pData, ulLHS, ulRHS, DIVREM_STRING);
8170645126fSAndrew Turner }
8180645126fSAndrew Turner 
8190645126fSAndrew Turner void
__ubsan_handle_dynamic_type_cache_miss(struct CDynamicTypeCacheMissData * pData,unsigned long ulPointer,unsigned long ulHash)8200645126fSAndrew Turner __ubsan_handle_dynamic_type_cache_miss(struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash)
8210645126fSAndrew Turner {
8220645126fSAndrew Turner 
8230645126fSAndrew Turner 	ASSERT(pData);
8240645126fSAndrew Turner 
8250645126fSAndrew Turner 	HandleDynamicTypeCacheMiss(false, pData, ulPointer, ulHash);
8260645126fSAndrew Turner }
8270645126fSAndrew Turner 
8280645126fSAndrew Turner void
__ubsan_handle_dynamic_type_cache_miss_abort(struct CDynamicTypeCacheMissData * pData,unsigned long ulPointer,unsigned long ulHash)8290645126fSAndrew Turner __ubsan_handle_dynamic_type_cache_miss_abort(struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash)
8300645126fSAndrew Turner {
8310645126fSAndrew Turner 
8320645126fSAndrew Turner 	ASSERT(pData);
8330645126fSAndrew Turner 
8340645126fSAndrew Turner 	HandleDynamicTypeCacheMiss(false, pData, ulPointer, ulHash);
8350645126fSAndrew Turner }
8360645126fSAndrew Turner 
8370645126fSAndrew Turner void
__ubsan_handle_float_cast_overflow(struct CFloatCastOverflowData * pData,unsigned long ulFrom)8380645126fSAndrew Turner __ubsan_handle_float_cast_overflow(struct CFloatCastOverflowData *pData, unsigned long ulFrom)
8390645126fSAndrew Turner {
8400645126fSAndrew Turner 
8410645126fSAndrew Turner 	ASSERT(pData);
8420645126fSAndrew Turner 
8430645126fSAndrew Turner 	HandleFloatCastOverflow(false, pData, ulFrom);
8440645126fSAndrew Turner }
8450645126fSAndrew Turner 
8460645126fSAndrew Turner void
__ubsan_handle_float_cast_overflow_abort(struct CFloatCastOverflowData * pData,unsigned long ulFrom)8470645126fSAndrew Turner __ubsan_handle_float_cast_overflow_abort(struct CFloatCastOverflowData *pData, unsigned long ulFrom)
8480645126fSAndrew Turner {
8490645126fSAndrew Turner 
8500645126fSAndrew Turner 	ASSERT(pData);
8510645126fSAndrew Turner 
8520645126fSAndrew Turner 	HandleFloatCastOverflow(true, pData, ulFrom);
8530645126fSAndrew Turner }
8540645126fSAndrew Turner 
8550645126fSAndrew Turner void
__ubsan_handle_function_type_mismatch(struct CFunctionTypeMismatchData * pData,unsigned long ulFunction)8560645126fSAndrew Turner __ubsan_handle_function_type_mismatch(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction)
8570645126fSAndrew Turner {
8580645126fSAndrew Turner 
8590645126fSAndrew Turner 	ASSERT(pData);
8600645126fSAndrew Turner 
8610645126fSAndrew Turner 	HandleFunctionTypeMismatch(false, pData, ulFunction);
8620645126fSAndrew Turner }
8630645126fSAndrew Turner 
8640645126fSAndrew Turner void
__ubsan_handle_function_type_mismatch_abort(struct CFunctionTypeMismatchData * pData,unsigned long ulFunction)8650645126fSAndrew Turner __ubsan_handle_function_type_mismatch_abort(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction)
8660645126fSAndrew Turner {
8670645126fSAndrew Turner 
8680645126fSAndrew Turner 	ASSERT(pData);
8690645126fSAndrew Turner 
8700645126fSAndrew Turner 	HandleFunctionTypeMismatch(false, pData, ulFunction);
8710645126fSAndrew Turner }
8720645126fSAndrew Turner 
8730645126fSAndrew Turner void
__ubsan_handle_invalid_builtin(struct CInvalidBuiltinData * pData)8740645126fSAndrew Turner __ubsan_handle_invalid_builtin(struct CInvalidBuiltinData *pData)
8750645126fSAndrew Turner {
8760645126fSAndrew Turner 
8770645126fSAndrew Turner 	ASSERT(pData);
8780645126fSAndrew Turner 
8790645126fSAndrew Turner 	HandleInvalidBuiltin(true, pData);
8800645126fSAndrew Turner }
8810645126fSAndrew Turner 
8820645126fSAndrew Turner void
__ubsan_handle_invalid_builtin_abort(struct CInvalidBuiltinData * pData)8830645126fSAndrew Turner __ubsan_handle_invalid_builtin_abort(struct CInvalidBuiltinData *pData)
8840645126fSAndrew Turner {
8850645126fSAndrew Turner 
8860645126fSAndrew Turner 	ASSERT(pData);
8870645126fSAndrew Turner 
8880645126fSAndrew Turner 	HandleInvalidBuiltin(true, pData);
8890645126fSAndrew Turner }
8900645126fSAndrew Turner 
8910645126fSAndrew Turner void
__ubsan_handle_load_invalid_value(struct CInvalidValueData * pData,unsigned long ulValue)8920645126fSAndrew Turner __ubsan_handle_load_invalid_value(struct CInvalidValueData *pData, unsigned long ulValue)
8930645126fSAndrew Turner {
8940645126fSAndrew Turner 
8950645126fSAndrew Turner 	ASSERT(pData);
8960645126fSAndrew Turner 
8970645126fSAndrew Turner 	HandleLoadInvalidValue(false, pData, ulValue);
8980645126fSAndrew Turner }
8990645126fSAndrew Turner 
9000645126fSAndrew Turner void
__ubsan_handle_load_invalid_value_abort(struct CInvalidValueData * pData,unsigned long ulValue)9010645126fSAndrew Turner __ubsan_handle_load_invalid_value_abort(struct CInvalidValueData *pData, unsigned long ulValue)
9020645126fSAndrew Turner {
9030645126fSAndrew Turner 
9040645126fSAndrew Turner 	ASSERT(pData);
9050645126fSAndrew Turner 
9060645126fSAndrew Turner 	HandleLoadInvalidValue(true, pData, ulValue);
9070645126fSAndrew Turner }
9080645126fSAndrew Turner 
9090645126fSAndrew Turner void
__ubsan_handle_missing_return(struct CUnreachableData * pData)9100645126fSAndrew Turner __ubsan_handle_missing_return(struct CUnreachableData *pData)
9110645126fSAndrew Turner {
9120645126fSAndrew Turner 
9130645126fSAndrew Turner 	ASSERT(pData);
9140645126fSAndrew Turner 
9150645126fSAndrew Turner 	HandleMissingReturn(true, pData);
9160645126fSAndrew Turner }
9170645126fSAndrew Turner 
9180645126fSAndrew Turner void
__ubsan_handle_mul_overflow(struct COverflowData * pData,unsigned long ulLHS,unsigned long ulRHS)9190645126fSAndrew Turner __ubsan_handle_mul_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
9200645126fSAndrew Turner {
9210645126fSAndrew Turner 
9220645126fSAndrew Turner 	ASSERT(pData);
9230645126fSAndrew Turner 
9240645126fSAndrew Turner 	HandleOverflow(false, pData, ulLHS, ulRHS, MUL_STRING);
9250645126fSAndrew Turner }
9260645126fSAndrew Turner 
9270645126fSAndrew Turner void
__ubsan_handle_mul_overflow_abort(struct COverflowData * pData,unsigned long ulLHS,unsigned long ulRHS)9280645126fSAndrew Turner __ubsan_handle_mul_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
9290645126fSAndrew Turner {
9300645126fSAndrew Turner 
9310645126fSAndrew Turner 	ASSERT(pData);
9320645126fSAndrew Turner 
9330645126fSAndrew Turner 	HandleOverflow(true, pData, ulLHS, ulRHS, MUL_STRING);
9340645126fSAndrew Turner }
9350645126fSAndrew Turner 
9360645126fSAndrew Turner void
__ubsan_handle_negate_overflow(struct COverflowData * pData,unsigned long ulOldValue)9370645126fSAndrew Turner __ubsan_handle_negate_overflow(struct COverflowData *pData, unsigned long ulOldValue)
9380645126fSAndrew Turner {
9390645126fSAndrew Turner 
9400645126fSAndrew Turner 	ASSERT(pData);
9410645126fSAndrew Turner 
9420645126fSAndrew Turner 	HandleNegateOverflow(false, pData, ulOldValue);
9430645126fSAndrew Turner }
9440645126fSAndrew Turner 
9450645126fSAndrew Turner void
__ubsan_handle_negate_overflow_abort(struct COverflowData * pData,unsigned long ulOldValue)9460645126fSAndrew Turner __ubsan_handle_negate_overflow_abort(struct COverflowData *pData, unsigned long ulOldValue)
9470645126fSAndrew Turner {
9480645126fSAndrew Turner 
9490645126fSAndrew Turner 	ASSERT(pData);
9500645126fSAndrew Turner 
9510645126fSAndrew Turner 	HandleNegateOverflow(true, pData, ulOldValue);
9520645126fSAndrew Turner }
9530645126fSAndrew Turner 
9540645126fSAndrew Turner void
__ubsan_handle_nonnull_arg(struct CNonNullArgData * pData)9550645126fSAndrew Turner __ubsan_handle_nonnull_arg(struct CNonNullArgData *pData)
9560645126fSAndrew Turner {
9570645126fSAndrew Turner 
9580645126fSAndrew Turner 	ASSERT(pData);
9590645126fSAndrew Turner 
9600645126fSAndrew Turner 	HandleNonnullArg(false, pData);
9610645126fSAndrew Turner }
9620645126fSAndrew Turner 
9630645126fSAndrew Turner void
__ubsan_handle_nonnull_arg_abort(struct CNonNullArgData * pData)9640645126fSAndrew Turner __ubsan_handle_nonnull_arg_abort(struct CNonNullArgData *pData)
9650645126fSAndrew Turner {
9660645126fSAndrew Turner 
9670645126fSAndrew Turner 	ASSERT(pData);
9680645126fSAndrew Turner 
9690645126fSAndrew Turner 	HandleNonnullArg(true, pData);
9700645126fSAndrew Turner }
9710645126fSAndrew Turner 
9720645126fSAndrew Turner void
__ubsan_handle_nonnull_return_v1(struct CNonNullReturnData * pData,struct CSourceLocation * pLocationPointer)9730645126fSAndrew Turner __ubsan_handle_nonnull_return_v1(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
9740645126fSAndrew Turner {
9750645126fSAndrew Turner 
9760645126fSAndrew Turner 	ASSERT(pData);
9770645126fSAndrew Turner 	ASSERT(pLocationPointer);
9780645126fSAndrew Turner 
9790645126fSAndrew Turner 	HandleNonnullReturn(false, pData, pLocationPointer);
9800645126fSAndrew Turner }
9810645126fSAndrew Turner 
9820645126fSAndrew Turner void
__ubsan_handle_nonnull_return_v1_abort(struct CNonNullReturnData * pData,struct CSourceLocation * pLocationPointer)9830645126fSAndrew Turner __ubsan_handle_nonnull_return_v1_abort(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
9840645126fSAndrew Turner {
9850645126fSAndrew Turner 
9860645126fSAndrew Turner 	ASSERT(pData);
9870645126fSAndrew Turner 	ASSERT(pLocationPointer);
9880645126fSAndrew Turner 
9890645126fSAndrew Turner 	HandleNonnullReturn(true, pData, pLocationPointer);
9900645126fSAndrew Turner }
9910645126fSAndrew Turner 
9920645126fSAndrew Turner void
__ubsan_handle_nullability_arg(struct CNonNullArgData * pData)9930645126fSAndrew Turner __ubsan_handle_nullability_arg(struct CNonNullArgData *pData)
9940645126fSAndrew Turner {
9950645126fSAndrew Turner 
9960645126fSAndrew Turner 	ASSERT(pData);
9970645126fSAndrew Turner 
9980645126fSAndrew Turner 	HandleNonnullArg(false, pData);
9990645126fSAndrew Turner }
10000645126fSAndrew Turner 
10010645126fSAndrew Turner void
__ubsan_handle_nullability_arg_abort(struct CNonNullArgData * pData)10020645126fSAndrew Turner __ubsan_handle_nullability_arg_abort(struct CNonNullArgData *pData)
10030645126fSAndrew Turner {
10040645126fSAndrew Turner 
10050645126fSAndrew Turner 	ASSERT(pData);
10060645126fSAndrew Turner 
10070645126fSAndrew Turner 	HandleNonnullArg(true, pData);
10080645126fSAndrew Turner }
10090645126fSAndrew Turner 
10100645126fSAndrew Turner void
__ubsan_handle_nullability_return_v1(struct CNonNullReturnData * pData,struct CSourceLocation * pLocationPointer)10110645126fSAndrew Turner __ubsan_handle_nullability_return_v1(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
10120645126fSAndrew Turner {
10130645126fSAndrew Turner 
10140645126fSAndrew Turner 	ASSERT(pData);
10150645126fSAndrew Turner 	ASSERT(pLocationPointer);
10160645126fSAndrew Turner 
10170645126fSAndrew Turner 	HandleNonnullReturn(false, pData, pLocationPointer);
10180645126fSAndrew Turner }
10190645126fSAndrew Turner 
10200645126fSAndrew Turner void
__ubsan_handle_nullability_return_v1_abort(struct CNonNullReturnData * pData,struct CSourceLocation * pLocationPointer)10210645126fSAndrew Turner __ubsan_handle_nullability_return_v1_abort(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
10220645126fSAndrew Turner {
10230645126fSAndrew Turner 
10240645126fSAndrew Turner 	ASSERT(pData);
10250645126fSAndrew Turner 	ASSERT(pLocationPointer);
10260645126fSAndrew Turner 
10270645126fSAndrew Turner 	HandleNonnullReturn(true, pData, pLocationPointer);
10280645126fSAndrew Turner }
10290645126fSAndrew Turner 
10300645126fSAndrew Turner void
__ubsan_handle_out_of_bounds(struct COutOfBoundsData * pData,unsigned long ulIndex)10310645126fSAndrew Turner __ubsan_handle_out_of_bounds(struct COutOfBoundsData *pData, unsigned long ulIndex)
10320645126fSAndrew Turner {
10330645126fSAndrew Turner 
10340645126fSAndrew Turner 	ASSERT(pData);
10350645126fSAndrew Turner 
10360645126fSAndrew Turner 	HandleOutOfBounds(false, pData, ulIndex);
10370645126fSAndrew Turner }
10380645126fSAndrew Turner 
10390645126fSAndrew Turner void
__ubsan_handle_out_of_bounds_abort(struct COutOfBoundsData * pData,unsigned long ulIndex)10400645126fSAndrew Turner __ubsan_handle_out_of_bounds_abort(struct COutOfBoundsData *pData, unsigned long ulIndex)
10410645126fSAndrew Turner {
10420645126fSAndrew Turner 
10430645126fSAndrew Turner 	ASSERT(pData);
10440645126fSAndrew Turner 
10450645126fSAndrew Turner 	HandleOutOfBounds(true, pData, ulIndex);
10460645126fSAndrew Turner }
10470645126fSAndrew Turner 
10480645126fSAndrew Turner void
__ubsan_handle_pointer_overflow(struct CPointerOverflowData * pData,unsigned long ulBase,unsigned long ulResult)10490645126fSAndrew Turner __ubsan_handle_pointer_overflow(struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult)
10500645126fSAndrew Turner {
10510645126fSAndrew Turner 
10520645126fSAndrew Turner 	ASSERT(pData);
10530645126fSAndrew Turner 
10540645126fSAndrew Turner 	HandlePointerOverflow(false, pData, ulBase, ulResult);
10550645126fSAndrew Turner }
10560645126fSAndrew Turner 
10570645126fSAndrew Turner void
__ubsan_handle_pointer_overflow_abort(struct CPointerOverflowData * pData,unsigned long ulBase,unsigned long ulResult)10580645126fSAndrew Turner __ubsan_handle_pointer_overflow_abort(struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult)
10590645126fSAndrew Turner {
10600645126fSAndrew Turner 
10610645126fSAndrew Turner 	ASSERT(pData);
10620645126fSAndrew Turner 
10630645126fSAndrew Turner 	HandlePointerOverflow(true, pData, ulBase, ulResult);
10640645126fSAndrew Turner }
10650645126fSAndrew Turner 
10660645126fSAndrew Turner void
__ubsan_handle_shift_out_of_bounds(struct CShiftOutOfBoundsData * pData,unsigned long ulLHS,unsigned long ulRHS)10670645126fSAndrew Turner __ubsan_handle_shift_out_of_bounds(struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS)
10680645126fSAndrew Turner {
10690645126fSAndrew Turner 
10700645126fSAndrew Turner 	ASSERT(pData);
10710645126fSAndrew Turner 
10720645126fSAndrew Turner 	HandleShiftOutOfBounds(false, pData, ulLHS, ulRHS);
10730645126fSAndrew Turner }
10740645126fSAndrew Turner 
10750645126fSAndrew Turner void
__ubsan_handle_shift_out_of_bounds_abort(struct CShiftOutOfBoundsData * pData,unsigned long ulLHS,unsigned long ulRHS)10760645126fSAndrew Turner __ubsan_handle_shift_out_of_bounds_abort(struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS)
10770645126fSAndrew Turner {
10780645126fSAndrew Turner 
10790645126fSAndrew Turner 	ASSERT(pData);
10800645126fSAndrew Turner 
10810645126fSAndrew Turner 	HandleShiftOutOfBounds(true, pData, ulLHS, ulRHS);
10820645126fSAndrew Turner }
10830645126fSAndrew Turner 
10840645126fSAndrew Turner void
__ubsan_handle_sub_overflow(struct COverflowData * pData,unsigned long ulLHS,unsigned long ulRHS)10850645126fSAndrew Turner __ubsan_handle_sub_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
10860645126fSAndrew Turner {
10870645126fSAndrew Turner 
10880645126fSAndrew Turner 	ASSERT(pData);
10890645126fSAndrew Turner 
10900645126fSAndrew Turner 	HandleOverflow(false, pData, ulLHS, ulRHS, MINUS_STRING);
10910645126fSAndrew Turner }
10920645126fSAndrew Turner 
10930645126fSAndrew Turner void
__ubsan_handle_sub_overflow_abort(struct COverflowData * pData,unsigned long ulLHS,unsigned long ulRHS)10940645126fSAndrew Turner __ubsan_handle_sub_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
10950645126fSAndrew Turner {
10960645126fSAndrew Turner 
10970645126fSAndrew Turner 	ASSERT(pData);
10980645126fSAndrew Turner 
10990645126fSAndrew Turner 	HandleOverflow(true, pData, ulLHS, ulRHS, MINUS_STRING);
11000645126fSAndrew Turner }
11010645126fSAndrew Turner 
11020645126fSAndrew Turner void
__ubsan_handle_type_mismatch(struct CTypeMismatchData * pData,unsigned long ulPointer)11030645126fSAndrew Turner __ubsan_handle_type_mismatch(struct CTypeMismatchData *pData, unsigned long ulPointer)
11040645126fSAndrew Turner {
11050645126fSAndrew Turner 
11060645126fSAndrew Turner 	ASSERT(pData);
11070645126fSAndrew Turner 
11080645126fSAndrew Turner 	HandleTypeMismatch(false, &pData->mLocation, pData->mType, pData->mLogAlignment, pData->mTypeCheckKind, ulPointer);
11090645126fSAndrew Turner }
11100645126fSAndrew Turner 
11110645126fSAndrew Turner void
__ubsan_handle_type_mismatch_abort(struct CTypeMismatchData * pData,unsigned long ulPointer)11120645126fSAndrew Turner __ubsan_handle_type_mismatch_abort(struct CTypeMismatchData *pData, unsigned long ulPointer)
11130645126fSAndrew Turner {
11140645126fSAndrew Turner 
11150645126fSAndrew Turner 	ASSERT(pData);
11160645126fSAndrew Turner 
11170645126fSAndrew Turner 	HandleTypeMismatch(true, &pData->mLocation, pData->mType, pData->mLogAlignment, pData->mTypeCheckKind, ulPointer);
11180645126fSAndrew Turner }
11190645126fSAndrew Turner 
11200645126fSAndrew Turner void
__ubsan_handle_type_mismatch_v1(struct CTypeMismatchData_v1 * pData,unsigned long ulPointer)11210645126fSAndrew Turner __ubsan_handle_type_mismatch_v1(struct CTypeMismatchData_v1 *pData, unsigned long ulPointer)
11220645126fSAndrew Turner {
11230645126fSAndrew Turner 
11240645126fSAndrew Turner 	ASSERT(pData);
11250645126fSAndrew Turner 
11260645126fSAndrew Turner 	HandleTypeMismatch(false, &pData->mLocation, pData->mType, __BIT(pData->mLogAlignment), pData->mTypeCheckKind, ulPointer);
11270645126fSAndrew Turner }
11280645126fSAndrew Turner 
11290645126fSAndrew Turner void
__ubsan_handle_type_mismatch_v1_abort(struct CTypeMismatchData_v1 * pData,unsigned long ulPointer)11300645126fSAndrew Turner __ubsan_handle_type_mismatch_v1_abort(struct CTypeMismatchData_v1 *pData, unsigned long ulPointer)
11310645126fSAndrew Turner {
11320645126fSAndrew Turner 
11330645126fSAndrew Turner 	ASSERT(pData);
11340645126fSAndrew Turner 
11350645126fSAndrew Turner 	HandleTypeMismatch(true, &pData->mLocation, pData->mType, __BIT(pData->mLogAlignment), pData->mTypeCheckKind, ulPointer);
11360645126fSAndrew Turner }
11370645126fSAndrew Turner 
11380645126fSAndrew Turner void
__ubsan_handle_vla_bound_not_positive(struct CVLABoundData * pData,unsigned long ulBound)11390645126fSAndrew Turner __ubsan_handle_vla_bound_not_positive(struct CVLABoundData *pData, unsigned long ulBound)
11400645126fSAndrew Turner {
11410645126fSAndrew Turner 
11420645126fSAndrew Turner 	ASSERT(pData);
11430645126fSAndrew Turner 
11440645126fSAndrew Turner 	HandleVlaBoundNotPositive(false, pData, ulBound);
11450645126fSAndrew Turner }
11460645126fSAndrew Turner 
11470645126fSAndrew Turner void
__ubsan_handle_vla_bound_not_positive_abort(struct CVLABoundData * pData,unsigned long ulBound)11480645126fSAndrew Turner __ubsan_handle_vla_bound_not_positive_abort(struct CVLABoundData *pData, unsigned long ulBound)
11490645126fSAndrew Turner {
11500645126fSAndrew Turner 
11510645126fSAndrew Turner 	ASSERT(pData);
11520645126fSAndrew Turner 
11530645126fSAndrew Turner 	HandleVlaBoundNotPositive(true, pData, ulBound);
11540645126fSAndrew Turner }
11550645126fSAndrew Turner 
11560645126fSAndrew Turner void
__ubsan_get_current_report_data(const char ** ppOutIssueKind,const char ** ppOutMessage,const char ** ppOutFilename,uint32_t * pOutLine,uint32_t * pOutCol,char ** ppOutMemoryAddr)11570645126fSAndrew Turner __ubsan_get_current_report_data(const char **ppOutIssueKind, const char **ppOutMessage, const char **ppOutFilename, uint32_t *pOutLine, uint32_t *pOutCol, char **ppOutMemoryAddr)
11580645126fSAndrew Turner {
11590645126fSAndrew Turner 	/*
11600645126fSAndrew Turner 	 * Unimplemented.
11610645126fSAndrew Turner 	 *
11620645126fSAndrew Turner 	 * The __ubsan_on_report() feature is non trivial to implement in a
11630645126fSAndrew Turner 	 * shared code between the kernel and userland. It's also opening
11640645126fSAndrew Turner 	 * new sets of potential problems as we are not expected to slow down
11650645126fSAndrew Turner 	 * execution of certain kernel subsystems (synchronization issues,
11660645126fSAndrew Turner 	 * interrupt handling etc).
11670645126fSAndrew Turner 	 *
11680645126fSAndrew Turner 	 * A proper solution would need probably a lock-free bounded queue built
11690645126fSAndrew Turner 	 * with atomic operations with the property of miltiple consumers and
11700645126fSAndrew Turner 	 * multiple producers. Maintaining and validating such code is not
11710645126fSAndrew Turner 	 * worth the effort.
11720645126fSAndrew Turner 	 *
11730645126fSAndrew Turner 	 * A legitimate user - besides testing framework - is a debugger plugin
11740645126fSAndrew Turner 	 * intercepting reports from the UBSan instrumentation. For such
11750645126fSAndrew Turner 	 * scenarios it is better to run the Clang/GCC version.
11760645126fSAndrew Turner 	 */
11770645126fSAndrew Turner }
11780645126fSAndrew Turner 
11790645126fSAndrew Turner /* Local utility functions */
11800645126fSAndrew Turner 
11810645126fSAndrew Turner static void
Report(bool isFatal,const char * pFormat,...)11820645126fSAndrew Turner Report(bool isFatal, const char *pFormat, ...)
11830645126fSAndrew Turner {
11840645126fSAndrew Turner 	va_list ap;
11850645126fSAndrew Turner 
11860645126fSAndrew Turner 	ASSERT(pFormat);
11870645126fSAndrew Turner 
11880645126fSAndrew Turner 	va_start(ap, pFormat);
11890645126fSAndrew Turner #if defined(_KERNEL)
11900645126fSAndrew Turner 	if (isFatal)
11910645126fSAndrew Turner 		vpanic(pFormat, ap);
11920645126fSAndrew Turner 	else
11930645126fSAndrew Turner 		vprintf(pFormat, ap);
11940645126fSAndrew Turner #else
11950645126fSAndrew Turner 	if (ubsan_flags == -1) {
11960645126fSAndrew Turner 		char buf[1024];
11970645126fSAndrew Turner 		char *p;
11980645126fSAndrew Turner 
11990645126fSAndrew Turner 		ubsan_flags = UBSAN_STDERR;
12000645126fSAndrew Turner 
12010645126fSAndrew Turner 		if (getenv_r("LIBC_UBSAN", buf, sizeof(buf)) != -1) {
12020645126fSAndrew Turner 			for (p = buf; *p; p++) {
12030645126fSAndrew Turner 				switch (*p) {
12040645126fSAndrew Turner 				case 'a':
12050645126fSAndrew Turner 					SET(ubsan_flags, UBSAN_ABORT);
12060645126fSAndrew Turner 					break;
12070645126fSAndrew Turner 				case 'A':
12080645126fSAndrew Turner 					CLR(ubsan_flags, UBSAN_ABORT);
12090645126fSAndrew Turner 					break;
12100645126fSAndrew Turner 				case 'e':
12110645126fSAndrew Turner 					SET(ubsan_flags, UBSAN_STDERR);
12120645126fSAndrew Turner 					break;
12130645126fSAndrew Turner 				case 'E':
12140645126fSAndrew Turner 					CLR(ubsan_flags, UBSAN_STDERR);
12150645126fSAndrew Turner 					break;
12160645126fSAndrew Turner 				case 'l':
12170645126fSAndrew Turner 					SET(ubsan_flags, UBSAN_SYSLOG);
12180645126fSAndrew Turner 					break;
12190645126fSAndrew Turner 				case 'L':
12200645126fSAndrew Turner 					CLR(ubsan_flags, UBSAN_SYSLOG);
12210645126fSAndrew Turner 					break;
12220645126fSAndrew Turner 				case 'o':
12230645126fSAndrew Turner 					SET(ubsan_flags, UBSAN_STDOUT);
12240645126fSAndrew Turner 					break;
12250645126fSAndrew Turner 				case 'O':
12260645126fSAndrew Turner 					CLR(ubsan_flags, UBSAN_STDOUT);
12270645126fSAndrew Turner 					break;
12280645126fSAndrew Turner 				default:
12290645126fSAndrew Turner 					break;
12300645126fSAndrew Turner 				}
12310645126fSAndrew Turner 			}
12320645126fSAndrew Turner 		}
12330645126fSAndrew Turner 	}
12340645126fSAndrew Turner 
12350645126fSAndrew Turner 	// The *v*print* functions can flush the va_list argument.
12360645126fSAndrew Turner 	// Create a local copy for each call to prevent invalid read.
12370645126fSAndrew Turner 	if (ISSET(ubsan_flags, UBSAN_STDOUT)) {
12380645126fSAndrew Turner 		va_list tmp;
12390645126fSAndrew Turner 		va_copy(tmp, ap);
12400645126fSAndrew Turner 		vprintf(pFormat, tmp);
12410645126fSAndrew Turner 		va_end(tmp);
12420645126fSAndrew Turner 		fflush(stdout);
12430645126fSAndrew Turner 	}
12440645126fSAndrew Turner 	if (ISSET(ubsan_flags, UBSAN_STDERR)) {
12450645126fSAndrew Turner 		va_list tmp;
12460645126fSAndrew Turner 		va_copy(tmp, ap);
12470645126fSAndrew Turner 		vfprintf(stderr, pFormat, tmp);
12480645126fSAndrew Turner 		va_end(tmp);
12490645126fSAndrew Turner 		fflush(stderr);
12500645126fSAndrew Turner 	}
12510645126fSAndrew Turner 	if (ISSET(ubsan_flags, UBSAN_SYSLOG)) {
12520645126fSAndrew Turner 		va_list tmp;
12530645126fSAndrew Turner 		va_copy(tmp, ap);
12540645126fSAndrew Turner 		struct syslog_data SyslogData = SYSLOG_DATA_INIT;
12550645126fSAndrew Turner 		ubsan_vsyslog(LOG_DEBUG | LOG_USER, &SyslogData, pFormat, tmp);
12560645126fSAndrew Turner 		va_end(tmp);
12570645126fSAndrew Turner 	}
12580645126fSAndrew Turner 	if (isFatal || ISSET(ubsan_flags, UBSAN_ABORT)) {
12590645126fSAndrew Turner 		abort();
12600645126fSAndrew Turner 		/* NOTREACHED */
12610645126fSAndrew Turner 	}
12620645126fSAndrew Turner #endif
12630645126fSAndrew Turner 	va_end(ap);
12640645126fSAndrew Turner }
12650645126fSAndrew Turner 
12660645126fSAndrew Turner static bool
isAlreadyReported(struct CSourceLocation * pLocation)12670645126fSAndrew Turner isAlreadyReported(struct CSourceLocation *pLocation)
12680645126fSAndrew Turner {
12690645126fSAndrew Turner 	/*
12700645126fSAndrew Turner 	 * This code is shared between libc, kernel and standalone usage.
12710645126fSAndrew Turner 	 * It shall work in early bootstrap phase of both of them.
12720645126fSAndrew Turner 	 */
12730645126fSAndrew Turner 
12740645126fSAndrew Turner 	uint32_t siOldValue;
12750645126fSAndrew Turner 	volatile uint32_t *pLine;
12760645126fSAndrew Turner 
12770645126fSAndrew Turner 	ASSERT(pLocation);
12780645126fSAndrew Turner 
12790645126fSAndrew Turner 	pLine = &pLocation->mLine;
12800645126fSAndrew Turner 
12810645126fSAndrew Turner 	do {
12820645126fSAndrew Turner 		siOldValue = *pLine;
12830645126fSAndrew Turner 	} while (__sync_val_compare_and_swap(pLine, siOldValue, siOldValue | ACK_REPORTED) != siOldValue);
12840645126fSAndrew Turner 
12850645126fSAndrew Turner 	return ISSET(siOldValue, ACK_REPORTED);
12860645126fSAndrew Turner }
12870645126fSAndrew Turner 
12880645126fSAndrew Turner static size_t
zDeserializeTypeWidth(struct CTypeDescriptor * pType)12890645126fSAndrew Turner zDeserializeTypeWidth(struct CTypeDescriptor *pType)
12900645126fSAndrew Turner {
12910645126fSAndrew Turner 	size_t zWidth = 0;
12920645126fSAndrew Turner 
12930645126fSAndrew Turner 	ASSERT(pType);
12940645126fSAndrew Turner 
12950645126fSAndrew Turner 	switch (pType->mTypeKind) {
12960645126fSAndrew Turner 	case KIND_INTEGER:
12970645126fSAndrew Turner 		zWidth = __BIT(__SHIFTOUT(pType->mTypeInfo, ~NUMBER_SIGNED_BIT));
12980645126fSAndrew Turner 		break;
12990645126fSAndrew Turner 	case KIND_FLOAT:
13000645126fSAndrew Turner 		zWidth = pType->mTypeInfo;
13010645126fSAndrew Turner 		break;
13020645126fSAndrew Turner 	default:
13030645126fSAndrew Turner 		Report(true, "UBSan: Unknown variable type %#04" PRIx16 "\n", pType->mTypeKind);
13040645126fSAndrew Turner 		/* NOTREACHED */
13050645126fSAndrew Turner 	}
13060645126fSAndrew Turner 
13070645126fSAndrew Turner 	/* Invalid width will be transformed to 0 */
13080645126fSAndrew Turner 	ASSERT(zWidth > 0);
13090645126fSAndrew Turner 
13100645126fSAndrew Turner 	return zWidth;
13110645126fSAndrew Turner }
13120645126fSAndrew Turner 
13130645126fSAndrew Turner static void
DeserializeLocation(char * pBuffer,size_t zBUfferLength,struct CSourceLocation * pLocation)13140645126fSAndrew Turner DeserializeLocation(char *pBuffer, size_t zBUfferLength, struct CSourceLocation *pLocation)
13150645126fSAndrew Turner {
13160645126fSAndrew Turner 
13170645126fSAndrew Turner 	ASSERT(pLocation);
13180645126fSAndrew Turner 	ASSERT(pLocation->mFilename);
13190645126fSAndrew Turner 
13200645126fSAndrew Turner 	snprintf(pBuffer, zBUfferLength, "%s:%" PRIu32 ":%" PRIu32, pLocation->mFilename, pLocation->mLine & (uint32_t)~ACK_REPORTED, pLocation->mColumn);
13210645126fSAndrew Turner }
13220645126fSAndrew Turner 
13230645126fSAndrew Turner #ifdef __SIZEOF_INT128__
13240645126fSAndrew Turner static void
DeserializeUINT128(char * pBuffer,size_t zBUfferLength,struct CTypeDescriptor * pType,__uint128_t U128)13250645126fSAndrew Turner DeserializeUINT128(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, __uint128_t U128)
13260645126fSAndrew Turner {
13270645126fSAndrew Turner 	char szBuf[3]; /* 'XX\0' */
13280645126fSAndrew Turner 	char rgNumber[sizeof(ulongest)];
13290645126fSAndrew Turner 	ssize_t zI;
13300645126fSAndrew Turner 
13310645126fSAndrew Turner 	memcpy(rgNumber, &U128, sizeof(U128));
13320645126fSAndrew Turner 
13330645126fSAndrew Turner 	strlcpy(pBuffer, "Undecoded-128-bit-Integer-Type (0x", zBUfferLength);
13340645126fSAndrew Turner #if BYTE_ORDER == LITTLE_ENDIAN
13350645126fSAndrew Turner 	for (zI = sizeof(ulongest) - 1; zI >= 0; zI--) {
13360645126fSAndrew Turner #else
13370645126fSAndrew Turner 	for (zI = 0; zI < (ssize_t)sizeof(ulongest); zI++) {
13380645126fSAndrew Turner #endif
13390645126fSAndrew Turner 		snprintf(szBuf, sizeof(szBuf), "%02" PRIx8, rgNumber[zI]);
13400645126fSAndrew Turner 		strlcat(pBuffer, szBuf, zBUfferLength);
13410645126fSAndrew Turner 	}
13420645126fSAndrew Turner 	strlcat(pBuffer, ")", zBUfferLength);
13430645126fSAndrew Turner }
13440645126fSAndrew Turner #endif
13450645126fSAndrew Turner 
13460645126fSAndrew Turner static void
13470645126fSAndrew Turner DeserializeNumberSigned(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, longest L)
13480645126fSAndrew Turner {
13490645126fSAndrew Turner 
13500645126fSAndrew Turner 	ASSERT(pBuffer);
13510645126fSAndrew Turner 	ASSERT(zBUfferLength > 0);
13520645126fSAndrew Turner 	ASSERT(pType);
13530645126fSAndrew Turner 	ASSERT(ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT));
13540645126fSAndrew Turner 
13550645126fSAndrew Turner 	switch (zDeserializeTypeWidth(pType)) {
13560645126fSAndrew Turner 	default:
13570645126fSAndrew Turner 		ASSERT(0 && "Invalid codepath");
13580645126fSAndrew Turner 		/* NOTREACHED */
13590645126fSAndrew Turner #ifdef __SIZEOF_INT128__
13600645126fSAndrew Turner 	case WIDTH_128:
13610645126fSAndrew Turner 		DeserializeUINT128(pBuffer, zBUfferLength, pType, STATIC_CAST(__uint128_t, L));
13620645126fSAndrew Turner 		break;
13630645126fSAndrew Turner #endif
13640645126fSAndrew Turner 	case WIDTH_64:
13650645126fSAndrew Turner 	case WIDTH_32:
13660645126fSAndrew Turner 	case WIDTH_16:
13670645126fSAndrew Turner 	case WIDTH_8:
13680645126fSAndrew Turner 		snprintf(pBuffer, zBUfferLength, "%" PRId64, STATIC_CAST(int64_t, L));
13690645126fSAndrew Turner 		break;
13700645126fSAndrew Turner 	}
13710645126fSAndrew Turner }
13720645126fSAndrew Turner 
13730645126fSAndrew Turner static void
13740645126fSAndrew Turner DeserializeNumberUnsigned(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, ulongest L)
13750645126fSAndrew Turner {
13760645126fSAndrew Turner 
13770645126fSAndrew Turner 	ASSERT(pBuffer);
13780645126fSAndrew Turner 	ASSERT(zBUfferLength > 0);
13790645126fSAndrew Turner 	ASSERT(pType);
13800645126fSAndrew Turner 	ASSERT(!ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT));
13810645126fSAndrew Turner 
13820645126fSAndrew Turner 	switch (zDeserializeTypeWidth(pType)) {
13830645126fSAndrew Turner 	default:
13840645126fSAndrew Turner 		ASSERT(0 && "Invalid codepath");
13850645126fSAndrew Turner 		/* NOTREACHED */
13860645126fSAndrew Turner #ifdef __SIZEOF_INT128__
13870645126fSAndrew Turner 	case WIDTH_128:
13880645126fSAndrew Turner 		DeserializeUINT128(pBuffer, zBUfferLength, pType, STATIC_CAST(__uint128_t, L));
13890645126fSAndrew Turner 		break;
13900645126fSAndrew Turner #endif
13910645126fSAndrew Turner 	case WIDTH_64:
13920645126fSAndrew Turner 	case WIDTH_32:
13930645126fSAndrew Turner 	case WIDTH_16:
13940645126fSAndrew Turner 	case WIDTH_8:
13950645126fSAndrew Turner 		snprintf(pBuffer, zBUfferLength, "%" PRIu64, STATIC_CAST(uint64_t, L));
13960645126fSAndrew Turner 		break;
13970645126fSAndrew Turner 	}
13980645126fSAndrew Turner }
13990645126fSAndrew Turner 
14000645126fSAndrew Turner #ifndef _KERNEL
14010645126fSAndrew Turner static void
14020645126fSAndrew Turner DeserializeFloatOverPointer(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long *pNumber)
14030645126fSAndrew Turner {
14040645126fSAndrew Turner 	double D;
14050645126fSAndrew Turner #ifdef __HAVE_LONG_DOUBLE
14060645126fSAndrew Turner 	long double LD;
14070645126fSAndrew Turner #endif
14080645126fSAndrew Turner 
14090645126fSAndrew Turner 	ASSERT(pBuffer);
14100645126fSAndrew Turner 	ASSERT(zBUfferLength > 0);
14110645126fSAndrew Turner 	ASSERT(pType);
14120645126fSAndrew Turner 	ASSERT(pNumber);
14130645126fSAndrew Turner 	/*
14140645126fSAndrew Turner 	 * This function handles 64-bit number over a pointer on 32-bit CPUs.
14150645126fSAndrew Turner 	 */
14160645126fSAndrew Turner 	ASSERT((sizeof(*pNumber) * CHAR_BIT < WIDTH_64) || (zDeserializeTypeWidth(pType) >= WIDTH_64));
14170645126fSAndrew Turner 	ASSERT(sizeof(D) == sizeof(uint64_t));
14180645126fSAndrew Turner #ifdef __HAVE_LONG_DOUBLE
14190645126fSAndrew Turner 	ASSERT(sizeof(LD) > sizeof(uint64_t));
14200645126fSAndrew Turner #endif
14210645126fSAndrew Turner 
14220645126fSAndrew Turner 	switch (zDeserializeTypeWidth(pType)) {
14230645126fSAndrew Turner #ifdef __HAVE_LONG_DOUBLE
14240645126fSAndrew Turner 	case WIDTH_128:
14250645126fSAndrew Turner 	case WIDTH_96:
14260645126fSAndrew Turner 	case WIDTH_80:
14270645126fSAndrew Turner 		memcpy(&LD, pNumber, sizeof(long double));
14280645126fSAndrew Turner 		snprintf(pBuffer, zBUfferLength, "%Lg", LD);
14290645126fSAndrew Turner 		break;
14300645126fSAndrew Turner #endif
14310645126fSAndrew Turner 	case WIDTH_64:
14320645126fSAndrew Turner 		memcpy(&D, pNumber, sizeof(double));
14330645126fSAndrew Turner 		snprintf(pBuffer, zBUfferLength, "%g", D);
14340645126fSAndrew Turner 		break;
14350645126fSAndrew Turner 	}
14360645126fSAndrew Turner }
14370645126fSAndrew Turner 
14380645126fSAndrew Turner static void
14390645126fSAndrew Turner DeserializeFloatInlined(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber)
14400645126fSAndrew Turner {
14410645126fSAndrew Turner 	float F;
14420645126fSAndrew Turner 	double D;
14430645126fSAndrew Turner 	uint32_t U32;
14440645126fSAndrew Turner 
14450645126fSAndrew Turner 	ASSERT(pBuffer);
14460645126fSAndrew Turner 	ASSERT(zBUfferLength > 0);
14470645126fSAndrew Turner 	ASSERT(pType);
14480645126fSAndrew Turner 	ASSERT(sizeof(F) == sizeof(uint32_t));
14490645126fSAndrew Turner 	ASSERT(sizeof(D) == sizeof(uint64_t));
14500645126fSAndrew Turner 
14510645126fSAndrew Turner 	switch (zDeserializeTypeWidth(pType)) {
14520645126fSAndrew Turner 	case WIDTH_64:
14530645126fSAndrew Turner 		memcpy(&D, &ulNumber, sizeof(double));
14540645126fSAndrew Turner 		snprintf(pBuffer, zBUfferLength, "%g", D);
14550645126fSAndrew Turner 		break;
14560645126fSAndrew Turner 	case WIDTH_32:
14570645126fSAndrew Turner 		/*
14580645126fSAndrew Turner 		 * On supported platforms sizeof(float)==sizeof(uint32_t)
14590645126fSAndrew Turner 		 * unsigned long is either 32 or 64-bit, cast it to 32-bit
14600645126fSAndrew Turner 		 * value in order to call memcpy(3) in an Endian-aware way.
14610645126fSAndrew Turner 		 */
14620645126fSAndrew Turner 		U32 = STATIC_CAST(uint32_t, ulNumber);
14630645126fSAndrew Turner 		memcpy(&F, &U32, sizeof(float));
14640645126fSAndrew Turner 		snprintf(pBuffer, zBUfferLength, "%g", F);
14650645126fSAndrew Turner 		break;
14660645126fSAndrew Turner 	case WIDTH_16:
14670645126fSAndrew Turner 		snprintf(pBuffer, zBUfferLength, "Undecoded-16-bit-Floating-Type (%#04" PRIx16 ")", STATIC_CAST(uint16_t, ulNumber));
14680645126fSAndrew Turner 		break;
14690645126fSAndrew Turner 	}
14700645126fSAndrew Turner }
14710645126fSAndrew Turner #endif
14720645126fSAndrew Turner 
14730645126fSAndrew Turner static longest
14740645126fSAndrew Turner llliGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber)
14750645126fSAndrew Turner {
14760645126fSAndrew Turner 	size_t zNumberWidth;
14770645126fSAndrew Turner 	longest L = 0;
14780645126fSAndrew Turner 
14790645126fSAndrew Turner 	ASSERT(szLocation);
14800645126fSAndrew Turner 	ASSERT(pType);
14810645126fSAndrew Turner 
14820645126fSAndrew Turner 	zNumberWidth = zDeserializeTypeWidth(pType);
14830645126fSAndrew Turner 	switch (zNumberWidth) {
14840645126fSAndrew Turner 	default:
14850645126fSAndrew Turner 		Report(true, "UBSan: Unexpected %zu-Bit Type in %s\n", zNumberWidth, szLocation);
14860645126fSAndrew Turner 		/* NOTREACHED */
14870645126fSAndrew Turner 	case WIDTH_128:
14880645126fSAndrew Turner #ifdef __SIZEOF_INT128__
14890645126fSAndrew Turner 		memcpy(&L, REINTERPRET_CAST(longest *, ulNumber), sizeof(longest));
14900645126fSAndrew Turner #else
14910645126fSAndrew Turner 		Report(true, "UBSan: Unexpected 128-Bit Type in %s\n", szLocation);
14920645126fSAndrew Turner 		/* NOTREACHED */
14930645126fSAndrew Turner #endif
14940645126fSAndrew Turner 		break;
14950645126fSAndrew Turner 	case WIDTH_64:
14960645126fSAndrew Turner 		if (sizeof(ulNumber) * CHAR_BIT < WIDTH_64) {
14970645126fSAndrew Turner 			L = *REINTERPRET_CAST(int64_t *, ulNumber);
14980645126fSAndrew Turner 		} else {
14990645126fSAndrew Turner 			L = STATIC_CAST(int64_t, STATIC_CAST(uint64_t, ulNumber));
15000645126fSAndrew Turner 		}
15010645126fSAndrew Turner 		break;
15020645126fSAndrew Turner 	case WIDTH_32:
15030645126fSAndrew Turner 		L = STATIC_CAST(int32_t, STATIC_CAST(uint32_t, ulNumber));
15040645126fSAndrew Turner 		break;
15050645126fSAndrew Turner 	case WIDTH_16:
15060645126fSAndrew Turner 		L = STATIC_CAST(int16_t, STATIC_CAST(uint16_t, ulNumber));
15070645126fSAndrew Turner 		break;
15080645126fSAndrew Turner 	case WIDTH_8:
15090645126fSAndrew Turner 		L = STATIC_CAST(int8_t, STATIC_CAST(uint8_t, ulNumber));
15100645126fSAndrew Turner 		break;
15110645126fSAndrew Turner 	}
15120645126fSAndrew Turner 
15130645126fSAndrew Turner 	return L;
15140645126fSAndrew Turner }
15150645126fSAndrew Turner 
15160645126fSAndrew Turner static ulongest
15170645126fSAndrew Turner llluGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber)
15180645126fSAndrew Turner {
15190645126fSAndrew Turner 	size_t zNumberWidth;
15200645126fSAndrew Turner 	ulongest UL = 0;
15210645126fSAndrew Turner 
15220645126fSAndrew Turner 	ASSERT(pType);
15230645126fSAndrew Turner 
15240645126fSAndrew Turner 	zNumberWidth = zDeserializeTypeWidth(pType);
15250645126fSAndrew Turner 	switch (zNumberWidth) {
15260645126fSAndrew Turner 	default:
15270645126fSAndrew Turner 		Report(true, "UBSan: Unexpected %zu-Bit Type in %s\n", zNumberWidth, szLocation);
15280645126fSAndrew Turner 		/* NOTREACHED */
15290645126fSAndrew Turner 	case WIDTH_128:
15300645126fSAndrew Turner #ifdef __SIZEOF_INT128__
15310645126fSAndrew Turner 		memcpy(&UL, REINTERPRET_CAST(ulongest *, ulNumber), sizeof(ulongest));
15320645126fSAndrew Turner 		break;
15330645126fSAndrew Turner #else
15340645126fSAndrew Turner 		Report(true, "UBSan: Unexpected 128-Bit Type in %s\n", szLocation);
15350645126fSAndrew Turner 		/* NOTREACHED */
15360645126fSAndrew Turner #endif
15370645126fSAndrew Turner 	case WIDTH_64:
15380645126fSAndrew Turner 		if (sizeof(ulNumber) * CHAR_BIT < WIDTH_64) {
15390645126fSAndrew Turner 			UL = *REINTERPRET_CAST(uint64_t *, ulNumber);
15400645126fSAndrew Turner 			break;
15410645126fSAndrew Turner 		}
15420645126fSAndrew Turner 		/* FALLTHROUGH */
15430645126fSAndrew Turner 	case WIDTH_32:
15440645126fSAndrew Turner 		/* FALLTHROUGH */
15450645126fSAndrew Turner 	case WIDTH_16:
15460645126fSAndrew Turner 		/* FALLTHROUGH */
15470645126fSAndrew Turner 	case WIDTH_8:
15480645126fSAndrew Turner 		UL = ulNumber;
15490645126fSAndrew Turner 		break;
15500645126fSAndrew Turner 	}
15510645126fSAndrew Turner 
15520645126fSAndrew Turner 	return UL;
15530645126fSAndrew Turner }
15540645126fSAndrew Turner 
15550645126fSAndrew Turner #ifndef _KERNEL
15560645126fSAndrew Turner static void
15570645126fSAndrew Turner DeserializeNumberFloat(char *szLocation, char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber)
15580645126fSAndrew Turner {
15590645126fSAndrew Turner 	size_t zNumberWidth;
15600645126fSAndrew Turner 
15610645126fSAndrew Turner 	ASSERT(szLocation);
15620645126fSAndrew Turner 	ASSERT(pBuffer);
15630645126fSAndrew Turner 	ASSERT(zBUfferLength > 0);
15640645126fSAndrew Turner 	ASSERT(pType);
15650645126fSAndrew Turner 	ASSERT(pType->mTypeKind == KIND_FLOAT);
15660645126fSAndrew Turner 
15670645126fSAndrew Turner 	zNumberWidth = zDeserializeTypeWidth(pType);
15680645126fSAndrew Turner 	switch (zNumberWidth) {
15690645126fSAndrew Turner 	default:
15700645126fSAndrew Turner 		Report(true, "UBSan: Unexpected %zu-Bit Type in %s\n", zNumberWidth, szLocation);
15710645126fSAndrew Turner 		/* NOTREACHED */
15720645126fSAndrew Turner #ifdef __HAVE_LONG_DOUBLE
15730645126fSAndrew Turner 	case WIDTH_128:
15740645126fSAndrew Turner 	case WIDTH_96:
15750645126fSAndrew Turner 	case WIDTH_80:
15760645126fSAndrew Turner 		DeserializeFloatOverPointer(pBuffer, zBUfferLength, pType, REINTERPRET_CAST(unsigned long *, ulNumber));
15770645126fSAndrew Turner 		break;
15780645126fSAndrew Turner #endif
15790645126fSAndrew Turner 	case WIDTH_64:
15800645126fSAndrew Turner 		if (sizeof(ulNumber) * CHAR_BIT < WIDTH_64) {
15810645126fSAndrew Turner 			DeserializeFloatOverPointer(pBuffer, zBUfferLength, pType, REINTERPRET_CAST(unsigned long *, ulNumber));
15820645126fSAndrew Turner 			break;
15830645126fSAndrew Turner 		}
15840645126fSAndrew Turner 	case WIDTH_32:
15850645126fSAndrew Turner 	case WIDTH_16:
15860645126fSAndrew Turner 		DeserializeFloatInlined(pBuffer, zBUfferLength, pType, ulNumber);
15870645126fSAndrew Turner 		break;
15880645126fSAndrew Turner 	}
15890645126fSAndrew Turner }
15900645126fSAndrew Turner #endif
15910645126fSAndrew Turner 
15920645126fSAndrew Turner static void
15930645126fSAndrew Turner DeserializeNumber(char *szLocation, char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber)
15940645126fSAndrew Turner {
15950645126fSAndrew Turner 
15960645126fSAndrew Turner 	ASSERT(szLocation);
15970645126fSAndrew Turner 	ASSERT(pBuffer);
15980645126fSAndrew Turner 	ASSERT(zBUfferLength > 0);
15990645126fSAndrew Turner 	ASSERT(pType);
16000645126fSAndrew Turner 
16010645126fSAndrew Turner 	switch(pType->mTypeKind) {
16020645126fSAndrew Turner 	case KIND_INTEGER:
16030645126fSAndrew Turner 		if (ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT)) {
16040645126fSAndrew Turner 			longest L = llliGetNumber(szLocation, pType, ulNumber);
16050645126fSAndrew Turner 			DeserializeNumberSigned(pBuffer, zBUfferLength, pType, L);
16060645126fSAndrew Turner 		} else {
16070645126fSAndrew Turner 			ulongest UL = llluGetNumber(szLocation, pType, ulNumber);
16080645126fSAndrew Turner 			DeserializeNumberUnsigned(pBuffer, zBUfferLength, pType, UL);
16090645126fSAndrew Turner 		}
16100645126fSAndrew Turner 		break;
16110645126fSAndrew Turner 	case KIND_FLOAT:
16120645126fSAndrew Turner #ifdef _KERNEL
16130645126fSAndrew Turner 		Report(true, "UBSan: Unexpected Float Type in %s\n", szLocation);
16140645126fSAndrew Turner 		/* NOTREACHED */
16150645126fSAndrew Turner #else
16160645126fSAndrew Turner 		DeserializeNumberFloat(szLocation, pBuffer, zBUfferLength, pType, ulNumber);
16170645126fSAndrew Turner #endif
16180645126fSAndrew Turner 		break;
16190645126fSAndrew Turner 	case KIND_UNKNOWN:
16200645126fSAndrew Turner 		Report(true, "UBSan: Unknown Type in %s\n", szLocation);
16210645126fSAndrew Turner 		/* NOTREACHED */
16220645126fSAndrew Turner 		break;
16230645126fSAndrew Turner 	}
16240645126fSAndrew Turner }
16250645126fSAndrew Turner 
16260645126fSAndrew Turner static const char *
16270645126fSAndrew Turner DeserializeTypeCheckKind(uint8_t hhuTypeCheckKind)
16280645126fSAndrew Turner {
16290645126fSAndrew Turner 	const char *rgczTypeCheckKinds[] = {
16300645126fSAndrew Turner 		"load of",
16310645126fSAndrew Turner 		"store to",
16320645126fSAndrew Turner 		"reference binding to",
16330645126fSAndrew Turner 		"member access within",
16340645126fSAndrew Turner 		"member call on",
16350645126fSAndrew Turner 		"constructor call on",
16360645126fSAndrew Turner 		"downcast of",
16370645126fSAndrew Turner 		"downcast of",
16380645126fSAndrew Turner 		"upcast of",
16390645126fSAndrew Turner 		"cast to virtual base of",
16400645126fSAndrew Turner 		"_Nonnull binding to",
16410645126fSAndrew Turner 		"dynamic operation on"
16420645126fSAndrew Turner 	};
16430645126fSAndrew Turner 
16440645126fSAndrew Turner 	ASSERT(__arraycount(rgczTypeCheckKinds) > hhuTypeCheckKind);
16450645126fSAndrew Turner 
16460645126fSAndrew Turner 	return rgczTypeCheckKinds[hhuTypeCheckKind];
16470645126fSAndrew Turner }
16480645126fSAndrew Turner 
16490645126fSAndrew Turner static const char *
16500645126fSAndrew Turner DeserializeBuiltinCheckKind(uint8_t hhuBuiltinCheckKind)
16510645126fSAndrew Turner {
16520645126fSAndrew Turner 	const char *rgczBuiltinCheckKinds[] = {
16530645126fSAndrew Turner 		"ctz()",
16540645126fSAndrew Turner 		"clz()"
16550645126fSAndrew Turner 	};
16560645126fSAndrew Turner 
16570645126fSAndrew Turner 	ASSERT(__arraycount(rgczBuiltinCheckKinds) > hhuBuiltinCheckKind);
16580645126fSAndrew Turner 
16590645126fSAndrew Turner 	return rgczBuiltinCheckKinds[hhuBuiltinCheckKind];
16600645126fSAndrew Turner }
16610645126fSAndrew Turner 
16620645126fSAndrew Turner static const char *
16630645126fSAndrew Turner DeserializeCFICheckKind(uint8_t hhuCFICheckKind)
16640645126fSAndrew Turner {
16650645126fSAndrew Turner 	const char *rgczCFICheckKinds[] = {
16660645126fSAndrew Turner 		"virtual call",					// CFI_VCALL
16670645126fSAndrew Turner 		"non-virtual call",				// CFI_NVCALL
16680645126fSAndrew Turner 		"base-to-derived cast",				// CFI_DERIVEDCAST
16690645126fSAndrew Turner 		"cast to unrelated type",			// CFI_UNRELATEDCAST
16700645126fSAndrew Turner 		"indirect function call",			// CFI_ICALL
16710645126fSAndrew Turner 		"non-virtual pointer to member function call",	// CFI_NVMFCALL
16720645126fSAndrew Turner 		"virtual pointer to member function call",	// CFI_VMFCALL
16730645126fSAndrew Turner 	};
16740645126fSAndrew Turner 
16750645126fSAndrew Turner 	ASSERT(__arraycount(rgczCFICheckKinds) > hhuCFICheckKind);
16760645126fSAndrew Turner 
16770645126fSAndrew Turner 	return rgczCFICheckKinds[hhuCFICheckKind];
16780645126fSAndrew Turner }
16790645126fSAndrew Turner 
16800645126fSAndrew Turner static bool
16810645126fSAndrew Turner isNegativeNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber)
16820645126fSAndrew Turner {
16830645126fSAndrew Turner 
16840645126fSAndrew Turner 	ASSERT(szLocation);
16850645126fSAndrew Turner 	ASSERT(pType);
16860645126fSAndrew Turner 	ASSERT(pType->mTypeKind == KIND_INTEGER);
16870645126fSAndrew Turner 
16880645126fSAndrew Turner 	if (!ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT))
16890645126fSAndrew Turner 		return false;
16900645126fSAndrew Turner 
16910645126fSAndrew Turner 	return llliGetNumber(szLocation, pType, ulNumber) < 0;
16920645126fSAndrew Turner }
16930645126fSAndrew Turner 
16940645126fSAndrew Turner static bool
16950645126fSAndrew Turner isShiftExponentTooLarge(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber, size_t zWidth)
16960645126fSAndrew Turner {
16970645126fSAndrew Turner 
16980645126fSAndrew Turner 	ASSERT(szLocation);
16990645126fSAndrew Turner 	ASSERT(pType);
17000645126fSAndrew Turner 	ASSERT(pType->mTypeKind == KIND_INTEGER);
17010645126fSAndrew Turner 
17020645126fSAndrew Turner 	return llluGetNumber(szLocation, pType, ulNumber) >= zWidth;
17030645126fSAndrew Turner }
1704