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