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