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