10b57cec5SDimitry Andric //===-- ubsan_handlers.h ----------------------------------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // Entry points to the runtime library for Clang's undefined behavior sanitizer. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric #ifndef UBSAN_HANDLERS_H 130b57cec5SDimitry Andric #define UBSAN_HANDLERS_H 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric #include "ubsan_value.h" 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric namespace __ubsan { 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric struct TypeMismatchData { 200b57cec5SDimitry Andric SourceLocation Loc; 210b57cec5SDimitry Andric const TypeDescriptor &Type; 220b57cec5SDimitry Andric unsigned char LogAlignment; 230b57cec5SDimitry Andric unsigned char TypeCheckKind; 240b57cec5SDimitry Andric }; 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric #define UNRECOVERABLE(checkname, ...) \ 270b57cec5SDimitry Andric extern "C" SANITIZER_INTERFACE_ATTRIBUTE NORETURN \ 280b57cec5SDimitry Andric void __ubsan_handle_ ## checkname( __VA_ARGS__ ); 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric #define RECOVERABLE(checkname, ...) \ 310b57cec5SDimitry Andric extern "C" SANITIZER_INTERFACE_ATTRIBUTE \ 320b57cec5SDimitry Andric void __ubsan_handle_ ## checkname( __VA_ARGS__ ); \ 330b57cec5SDimitry Andric extern "C" SANITIZER_INTERFACE_ATTRIBUTE NORETURN \ 340b57cec5SDimitry Andric void __ubsan_handle_ ## checkname ## _abort( __VA_ARGS__ ); 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric /// \brief Handle a runtime type check failure, caused by either a misaligned 370b57cec5SDimitry Andric /// pointer, a null pointer, or a pointer to insufficient storage for the 380b57cec5SDimitry Andric /// type. 390b57cec5SDimitry Andric RECOVERABLE(type_mismatch_v1, TypeMismatchData *Data, ValueHandle Pointer) 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric struct AlignmentAssumptionData { 420b57cec5SDimitry Andric SourceLocation Loc; 430b57cec5SDimitry Andric SourceLocation AssumptionLoc; 440b57cec5SDimitry Andric const TypeDescriptor &Type; 450b57cec5SDimitry Andric }; 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric /// \brief Handle a runtime alignment assumption check failure, 480b57cec5SDimitry Andric /// caused by a misaligned pointer. 490b57cec5SDimitry Andric RECOVERABLE(alignment_assumption, AlignmentAssumptionData *Data, 500b57cec5SDimitry Andric ValueHandle Pointer, ValueHandle Alignment, ValueHandle Offset) 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric struct OverflowData { 530b57cec5SDimitry Andric SourceLocation Loc; 540b57cec5SDimitry Andric const TypeDescriptor &Type; 550b57cec5SDimitry Andric }; 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric /// \brief Handle an integer addition overflow. 580b57cec5SDimitry Andric RECOVERABLE(add_overflow, OverflowData *Data, ValueHandle LHS, ValueHandle RHS) 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric /// \brief Handle an integer subtraction overflow. 610b57cec5SDimitry Andric RECOVERABLE(sub_overflow, OverflowData *Data, ValueHandle LHS, ValueHandle RHS) 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric /// \brief Handle an integer multiplication overflow. 640b57cec5SDimitry Andric RECOVERABLE(mul_overflow, OverflowData *Data, ValueHandle LHS, ValueHandle RHS) 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric /// \brief Handle a signed integer overflow for a unary negate operator. 670b57cec5SDimitry Andric RECOVERABLE(negate_overflow, OverflowData *Data, ValueHandle OldVal) 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric /// \brief Handle an INT_MIN/-1 overflow or division by zero. 700b57cec5SDimitry Andric RECOVERABLE(divrem_overflow, OverflowData *Data, 710b57cec5SDimitry Andric ValueHandle LHS, ValueHandle RHS) 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric struct ShiftOutOfBoundsData { 740b57cec5SDimitry Andric SourceLocation Loc; 750b57cec5SDimitry Andric const TypeDescriptor &LHSType; 760b57cec5SDimitry Andric const TypeDescriptor &RHSType; 770b57cec5SDimitry Andric }; 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric /// \brief Handle a shift where the RHS is out of bounds or a left shift where 800b57cec5SDimitry Andric /// the LHS is negative or overflows. 810b57cec5SDimitry Andric RECOVERABLE(shift_out_of_bounds, ShiftOutOfBoundsData *Data, 820b57cec5SDimitry Andric ValueHandle LHS, ValueHandle RHS) 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric struct OutOfBoundsData { 850b57cec5SDimitry Andric SourceLocation Loc; 860b57cec5SDimitry Andric const TypeDescriptor &ArrayType; 870b57cec5SDimitry Andric const TypeDescriptor &IndexType; 880b57cec5SDimitry Andric }; 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric /// \brief Handle an array index out of bounds error. 910b57cec5SDimitry Andric RECOVERABLE(out_of_bounds, OutOfBoundsData *Data, ValueHandle Index) 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric struct UnreachableData { 940b57cec5SDimitry Andric SourceLocation Loc; 950b57cec5SDimitry Andric }; 960b57cec5SDimitry Andric 970b57cec5SDimitry Andric /// \brief Handle a __builtin_unreachable which is reached. 980b57cec5SDimitry Andric UNRECOVERABLE(builtin_unreachable, UnreachableData *Data) 990b57cec5SDimitry Andric /// \brief Handle reaching the end of a value-returning function. 1000b57cec5SDimitry Andric UNRECOVERABLE(missing_return, UnreachableData *Data) 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric struct VLABoundData { 1030b57cec5SDimitry Andric SourceLocation Loc; 1040b57cec5SDimitry Andric const TypeDescriptor &Type; 1050b57cec5SDimitry Andric }; 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric /// \brief Handle a VLA with a non-positive bound. 1080b57cec5SDimitry Andric RECOVERABLE(vla_bound_not_positive, VLABoundData *Data, ValueHandle Bound) 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric // Keeping this around for binary compatibility with (sanitized) programs 1110b57cec5SDimitry Andric // compiled with older compilers. 1120b57cec5SDimitry Andric struct FloatCastOverflowData { 1130b57cec5SDimitry Andric const TypeDescriptor &FromType; 1140b57cec5SDimitry Andric const TypeDescriptor &ToType; 1150b57cec5SDimitry Andric }; 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric struct FloatCastOverflowDataV2 { 1180b57cec5SDimitry Andric SourceLocation Loc; 1190b57cec5SDimitry Andric const TypeDescriptor &FromType; 1200b57cec5SDimitry Andric const TypeDescriptor &ToType; 1210b57cec5SDimitry Andric }; 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric /// Handle overflow in a conversion to or from a floating-point type. 1240b57cec5SDimitry Andric /// void *Data is one of FloatCastOverflowData* or FloatCastOverflowDataV2* 1250b57cec5SDimitry Andric RECOVERABLE(float_cast_overflow, void *Data, ValueHandle From) 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric struct InvalidValueData { 1280b57cec5SDimitry Andric SourceLocation Loc; 1290b57cec5SDimitry Andric const TypeDescriptor &Type; 1300b57cec5SDimitry Andric }; 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric /// \brief Handle a load of an invalid value for the type. 1330b57cec5SDimitry Andric RECOVERABLE(load_invalid_value, InvalidValueData *Data, ValueHandle Val) 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric /// Known implicit conversion check kinds. 1360b57cec5SDimitry Andric /// Keep in sync with the enum of the same name in CGExprScalar.cpp 1370b57cec5SDimitry Andric enum ImplicitConversionCheckKind : unsigned char { 1380b57cec5SDimitry Andric ICCK_IntegerTruncation = 0, // Legacy, was only used by clang 7. 1390b57cec5SDimitry Andric ICCK_UnsignedIntegerTruncation = 1, 1400b57cec5SDimitry Andric ICCK_SignedIntegerTruncation = 2, 1410b57cec5SDimitry Andric ICCK_IntegerSignChange = 3, 1420b57cec5SDimitry Andric ICCK_SignedIntegerTruncationOrSignChange = 4, 1430b57cec5SDimitry Andric }; 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric struct ImplicitConversionData { 1460b57cec5SDimitry Andric SourceLocation Loc; 1470b57cec5SDimitry Andric const TypeDescriptor &FromType; 1480b57cec5SDimitry Andric const TypeDescriptor &ToType; 1490b57cec5SDimitry Andric /* ImplicitConversionCheckKind */ unsigned char Kind; 150*0fca6ea1SDimitry Andric unsigned int BitfieldBits; 1510b57cec5SDimitry Andric }; 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric /// \brief Implict conversion that changed the value. 1540b57cec5SDimitry Andric RECOVERABLE(implicit_conversion, ImplicitConversionData *Data, ValueHandle Src, 1550b57cec5SDimitry Andric ValueHandle Dst) 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric /// Known builtin check kinds. 1580b57cec5SDimitry Andric /// Keep in sync with the enum of the same name in CodeGenFunction.h 1590b57cec5SDimitry Andric enum BuiltinCheckKind : unsigned char { 1600b57cec5SDimitry Andric BCK_CTZPassedZero, 1610b57cec5SDimitry Andric BCK_CLZPassedZero, 1620b57cec5SDimitry Andric }; 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric struct InvalidBuiltinData { 1650b57cec5SDimitry Andric SourceLocation Loc; 1660b57cec5SDimitry Andric unsigned char Kind; 1670b57cec5SDimitry Andric }; 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andric /// Handle a builtin called in an invalid way. 1700b57cec5SDimitry Andric RECOVERABLE(invalid_builtin, InvalidBuiltinData *Data) 1710b57cec5SDimitry Andric 1725ffd83dbSDimitry Andric struct InvalidObjCCast { 1735ffd83dbSDimitry Andric SourceLocation Loc; 1745ffd83dbSDimitry Andric const TypeDescriptor &ExpectedType; 1755ffd83dbSDimitry Andric }; 1765ffd83dbSDimitry Andric 1775ffd83dbSDimitry Andric /// Handle an invalid ObjC cast. 1785ffd83dbSDimitry Andric RECOVERABLE(invalid_objc_cast, InvalidObjCCast *Data, ValueHandle Pointer) 1795ffd83dbSDimitry Andric 1800b57cec5SDimitry Andric struct NonNullReturnData { 1810b57cec5SDimitry Andric SourceLocation AttrLoc; 1820b57cec5SDimitry Andric }; 1830b57cec5SDimitry Andric 1840b57cec5SDimitry Andric /// \brief Handle returning null from function with the returns_nonnull 1850b57cec5SDimitry Andric /// attribute, or a return type annotated with _Nonnull. 1860b57cec5SDimitry Andric RECOVERABLE(nonnull_return_v1, NonNullReturnData *Data, SourceLocation *Loc) 1870b57cec5SDimitry Andric RECOVERABLE(nullability_return_v1, NonNullReturnData *Data, SourceLocation *Loc) 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric struct NonNullArgData { 1900b57cec5SDimitry Andric SourceLocation Loc; 1910b57cec5SDimitry Andric SourceLocation AttrLoc; 1920b57cec5SDimitry Andric int ArgIndex; 1930b57cec5SDimitry Andric }; 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric /// \brief Handle passing null pointer to a function parameter with the nonnull 1960b57cec5SDimitry Andric /// attribute, or a _Nonnull type annotation. 1970b57cec5SDimitry Andric RECOVERABLE(nonnull_arg, NonNullArgData *Data) 1980b57cec5SDimitry Andric RECOVERABLE(nullability_arg, NonNullArgData *Data) 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andric struct PointerOverflowData { 2010b57cec5SDimitry Andric SourceLocation Loc; 2020b57cec5SDimitry Andric }; 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric RECOVERABLE(pointer_overflow, PointerOverflowData *Data, ValueHandle Base, 2050b57cec5SDimitry Andric ValueHandle Result) 2060b57cec5SDimitry Andric 2070b57cec5SDimitry Andric /// \brief Known CFI check kinds. 2080b57cec5SDimitry Andric /// Keep in sync with the enum of the same name in CodeGenFunction.h 2090b57cec5SDimitry Andric enum CFITypeCheckKind : unsigned char { 2100b57cec5SDimitry Andric CFITCK_VCall, 2110b57cec5SDimitry Andric CFITCK_NVCall, 2120b57cec5SDimitry Andric CFITCK_DerivedCast, 2130b57cec5SDimitry Andric CFITCK_UnrelatedCast, 2140b57cec5SDimitry Andric CFITCK_ICall, 2150b57cec5SDimitry Andric CFITCK_NVMFCall, 2160b57cec5SDimitry Andric CFITCK_VMFCall, 2170b57cec5SDimitry Andric }; 2180b57cec5SDimitry Andric 2190b57cec5SDimitry Andric struct CFICheckFailData { 2200b57cec5SDimitry Andric CFITypeCheckKind CheckKind; 2210b57cec5SDimitry Andric SourceLocation Loc; 2220b57cec5SDimitry Andric const TypeDescriptor &Type; 2230b57cec5SDimitry Andric }; 2240b57cec5SDimitry Andric 2250b57cec5SDimitry Andric /// \brief Handle control flow integrity failures. 2260b57cec5SDimitry Andric RECOVERABLE(cfi_check_fail, CFICheckFailData *Data, ValueHandle Function, 2270b57cec5SDimitry Andric uptr VtableIsValid) 2280b57cec5SDimitry Andric 2290b57cec5SDimitry Andric struct ReportOptions; 2300b57cec5SDimitry Andric 2310b57cec5SDimitry Andric extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __ubsan_handle_cfi_bad_type( 2320b57cec5SDimitry Andric CFICheckFailData *Data, ValueHandle Vtable, bool ValidVtable, 2330b57cec5SDimitry Andric ReportOptions Opts); 2340b57cec5SDimitry Andric 23506c3fb27SDimitry Andric struct FunctionTypeMismatchData { 23606c3fb27SDimitry Andric SourceLocation Loc; 23706c3fb27SDimitry Andric const TypeDescriptor &Type; 23806c3fb27SDimitry Andric }; 23906c3fb27SDimitry Andric 24006c3fb27SDimitry Andric extern "C" SANITIZER_INTERFACE_ATTRIBUTE void 24106c3fb27SDimitry Andric __ubsan_handle_function_type_mismatch(FunctionTypeMismatchData *Data, 24206c3fb27SDimitry Andric ValueHandle Val); 24306c3fb27SDimitry Andric extern "C" SANITIZER_INTERFACE_ATTRIBUTE void 24406c3fb27SDimitry Andric __ubsan_handle_function_type_mismatch_abort(FunctionTypeMismatchData *Data, 24506c3fb27SDimitry Andric ValueHandle Val); 2460b57cec5SDimitry Andric } 2470b57cec5SDimitry Andric 2480b57cec5SDimitry Andric #endif // UBSAN_HANDLERS_H 249