xref: /freebsd/contrib/llvm-project/compiler-rt/lib/ubsan/ubsan_handlers.h (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
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;
1500b57cec5SDimitry Andric };
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric /// \brief Implict conversion that changed the value.
1530b57cec5SDimitry Andric RECOVERABLE(implicit_conversion, ImplicitConversionData *Data, ValueHandle Src,
1540b57cec5SDimitry Andric             ValueHandle Dst)
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric /// Known builtin check kinds.
1570b57cec5SDimitry Andric /// Keep in sync with the enum of the same name in CodeGenFunction.h
1580b57cec5SDimitry Andric enum BuiltinCheckKind : unsigned char {
1590b57cec5SDimitry Andric   BCK_CTZPassedZero,
1600b57cec5SDimitry Andric   BCK_CLZPassedZero,
1610b57cec5SDimitry Andric };
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric struct InvalidBuiltinData {
1640b57cec5SDimitry Andric   SourceLocation Loc;
1650b57cec5SDimitry Andric   unsigned char Kind;
1660b57cec5SDimitry Andric };
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric /// Handle a builtin called in an invalid way.
1690b57cec5SDimitry Andric RECOVERABLE(invalid_builtin, InvalidBuiltinData *Data)
1700b57cec5SDimitry Andric 
171*5ffd83dbSDimitry Andric struct InvalidObjCCast {
172*5ffd83dbSDimitry Andric   SourceLocation Loc;
173*5ffd83dbSDimitry Andric   const TypeDescriptor &ExpectedType;
174*5ffd83dbSDimitry Andric };
175*5ffd83dbSDimitry Andric 
176*5ffd83dbSDimitry Andric /// Handle an invalid ObjC cast.
177*5ffd83dbSDimitry Andric RECOVERABLE(invalid_objc_cast, InvalidObjCCast *Data, ValueHandle Pointer)
178*5ffd83dbSDimitry Andric 
1790b57cec5SDimitry Andric struct NonNullReturnData {
1800b57cec5SDimitry Andric   SourceLocation AttrLoc;
1810b57cec5SDimitry Andric };
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric /// \brief Handle returning null from function with the returns_nonnull
1840b57cec5SDimitry Andric /// attribute, or a return type annotated with _Nonnull.
1850b57cec5SDimitry Andric RECOVERABLE(nonnull_return_v1, NonNullReturnData *Data, SourceLocation *Loc)
1860b57cec5SDimitry Andric RECOVERABLE(nullability_return_v1, NonNullReturnData *Data, SourceLocation *Loc)
1870b57cec5SDimitry Andric 
1880b57cec5SDimitry Andric struct NonNullArgData {
1890b57cec5SDimitry Andric   SourceLocation Loc;
1900b57cec5SDimitry Andric   SourceLocation AttrLoc;
1910b57cec5SDimitry Andric   int ArgIndex;
1920b57cec5SDimitry Andric };
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric /// \brief Handle passing null pointer to a function parameter with the nonnull
1950b57cec5SDimitry Andric /// attribute, or a _Nonnull type annotation.
1960b57cec5SDimitry Andric RECOVERABLE(nonnull_arg, NonNullArgData *Data)
1970b57cec5SDimitry Andric RECOVERABLE(nullability_arg, NonNullArgData *Data)
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric struct PointerOverflowData {
2000b57cec5SDimitry Andric   SourceLocation Loc;
2010b57cec5SDimitry Andric };
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric RECOVERABLE(pointer_overflow, PointerOverflowData *Data, ValueHandle Base,
2040b57cec5SDimitry Andric             ValueHandle Result)
2050b57cec5SDimitry Andric 
2060b57cec5SDimitry Andric /// \brief Known CFI check kinds.
2070b57cec5SDimitry Andric /// Keep in sync with the enum of the same name in CodeGenFunction.h
2080b57cec5SDimitry Andric enum CFITypeCheckKind : unsigned char {
2090b57cec5SDimitry Andric   CFITCK_VCall,
2100b57cec5SDimitry Andric   CFITCK_NVCall,
2110b57cec5SDimitry Andric   CFITCK_DerivedCast,
2120b57cec5SDimitry Andric   CFITCK_UnrelatedCast,
2130b57cec5SDimitry Andric   CFITCK_ICall,
2140b57cec5SDimitry Andric   CFITCK_NVMFCall,
2150b57cec5SDimitry Andric   CFITCK_VMFCall,
2160b57cec5SDimitry Andric };
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric struct CFICheckFailData {
2190b57cec5SDimitry Andric   CFITypeCheckKind CheckKind;
2200b57cec5SDimitry Andric   SourceLocation Loc;
2210b57cec5SDimitry Andric   const TypeDescriptor &Type;
2220b57cec5SDimitry Andric };
2230b57cec5SDimitry Andric 
2240b57cec5SDimitry Andric /// \brief Handle control flow integrity failures.
2250b57cec5SDimitry Andric RECOVERABLE(cfi_check_fail, CFICheckFailData *Data, ValueHandle Function,
2260b57cec5SDimitry Andric             uptr VtableIsValid)
2270b57cec5SDimitry Andric 
2280b57cec5SDimitry Andric struct ReportOptions;
2290b57cec5SDimitry Andric 
2300b57cec5SDimitry Andric extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __ubsan_handle_cfi_bad_type(
2310b57cec5SDimitry Andric     CFICheckFailData *Data, ValueHandle Vtable, bool ValidVtable,
2320b57cec5SDimitry Andric     ReportOptions Opts);
2330b57cec5SDimitry Andric 
2340b57cec5SDimitry Andric }
2350b57cec5SDimitry Andric 
2360b57cec5SDimitry Andric #endif // UBSAN_HANDLERS_H
237