Home | History | Annotate | Line # | Download | only in ubsan
      1  1.1  kamil //===-- ubsan_handlers.cc -------------------------------------------------===//
      2  1.1  kamil //
      3  1.1  kamil //                     The LLVM Compiler Infrastructure
      4  1.1  kamil //
      5  1.1  kamil // This file is distributed under the University of Illinois Open Source
      6  1.1  kamil // License. See LICENSE.TXT for details.
      7  1.1  kamil //
      8  1.1  kamil //===----------------------------------------------------------------------===//
      9  1.1  kamil //
     10  1.1  kamil // Error logging entry points for the UBSan runtime.
     11  1.1  kamil //
     12  1.1  kamil //===----------------------------------------------------------------------===//
     13  1.1  kamil 
     14  1.1  kamil #include "ubsan_platform.h"
     15  1.1  kamil #if CAN_SANITIZE_UB
     16  1.1  kamil #include "ubsan_handlers.h"
     17  1.1  kamil #include "ubsan_diag.h"
     18  1.1  kamil #include "ubsan_flags.h"
     19  1.1  kamil #include "ubsan_monitor.h"
     20  1.1  kamil 
     21  1.1  kamil #include "sanitizer_common/sanitizer_common.h"
     22  1.1  kamil 
     23  1.1  kamil using namespace __sanitizer;
     24  1.1  kamil using namespace __ubsan;
     25  1.1  kamil 
     26  1.1  kamil namespace __ubsan {
     27  1.1  kamil bool ignoreReport(SourceLocation SLoc, ReportOptions Opts, ErrorType ET) {
     28  1.1  kamil   // We are not allowed to skip error report: if we are in unrecoverable
     29  1.1  kamil   // handler, we have to terminate the program right now, and therefore
     30  1.1  kamil   // have to print some diagnostic.
     31  1.1  kamil   //
     32  1.1  kamil   // Even if source location is disabled, it doesn't mean that we have
     33  1.1  kamil   // already report an error to the user: some concurrently running
     34  1.1  kamil   // thread could have acquired it, but not yet printed the report.
     35  1.1  kamil   if (Opts.FromUnrecoverableHandler)
     36  1.1  kamil     return false;
     37  1.1  kamil   return SLoc.isDisabled() || IsPCSuppressed(ET, Opts.pc, SLoc.getFilename());
     38  1.1  kamil }
     39  1.1  kamil 
     40  1.1  kamil const char *TypeCheckKinds[] = {
     41  1.1  kamil     "load of", "store to", "reference binding to", "member access within",
     42  1.1  kamil     "member call on", "constructor call on", "downcast of", "downcast of",
     43  1.1  kamil     "upcast of", "cast to virtual base of", "_Nonnull binding to",
     44  1.1  kamil     "dynamic operation on"};
     45  1.1  kamil }
     46  1.1  kamil 
     47  1.1  kamil static void handleTypeMismatchImpl(TypeMismatchData *Data, ValueHandle Pointer,
     48  1.1  kamil                                    ReportOptions Opts) {
     49  1.1  kamil   Location Loc = Data->Loc.acquire();
     50  1.1  kamil 
     51  1.1  kamil   uptr Alignment = (uptr)1 << Data->LogAlignment;
     52  1.1  kamil   ErrorType ET;
     53  1.1  kamil   if (!Pointer)
     54  1.1  kamil     ET = ErrorType::NullPointerUse;
     55  1.1  kamil   else if (Pointer & (Alignment - 1))
     56  1.1  kamil     ET = ErrorType::MisalignedPointerUse;
     57  1.1  kamil   else
     58  1.1  kamil     ET = ErrorType::InsufficientObjectSize;
     59  1.1  kamil 
     60  1.1  kamil   // Use the SourceLocation from Data to track deduplication, even if it's
     61  1.1  kamil   // invalid.
     62  1.1  kamil   if (ignoreReport(Loc.getSourceLocation(), Opts, ET))
     63  1.1  kamil     return;
     64  1.1  kamil 
     65  1.1  kamil   SymbolizedStackHolder FallbackLoc;
     66  1.1  kamil   if (Data->Loc.isInvalid()) {
     67  1.1  kamil     FallbackLoc.reset(getCallerLocation(Opts.pc));
     68  1.1  kamil     Loc = FallbackLoc;
     69  1.1  kamil   }
     70  1.1  kamil 
     71  1.1  kamil   ScopedReport R(Opts, Loc, ET);
     72  1.1  kamil 
     73  1.1  kamil   switch (ET) {
     74  1.1  kamil   case ErrorType::NullPointerUse:
     75  1.1  kamil     Diag(Loc, DL_Error, ET, "%0 null pointer of type %1")
     76  1.1  kamil         << TypeCheckKinds[Data->TypeCheckKind] << Data->Type;
     77  1.1  kamil     break;
     78  1.1  kamil   case ErrorType::MisalignedPointerUse:
     79  1.1  kamil     Diag(Loc, DL_Error, ET, "%0 misaligned address %1 for type %3, "
     80  1.1  kamil                         "which requires %2 byte alignment")
     81  1.1  kamil         << TypeCheckKinds[Data->TypeCheckKind] << (void *)Pointer << Alignment
     82  1.1  kamil         << Data->Type;
     83  1.1  kamil     break;
     84  1.1  kamil   case ErrorType::InsufficientObjectSize:
     85  1.1  kamil     Diag(Loc, DL_Error, ET, "%0 address %1 with insufficient space "
     86  1.1  kamil                         "for an object of type %2")
     87  1.1  kamil         << TypeCheckKinds[Data->TypeCheckKind] << (void *)Pointer << Data->Type;
     88  1.1  kamil     break;
     89  1.1  kamil   default:
     90  1.1  kamil     UNREACHABLE("unexpected error type!");
     91  1.1  kamil   }
     92  1.1  kamil 
     93  1.1  kamil   if (Pointer)
     94  1.1  kamil     Diag(Pointer, DL_Note, ET, "pointer points here");
     95  1.1  kamil }
     96  1.1  kamil 
     97  1.1  kamil void __ubsan::__ubsan_handle_type_mismatch_v1(TypeMismatchData *Data,
     98  1.1  kamil                                               ValueHandle Pointer) {
     99  1.1  kamil   GET_REPORT_OPTIONS(false);
    100  1.1  kamil   handleTypeMismatchImpl(Data, Pointer, Opts);
    101  1.1  kamil }
    102  1.1  kamil void __ubsan::__ubsan_handle_type_mismatch_v1_abort(TypeMismatchData *Data,
    103  1.1  kamil                                                     ValueHandle Pointer) {
    104  1.1  kamil   GET_REPORT_OPTIONS(true);
    105  1.1  kamil   handleTypeMismatchImpl(Data, Pointer, Opts);
    106  1.1  kamil   Die();
    107  1.1  kamil }
    108  1.1  kamil 
    109  1.1  kamil /// \brief Common diagnostic emission for various forms of integer overflow.
    110  1.1  kamil template <typename T>
    111  1.1  kamil static void handleIntegerOverflowImpl(OverflowData *Data, ValueHandle LHS,
    112  1.1  kamil                                       const char *Operator, T RHS,
    113  1.1  kamil                                       ReportOptions Opts) {
    114  1.1  kamil   SourceLocation Loc = Data->Loc.acquire();
    115  1.1  kamil   bool IsSigned = Data->Type.isSignedIntegerTy();
    116  1.1  kamil   ErrorType ET = IsSigned ? ErrorType::SignedIntegerOverflow
    117  1.1  kamil                           : ErrorType::UnsignedIntegerOverflow;
    118  1.1  kamil 
    119  1.1  kamil   if (ignoreReport(Loc, Opts, ET))
    120  1.1  kamil     return;
    121  1.1  kamil 
    122  1.1  kamil   // If this is an unsigned overflow in non-fatal mode, potentially ignore it.
    123  1.1  kamil   if (!IsSigned && !Opts.FromUnrecoverableHandler &&
    124  1.1  kamil       flags()->silence_unsigned_overflow)
    125  1.1  kamil     return;
    126  1.1  kamil 
    127  1.1  kamil   ScopedReport R(Opts, Loc, ET);
    128  1.1  kamil 
    129  1.1  kamil   Diag(Loc, DL_Error, ET, "%0 integer overflow: "
    130  1.1  kamil                           "%1 %2 %3 cannot be represented in type %4")
    131  1.1  kamil       << (IsSigned ? "signed" : "unsigned") << Value(Data->Type, LHS)
    132  1.1  kamil       << Operator << RHS << Data->Type;
    133  1.1  kamil }
    134  1.1  kamil 
    135  1.1  kamil #define UBSAN_OVERFLOW_HANDLER(handler_name, op, unrecoverable)                \
    136  1.1  kamil   void __ubsan::handler_name(OverflowData *Data, ValueHandle LHS,              \
    137  1.1  kamil                              ValueHandle RHS) {                                \
    138  1.1  kamil     GET_REPORT_OPTIONS(unrecoverable);                                         \
    139  1.1  kamil     handleIntegerOverflowImpl(Data, LHS, op, Value(Data->Type, RHS), Opts);    \
    140  1.1  kamil     if (unrecoverable)                                                         \
    141  1.1  kamil       Die();                                                                   \
    142  1.1  kamil   }
    143  1.1  kamil 
    144  1.1  kamil UBSAN_OVERFLOW_HANDLER(__ubsan_handle_add_overflow, "+", false)
    145  1.1  kamil UBSAN_OVERFLOW_HANDLER(__ubsan_handle_add_overflow_abort, "+", true)
    146  1.1  kamil UBSAN_OVERFLOW_HANDLER(__ubsan_handle_sub_overflow, "-", false)
    147  1.1  kamil UBSAN_OVERFLOW_HANDLER(__ubsan_handle_sub_overflow_abort, "-", true)
    148  1.1  kamil UBSAN_OVERFLOW_HANDLER(__ubsan_handle_mul_overflow, "*", false)
    149  1.1  kamil UBSAN_OVERFLOW_HANDLER(__ubsan_handle_mul_overflow_abort, "*", true)
    150  1.1  kamil 
    151  1.1  kamil static void handleNegateOverflowImpl(OverflowData *Data, ValueHandle OldVal,
    152  1.1  kamil                                      ReportOptions Opts) {
    153  1.1  kamil   SourceLocation Loc = Data->Loc.acquire();
    154  1.1  kamil   bool IsSigned = Data->Type.isSignedIntegerTy();
    155  1.1  kamil   ErrorType ET = IsSigned ? ErrorType::SignedIntegerOverflow
    156  1.1  kamil                           : ErrorType::UnsignedIntegerOverflow;
    157  1.1  kamil 
    158  1.1  kamil   if (ignoreReport(Loc, Opts, ET))
    159  1.1  kamil     return;
    160  1.1  kamil 
    161  1.1  kamil   if (!IsSigned && flags()->silence_unsigned_overflow)
    162  1.1  kamil     return;
    163  1.1  kamil 
    164  1.1  kamil   ScopedReport R(Opts, Loc, ET);
    165  1.1  kamil 
    166  1.1  kamil   if (IsSigned)
    167  1.1  kamil     Diag(Loc, DL_Error, ET,
    168  1.1  kamil          "negation of %0 cannot be represented in type %1; "
    169  1.1  kamil          "cast to an unsigned type to negate this value to itself")
    170  1.1  kamil         << Value(Data->Type, OldVal) << Data->Type;
    171  1.1  kamil   else
    172  1.1  kamil     Diag(Loc, DL_Error, ET, "negation of %0 cannot be represented in type %1")
    173  1.1  kamil         << Value(Data->Type, OldVal) << Data->Type;
    174  1.1  kamil }
    175  1.1  kamil 
    176  1.1  kamil void __ubsan::__ubsan_handle_negate_overflow(OverflowData *Data,
    177  1.1  kamil                                              ValueHandle OldVal) {
    178  1.1  kamil   GET_REPORT_OPTIONS(false);
    179  1.1  kamil   handleNegateOverflowImpl(Data, OldVal, Opts);
    180  1.1  kamil }
    181  1.1  kamil void __ubsan::__ubsan_handle_negate_overflow_abort(OverflowData *Data,
    182  1.1  kamil                                                     ValueHandle OldVal) {
    183  1.1  kamil   GET_REPORT_OPTIONS(true);
    184  1.1  kamil   handleNegateOverflowImpl(Data, OldVal, Opts);
    185  1.1  kamil   Die();
    186  1.1  kamil }
    187  1.1  kamil 
    188  1.1  kamil static void handleDivremOverflowImpl(OverflowData *Data, ValueHandle LHS,
    189  1.1  kamil                                      ValueHandle RHS, ReportOptions Opts) {
    190  1.1  kamil   SourceLocation Loc = Data->Loc.acquire();
    191  1.1  kamil   Value LHSVal(Data->Type, LHS);
    192  1.1  kamil   Value RHSVal(Data->Type, RHS);
    193  1.1  kamil 
    194  1.1  kamil   ErrorType ET;
    195  1.1  kamil   if (RHSVal.isMinusOne())
    196  1.1  kamil     ET = ErrorType::SignedIntegerOverflow;
    197  1.1  kamil   else if (Data->Type.isIntegerTy())
    198  1.1  kamil     ET = ErrorType::IntegerDivideByZero;
    199  1.1  kamil   else
    200  1.1  kamil     ET = ErrorType::FloatDivideByZero;
    201  1.1  kamil 
    202  1.1  kamil   if (ignoreReport(Loc, Opts, ET))
    203  1.1  kamil     return;
    204  1.1  kamil 
    205  1.1  kamil   ScopedReport R(Opts, Loc, ET);
    206  1.1  kamil 
    207  1.1  kamil   switch (ET) {
    208  1.1  kamil   case ErrorType::SignedIntegerOverflow:
    209  1.1  kamil     Diag(Loc, DL_Error, ET,
    210  1.1  kamil          "division of %0 by -1 cannot be represented in type %1")
    211  1.1  kamil         << LHSVal << Data->Type;
    212  1.1  kamil     break;
    213  1.1  kamil   default:
    214  1.1  kamil     Diag(Loc, DL_Error, ET, "division by zero");
    215  1.1  kamil     break;
    216  1.1  kamil   }
    217  1.1  kamil }
    218  1.1  kamil 
    219  1.1  kamil void __ubsan::__ubsan_handle_divrem_overflow(OverflowData *Data,
    220  1.1  kamil                                              ValueHandle LHS, ValueHandle RHS) {
    221  1.1  kamil   GET_REPORT_OPTIONS(false);
    222  1.1  kamil   handleDivremOverflowImpl(Data, LHS, RHS, Opts);
    223  1.1  kamil }
    224  1.1  kamil void __ubsan::__ubsan_handle_divrem_overflow_abort(OverflowData *Data,
    225  1.1  kamil                                                     ValueHandle LHS,
    226  1.1  kamil                                                     ValueHandle RHS) {
    227  1.1  kamil   GET_REPORT_OPTIONS(true);
    228  1.1  kamil   handleDivremOverflowImpl(Data, LHS, RHS, Opts);
    229  1.1  kamil   Die();
    230  1.1  kamil }
    231  1.1  kamil 
    232  1.1  kamil static void handleShiftOutOfBoundsImpl(ShiftOutOfBoundsData *Data,
    233  1.1  kamil                                        ValueHandle LHS, ValueHandle RHS,
    234  1.1  kamil                                        ReportOptions Opts) {
    235  1.1  kamil   SourceLocation Loc = Data->Loc.acquire();
    236  1.1  kamil   Value LHSVal(Data->LHSType, LHS);
    237  1.1  kamil   Value RHSVal(Data->RHSType, RHS);
    238  1.1  kamil 
    239  1.1  kamil   ErrorType ET;
    240  1.1  kamil   if (RHSVal.isNegative() ||
    241  1.1  kamil       RHSVal.getPositiveIntValue() >= Data->LHSType.getIntegerBitWidth())
    242  1.1  kamil     ET = ErrorType::InvalidShiftExponent;
    243  1.1  kamil   else
    244  1.1  kamil     ET = ErrorType::InvalidShiftBase;
    245  1.1  kamil 
    246  1.1  kamil   if (ignoreReport(Loc, Opts, ET))
    247  1.1  kamil     return;
    248  1.1  kamil 
    249  1.1  kamil   ScopedReport R(Opts, Loc, ET);
    250  1.1  kamil 
    251  1.1  kamil   if (ET == ErrorType::InvalidShiftExponent) {
    252  1.1  kamil     if (RHSVal.isNegative())
    253  1.1  kamil       Diag(Loc, DL_Error, ET, "shift exponent %0 is negative") << RHSVal;
    254  1.1  kamil     else
    255  1.1  kamil       Diag(Loc, DL_Error, ET,
    256  1.1  kamil            "shift exponent %0 is too large for %1-bit type %2")
    257  1.1  kamil           << RHSVal << Data->LHSType.getIntegerBitWidth() << Data->LHSType;
    258  1.1  kamil   } else {
    259  1.1  kamil     if (LHSVal.isNegative())
    260  1.1  kamil       Diag(Loc, DL_Error, ET, "left shift of negative value %0") << LHSVal;
    261  1.1  kamil     else
    262  1.1  kamil       Diag(Loc, DL_Error, ET,
    263  1.1  kamil            "left shift of %0 by %1 places cannot be represented in type %2")
    264  1.1  kamil           << LHSVal << RHSVal << Data->LHSType;
    265  1.1  kamil   }
    266  1.1  kamil }
    267  1.1  kamil 
    268  1.1  kamil void __ubsan::__ubsan_handle_shift_out_of_bounds(ShiftOutOfBoundsData *Data,
    269  1.1  kamil                                                  ValueHandle LHS,
    270  1.1  kamil                                                  ValueHandle RHS) {
    271  1.1  kamil   GET_REPORT_OPTIONS(false);
    272  1.1  kamil   handleShiftOutOfBoundsImpl(Data, LHS, RHS, Opts);
    273  1.1  kamil }
    274  1.1  kamil void __ubsan::__ubsan_handle_shift_out_of_bounds_abort(
    275  1.1  kamil                                                      ShiftOutOfBoundsData *Data,
    276  1.1  kamil                                                      ValueHandle LHS,
    277  1.1  kamil                                                      ValueHandle RHS) {
    278  1.1  kamil   GET_REPORT_OPTIONS(true);
    279  1.1  kamil   handleShiftOutOfBoundsImpl(Data, LHS, RHS, Opts);
    280  1.1  kamil   Die();
    281  1.1  kamil }
    282  1.1  kamil 
    283  1.1  kamil static void handleOutOfBoundsImpl(OutOfBoundsData *Data, ValueHandle Index,
    284  1.1  kamil                                   ReportOptions Opts) {
    285  1.1  kamil   SourceLocation Loc = Data->Loc.acquire();
    286  1.1  kamil   ErrorType ET = ErrorType::OutOfBoundsIndex;
    287  1.1  kamil 
    288  1.1  kamil   if (ignoreReport(Loc, Opts, ET))
    289  1.1  kamil     return;
    290  1.1  kamil 
    291  1.1  kamil   ScopedReport R(Opts, Loc, ET);
    292  1.1  kamil 
    293  1.1  kamil   Value IndexVal(Data->IndexType, Index);
    294  1.1  kamil   Diag(Loc, DL_Error, ET, "index %0 out of bounds for type %1")
    295  1.1  kamil     << IndexVal << Data->ArrayType;
    296  1.1  kamil }
    297  1.1  kamil 
    298  1.1  kamil void __ubsan::__ubsan_handle_out_of_bounds(OutOfBoundsData *Data,
    299  1.1  kamil                                            ValueHandle Index) {
    300  1.1  kamil   GET_REPORT_OPTIONS(false);
    301  1.1  kamil   handleOutOfBoundsImpl(Data, Index, Opts);
    302  1.1  kamil }
    303  1.1  kamil void __ubsan::__ubsan_handle_out_of_bounds_abort(OutOfBoundsData *Data,
    304  1.1  kamil                                                  ValueHandle Index) {
    305  1.1  kamil   GET_REPORT_OPTIONS(true);
    306  1.1  kamil   handleOutOfBoundsImpl(Data, Index, Opts);
    307  1.1  kamil   Die();
    308  1.1  kamil }
    309  1.1  kamil 
    310  1.1  kamil static void handleBuiltinUnreachableImpl(UnreachableData *Data,
    311  1.1  kamil                                          ReportOptions Opts) {
    312  1.1  kamil   ErrorType ET = ErrorType::UnreachableCall;
    313  1.1  kamil   ScopedReport R(Opts, Data->Loc, ET);
    314  1.1  kamil   Diag(Data->Loc, DL_Error, ET,
    315  1.1  kamil        "execution reached an unreachable program point");
    316  1.1  kamil }
    317  1.1  kamil 
    318  1.1  kamil void __ubsan::__ubsan_handle_builtin_unreachable(UnreachableData *Data) {
    319  1.1  kamil   GET_REPORT_OPTIONS(true);
    320  1.1  kamil   handleBuiltinUnreachableImpl(Data, Opts);
    321  1.1  kamil   Die();
    322  1.1  kamil }
    323  1.1  kamil 
    324  1.1  kamil static void handleMissingReturnImpl(UnreachableData *Data, ReportOptions Opts) {
    325  1.1  kamil   ErrorType ET = ErrorType::MissingReturn;
    326  1.1  kamil   ScopedReport R(Opts, Data->Loc, ET);
    327  1.1  kamil   Diag(Data->Loc, DL_Error, ET,
    328  1.1  kamil        "execution reached the end of a value-returning function "
    329  1.1  kamil        "without returning a value");
    330  1.1  kamil }
    331  1.1  kamil 
    332  1.1  kamil void __ubsan::__ubsan_handle_missing_return(UnreachableData *Data) {
    333  1.1  kamil   GET_REPORT_OPTIONS(true);
    334  1.1  kamil   handleMissingReturnImpl(Data, Opts);
    335  1.1  kamil   Die();
    336  1.1  kamil }
    337  1.1  kamil 
    338  1.1  kamil static void handleVLABoundNotPositive(VLABoundData *Data, ValueHandle Bound,
    339  1.1  kamil                                       ReportOptions Opts) {
    340  1.1  kamil   SourceLocation Loc = Data->Loc.acquire();
    341  1.1  kamil   ErrorType ET = ErrorType::NonPositiveVLAIndex;
    342  1.1  kamil 
    343  1.1  kamil   if (ignoreReport(Loc, Opts, ET))
    344  1.1  kamil     return;
    345  1.1  kamil 
    346  1.1  kamil   ScopedReport R(Opts, Loc, ET);
    347  1.1  kamil 
    348  1.1  kamil   Diag(Loc, DL_Error, ET, "variable length array bound evaluates to "
    349  1.1  kamil                           "non-positive value %0")
    350  1.1  kamil       << Value(Data->Type, Bound);
    351  1.1  kamil }
    352  1.1  kamil 
    353  1.1  kamil void __ubsan::__ubsan_handle_vla_bound_not_positive(VLABoundData *Data,
    354  1.1  kamil                                                     ValueHandle Bound) {
    355  1.1  kamil   GET_REPORT_OPTIONS(false);
    356  1.1  kamil   handleVLABoundNotPositive(Data, Bound, Opts);
    357  1.1  kamil }
    358  1.1  kamil void __ubsan::__ubsan_handle_vla_bound_not_positive_abort(VLABoundData *Data,
    359  1.1  kamil                                                           ValueHandle Bound) {
    360  1.1  kamil   GET_REPORT_OPTIONS(true);
    361  1.1  kamil   handleVLABoundNotPositive(Data, Bound, Opts);
    362  1.1  kamil   Die();
    363  1.1  kamil }
    364  1.1  kamil 
    365  1.1  kamil static bool looksLikeFloatCastOverflowDataV1(void *Data) {
    366  1.1  kamil   // First field is either a pointer to filename or a pointer to a
    367  1.1  kamil   // TypeDescriptor.
    368  1.1  kamil   u8 *FilenameOrTypeDescriptor;
    369  1.1  kamil   internal_memcpy(&FilenameOrTypeDescriptor, Data,
    370  1.1  kamil                   sizeof(FilenameOrTypeDescriptor));
    371  1.1  kamil 
    372  1.1  kamil   // Heuristic: For float_cast_overflow, the TypeKind will be either TK_Integer
    373  1.1  kamil   // (0x0), TK_Float (0x1) or TK_Unknown (0xff). If both types are known,
    374  1.1  kamil   // adding both bytes will be 0 or 1 (for BE or LE). If it were a filename,
    375  1.1  kamil   // adding two printable characters will not yield such a value. Otherwise,
    376  1.1  kamil   // if one of them is 0xff, this is most likely TK_Unknown type descriptor.
    377  1.1  kamil   u16 MaybeFromTypeKind =
    378  1.1  kamil       FilenameOrTypeDescriptor[0] + FilenameOrTypeDescriptor[1];
    379  1.1  kamil   return MaybeFromTypeKind < 2 || FilenameOrTypeDescriptor[0] == 0xff ||
    380  1.1  kamil          FilenameOrTypeDescriptor[1] == 0xff;
    381  1.1  kamil }
    382  1.1  kamil 
    383  1.1  kamil static void handleFloatCastOverflow(void *DataPtr, ValueHandle From,
    384  1.1  kamil                                     ReportOptions Opts) {
    385  1.1  kamil   SymbolizedStackHolder CallerLoc;
    386  1.1  kamil   Location Loc;
    387  1.1  kamil   const TypeDescriptor *FromType, *ToType;
    388  1.1  kamil   ErrorType ET = ErrorType::FloatCastOverflow;
    389  1.1  kamil 
    390  1.1  kamil   if (looksLikeFloatCastOverflowDataV1(DataPtr)) {
    391  1.1  kamil     auto Data = reinterpret_cast<FloatCastOverflowData *>(DataPtr);
    392  1.1  kamil     CallerLoc.reset(getCallerLocation(Opts.pc));
    393  1.1  kamil     Loc = CallerLoc;
    394  1.1  kamil     FromType = &Data->FromType;
    395  1.1  kamil     ToType = &Data->ToType;
    396  1.1  kamil   } else {
    397  1.1  kamil     auto Data = reinterpret_cast<FloatCastOverflowDataV2 *>(DataPtr);
    398  1.1  kamil     SourceLocation SLoc = Data->Loc.acquire();
    399  1.1  kamil     if (ignoreReport(SLoc, Opts, ET))
    400  1.1  kamil       return;
    401  1.1  kamil     Loc = SLoc;
    402  1.1  kamil     FromType = &Data->FromType;
    403  1.1  kamil     ToType = &Data->ToType;
    404  1.1  kamil   }
    405  1.1  kamil 
    406  1.1  kamil   ScopedReport R(Opts, Loc, ET);
    407  1.1  kamil 
    408  1.1  kamil   Diag(Loc, DL_Error, ET,
    409  1.1  kamil        "%0 is outside the range of representable values of type %2")
    410  1.1  kamil       << Value(*FromType, From) << *FromType << *ToType;
    411  1.1  kamil }
    412  1.1  kamil 
    413  1.1  kamil void __ubsan::__ubsan_handle_float_cast_overflow(void *Data, ValueHandle From) {
    414  1.1  kamil   GET_REPORT_OPTIONS(false);
    415  1.1  kamil   handleFloatCastOverflow(Data, From, Opts);
    416  1.1  kamil }
    417  1.1  kamil void __ubsan::__ubsan_handle_float_cast_overflow_abort(void *Data,
    418  1.1  kamil                                                        ValueHandle From) {
    419  1.1  kamil   GET_REPORT_OPTIONS(true);
    420  1.1  kamil   handleFloatCastOverflow(Data, From, Opts);
    421  1.1  kamil   Die();
    422  1.1  kamil }
    423  1.1  kamil 
    424  1.1  kamil static void handleLoadInvalidValue(InvalidValueData *Data, ValueHandle Val,
    425  1.1  kamil                                    ReportOptions Opts) {
    426  1.1  kamil   SourceLocation Loc = Data->Loc.acquire();
    427  1.1  kamil   // This check could be more precise if we used different handlers for
    428  1.1  kamil   // -fsanitize=bool and -fsanitize=enum.
    429  1.1  kamil   bool IsBool = (0 == internal_strcmp(Data->Type.getTypeName(), "'bool'")) ||
    430  1.1  kamil                 (0 == internal_strncmp(Data->Type.getTypeName(), "'BOOL'", 6));
    431  1.1  kamil   ErrorType ET =
    432  1.1  kamil       IsBool ? ErrorType::InvalidBoolLoad : ErrorType::InvalidEnumLoad;
    433  1.1  kamil 
    434  1.1  kamil   if (ignoreReport(Loc, Opts, ET))
    435  1.1  kamil     return;
    436  1.1  kamil 
    437  1.1  kamil   ScopedReport R(Opts, Loc, ET);
    438  1.1  kamil 
    439  1.1  kamil   Diag(Loc, DL_Error, ET,
    440  1.1  kamil        "load of value %0, which is not a valid value for type %1")
    441  1.1  kamil       << Value(Data->Type, Val) << Data->Type;
    442  1.1  kamil }
    443  1.1  kamil 
    444  1.1  kamil void __ubsan::__ubsan_handle_load_invalid_value(InvalidValueData *Data,
    445  1.1  kamil                                                 ValueHandle Val) {
    446  1.1  kamil   GET_REPORT_OPTIONS(false);
    447  1.1  kamil   handleLoadInvalidValue(Data, Val, Opts);
    448  1.1  kamil }
    449  1.1  kamil void __ubsan::__ubsan_handle_load_invalid_value_abort(InvalidValueData *Data,
    450  1.1  kamil                                                       ValueHandle Val) {
    451  1.1  kamil   GET_REPORT_OPTIONS(true);
    452  1.1  kamil   handleLoadInvalidValue(Data, Val, Opts);
    453  1.1  kamil   Die();
    454  1.1  kamil }
    455  1.1  kamil 
    456  1.1  kamil static void handleImplicitConversion(ImplicitConversionData *Data,
    457  1.1  kamil                                      ReportOptions Opts, ValueHandle Src,
    458  1.1  kamil                                      ValueHandle Dst) {
    459  1.1  kamil   SourceLocation Loc = Data->Loc.acquire();
    460  1.1  kamil   ErrorType ET = ErrorType::GenericUB;
    461  1.1  kamil 
    462  1.1  kamil   const TypeDescriptor &SrcTy = Data->FromType;
    463  1.1  kamil   const TypeDescriptor &DstTy = Data->ToType;
    464  1.1  kamil 
    465  1.1  kamil   bool SrcSigned = SrcTy.isSignedIntegerTy();
    466  1.1  kamil   bool DstSigned = DstTy.isSignedIntegerTy();
    467  1.1  kamil 
    468  1.1  kamil   switch (Data->Kind) {
    469  1.1  kamil   case ICCK_IntegerTruncation: { // Legacy, no longer used.
    470  1.1  kamil     // Let's figure out what it should be as per the new types, and upgrade.
    471  1.1  kamil     // If both types are unsigned, then it's an unsigned truncation.
    472  1.1  kamil     // Else, it is a signed truncation.
    473  1.1  kamil     if (!SrcSigned && !DstSigned) {
    474  1.1  kamil       ET = ErrorType::ImplicitUnsignedIntegerTruncation;
    475  1.1  kamil     } else {
    476  1.1  kamil       ET = ErrorType::ImplicitSignedIntegerTruncation;
    477  1.1  kamil     }
    478  1.1  kamil     break;
    479  1.1  kamil   }
    480  1.1  kamil   case ICCK_UnsignedIntegerTruncation:
    481  1.1  kamil     ET = ErrorType::ImplicitUnsignedIntegerTruncation;
    482  1.1  kamil     break;
    483  1.1  kamil   case ICCK_SignedIntegerTruncation:
    484  1.1  kamil     ET = ErrorType::ImplicitSignedIntegerTruncation;
    485  1.1  kamil     break;
    486  1.1  kamil   case ICCK_IntegerSignChange:
    487  1.1  kamil     ET = ErrorType::ImplicitIntegerSignChange;
    488  1.1  kamil     break;
    489  1.1  kamil   case ICCK_SignedIntegerTruncationOrSignChange:
    490  1.1  kamil     ET = ErrorType::ImplicitSignedIntegerTruncationOrSignChange;
    491  1.1  kamil     break;
    492  1.1  kamil   }
    493  1.1  kamil 
    494  1.1  kamil   if (ignoreReport(Loc, Opts, ET))
    495  1.1  kamil     return;
    496  1.1  kamil 
    497  1.1  kamil   ScopedReport R(Opts, Loc, ET);
    498  1.1  kamil 
    499  1.1  kamil   // FIXME: is it possible to dump the values as hex with fixed width?
    500  1.1  kamil 
    501  1.1  kamil   Diag(Loc, DL_Error, ET,
    502  1.1  kamil        "implicit conversion from type %0 of value %1 (%2-bit, %3signed) to "
    503  1.1  kamil        "type %4 changed the value to %5 (%6-bit, %7signed)")
    504  1.1  kamil       << SrcTy << Value(SrcTy, Src) << SrcTy.getIntegerBitWidth()
    505  1.1  kamil       << (SrcSigned ? "" : "un") << DstTy << Value(DstTy, Dst)
    506  1.1  kamil       << DstTy.getIntegerBitWidth() << (DstSigned ? "" : "un");
    507  1.1  kamil }
    508  1.1  kamil 
    509  1.1  kamil void __ubsan::__ubsan_handle_implicit_conversion(ImplicitConversionData *Data,
    510  1.1  kamil                                                  ValueHandle Src,
    511  1.1  kamil                                                  ValueHandle Dst) {
    512  1.1  kamil   GET_REPORT_OPTIONS(false);
    513  1.1  kamil   handleImplicitConversion(Data, Opts, Src, Dst);
    514  1.1  kamil }
    515  1.1  kamil void __ubsan::__ubsan_handle_implicit_conversion_abort(
    516  1.1  kamil     ImplicitConversionData *Data, ValueHandle Src, ValueHandle Dst) {
    517  1.1  kamil   GET_REPORT_OPTIONS(true);
    518  1.1  kamil   handleImplicitConversion(Data, Opts, Src, Dst);
    519  1.1  kamil   Die();
    520  1.1  kamil }
    521  1.1  kamil 
    522  1.1  kamil static void handleInvalidBuiltin(InvalidBuiltinData *Data, ReportOptions Opts) {
    523  1.1  kamil   SourceLocation Loc = Data->Loc.acquire();
    524  1.1  kamil   ErrorType ET = ErrorType::InvalidBuiltin;
    525  1.1  kamil 
    526  1.1  kamil   if (ignoreReport(Loc, Opts, ET))
    527  1.1  kamil     return;
    528  1.1  kamil 
    529  1.1  kamil   ScopedReport R(Opts, Loc, ET);
    530  1.1  kamil 
    531  1.1  kamil   Diag(Loc, DL_Error, ET,
    532  1.1  kamil        "passing zero to %0, which is not a valid argument")
    533  1.1  kamil     << ((Data->Kind == BCK_CTZPassedZero) ? "ctz()" : "clz()");
    534  1.1  kamil }
    535  1.1  kamil 
    536  1.1  kamil void __ubsan::__ubsan_handle_invalid_builtin(InvalidBuiltinData *Data) {
    537  1.1  kamil   GET_REPORT_OPTIONS(true);
    538  1.1  kamil   handleInvalidBuiltin(Data, Opts);
    539  1.1  kamil }
    540  1.1  kamil void __ubsan::__ubsan_handle_invalid_builtin_abort(InvalidBuiltinData *Data) {
    541  1.1  kamil   GET_REPORT_OPTIONS(true);
    542  1.1  kamil   handleInvalidBuiltin(Data, Opts);
    543  1.1  kamil   Die();
    544  1.1  kamil }
    545  1.1  kamil 
    546  1.1  kamil static void handleFunctionTypeMismatch(FunctionTypeMismatchData *Data,
    547  1.1  kamil                                        ValueHandle Function,
    548  1.1  kamil                                        ReportOptions Opts) {
    549  1.1  kamil   SourceLocation CallLoc = Data->Loc.acquire();
    550  1.1  kamil   ErrorType ET = ErrorType::FunctionTypeMismatch;
    551  1.1  kamil 
    552  1.1  kamil   if (ignoreReport(CallLoc, Opts, ET))
    553  1.1  kamil     return;
    554  1.1  kamil 
    555  1.1  kamil   ScopedReport R(Opts, CallLoc, ET);
    556  1.1  kamil 
    557  1.1  kamil   SymbolizedStackHolder FLoc(getSymbolizedLocation(Function));
    558  1.1  kamil   const char *FName = FLoc.get()->info.function;
    559  1.1  kamil   if (!FName)
    560  1.1  kamil     FName = "(unknown)";
    561  1.1  kamil 
    562  1.1  kamil   Diag(CallLoc, DL_Error, ET,
    563  1.1  kamil        "call to function %0 through pointer to incorrect function type %1")
    564  1.1  kamil       << FName << Data->Type;
    565  1.1  kamil   Diag(FLoc, DL_Note, ET, "%0 defined here") << FName;
    566  1.1  kamil }
    567  1.1  kamil 
    568  1.1  kamil void
    569  1.1  kamil __ubsan::__ubsan_handle_function_type_mismatch(FunctionTypeMismatchData *Data,
    570  1.1  kamil                                                ValueHandle Function) {
    571  1.1  kamil   GET_REPORT_OPTIONS(false);
    572  1.1  kamil   handleFunctionTypeMismatch(Data, Function, Opts);
    573  1.1  kamil }
    574  1.1  kamil 
    575  1.1  kamil void __ubsan::__ubsan_handle_function_type_mismatch_abort(
    576  1.1  kamil     FunctionTypeMismatchData *Data, ValueHandle Function) {
    577  1.1  kamil   GET_REPORT_OPTIONS(true);
    578  1.1  kamil   handleFunctionTypeMismatch(Data, Function, Opts);
    579  1.1  kamil   Die();
    580  1.1  kamil }
    581  1.1  kamil 
    582  1.1  kamil static void handleNonNullReturn(NonNullReturnData *Data, SourceLocation *LocPtr,
    583  1.1  kamil                                 ReportOptions Opts, bool IsAttr) {
    584  1.1  kamil   if (!LocPtr)
    585  1.1  kamil     UNREACHABLE("source location pointer is null!");
    586  1.1  kamil 
    587  1.1  kamil   SourceLocation Loc = LocPtr->acquire();
    588  1.1  kamil   ErrorType ET = ErrorType::InvalidNullReturn;
    589  1.1  kamil 
    590  1.1  kamil   if (ignoreReport(Loc, Opts, ET))
    591  1.1  kamil     return;
    592  1.1  kamil 
    593  1.1  kamil   ScopedReport R(Opts, Loc, ET);
    594  1.1  kamil 
    595  1.1  kamil   Diag(Loc, DL_Error, ET,
    596  1.1  kamil        "null pointer returned from function declared to never return null");
    597  1.1  kamil   if (!Data->AttrLoc.isInvalid())
    598  1.1  kamil     Diag(Data->AttrLoc, DL_Note, ET, "%0 specified here")
    599  1.1  kamil         << (IsAttr ? "returns_nonnull attribute"
    600  1.1  kamil                    : "_Nonnull return type annotation");
    601  1.1  kamil }
    602  1.1  kamil 
    603  1.1  kamil void __ubsan::__ubsan_handle_nonnull_return_v1(NonNullReturnData *Data,
    604  1.1  kamil                                                SourceLocation *LocPtr) {
    605  1.1  kamil   GET_REPORT_OPTIONS(false);
    606  1.1  kamil   handleNonNullReturn(Data, LocPtr, Opts, true);
    607  1.1  kamil }
    608  1.1  kamil 
    609  1.1  kamil void __ubsan::__ubsan_handle_nonnull_return_v1_abort(NonNullReturnData *Data,
    610  1.1  kamil                                                      SourceLocation *LocPtr) {
    611  1.1  kamil   GET_REPORT_OPTIONS(true);
    612  1.1  kamil   handleNonNullReturn(Data, LocPtr, Opts, true);
    613  1.1  kamil   Die();
    614  1.1  kamil }
    615  1.1  kamil 
    616  1.1  kamil void __ubsan::__ubsan_handle_nullability_return_v1(NonNullReturnData *Data,
    617  1.1  kamil                                                    SourceLocation *LocPtr) {
    618  1.1  kamil   GET_REPORT_OPTIONS(false);
    619  1.1  kamil   handleNonNullReturn(Data, LocPtr, Opts, false);
    620  1.1  kamil }
    621  1.1  kamil 
    622  1.1  kamil void __ubsan::__ubsan_handle_nullability_return_v1_abort(
    623  1.1  kamil     NonNullReturnData *Data, SourceLocation *LocPtr) {
    624  1.1  kamil   GET_REPORT_OPTIONS(true);
    625  1.1  kamil   handleNonNullReturn(Data, LocPtr, Opts, false);
    626  1.1  kamil   Die();
    627  1.1  kamil }
    628  1.1  kamil 
    629  1.1  kamil static void handleNonNullArg(NonNullArgData *Data, ReportOptions Opts,
    630  1.1  kamil                              bool IsAttr) {
    631  1.1  kamil   SourceLocation Loc = Data->Loc.acquire();
    632  1.1  kamil   ErrorType ET = ErrorType::InvalidNullArgument;
    633  1.1  kamil 
    634  1.1  kamil   if (ignoreReport(Loc, Opts, ET))
    635  1.1  kamil     return;
    636  1.1  kamil 
    637  1.1  kamil   ScopedReport R(Opts, Loc, ET);
    638  1.1  kamil 
    639  1.1  kamil   Diag(Loc, DL_Error, ET,
    640  1.1  kamil        "null pointer passed as argument %0, which is declared to "
    641  1.1  kamil        "never be null")
    642  1.1  kamil       << Data->ArgIndex;
    643  1.1  kamil   if (!Data->AttrLoc.isInvalid())
    644  1.1  kamil     Diag(Data->AttrLoc, DL_Note, ET, "%0 specified here")
    645  1.1  kamil         << (IsAttr ? "nonnull attribute" : "_Nonnull type annotation");
    646  1.1  kamil }
    647  1.1  kamil 
    648  1.1  kamil void __ubsan::__ubsan_handle_nonnull_arg(NonNullArgData *Data) {
    649  1.1  kamil   GET_REPORT_OPTIONS(false);
    650  1.1  kamil   handleNonNullArg(Data, Opts, true);
    651  1.1  kamil }
    652  1.1  kamil 
    653  1.1  kamil void __ubsan::__ubsan_handle_nonnull_arg_abort(NonNullArgData *Data) {
    654  1.1  kamil   GET_REPORT_OPTIONS(true);
    655  1.1  kamil   handleNonNullArg(Data, Opts, true);
    656  1.1  kamil   Die();
    657  1.1  kamil }
    658  1.1  kamil 
    659  1.1  kamil void __ubsan::__ubsan_handle_nullability_arg(NonNullArgData *Data) {
    660  1.1  kamil   GET_REPORT_OPTIONS(false);
    661  1.1  kamil   handleNonNullArg(Data, Opts, false);
    662  1.1  kamil }
    663  1.1  kamil 
    664  1.1  kamil void __ubsan::__ubsan_handle_nullability_arg_abort(NonNullArgData *Data) {
    665  1.1  kamil   GET_REPORT_OPTIONS(true);
    666  1.1  kamil   handleNonNullArg(Data, Opts, false);
    667  1.1  kamil   Die();
    668  1.1  kamil }
    669  1.1  kamil 
    670  1.1  kamil static void handlePointerOverflowImpl(PointerOverflowData *Data,
    671  1.1  kamil                                       ValueHandle Base,
    672  1.1  kamil                                       ValueHandle Result,
    673  1.1  kamil                                       ReportOptions Opts) {
    674  1.1  kamil   SourceLocation Loc = Data->Loc.acquire();
    675  1.1  kamil   ErrorType ET = ErrorType::PointerOverflow;
    676  1.1  kamil 
    677  1.1  kamil   if (ignoreReport(Loc, Opts, ET))
    678  1.1  kamil     return;
    679  1.1  kamil 
    680  1.1  kamil   ScopedReport R(Opts, Loc, ET);
    681  1.1  kamil 
    682  1.1  kamil   if ((sptr(Base) >= 0) == (sptr(Result) >= 0)) {
    683  1.1  kamil     if (Base > Result)
    684  1.1  kamil       Diag(Loc, DL_Error, ET,
    685  1.1  kamil            "addition of unsigned offset to %0 overflowed to %1")
    686  1.1  kamil           << (void *)Base << (void *)Result;
    687  1.1  kamil     else
    688  1.1  kamil       Diag(Loc, DL_Error, ET,
    689  1.1  kamil            "subtraction of unsigned offset from %0 overflowed to %1")
    690  1.1  kamil           << (void *)Base << (void *)Result;
    691  1.1  kamil   } else {
    692  1.1  kamil     Diag(Loc, DL_Error, ET,
    693  1.1  kamil          "pointer index expression with base %0 overflowed to %1")
    694  1.1  kamil         << (void *)Base << (void *)Result;
    695  1.1  kamil   }
    696  1.1  kamil }
    697  1.1  kamil 
    698  1.1  kamil void __ubsan::__ubsan_handle_pointer_overflow(PointerOverflowData *Data,
    699  1.1  kamil                                               ValueHandle Base,
    700  1.1  kamil                                               ValueHandle Result) {
    701  1.1  kamil   GET_REPORT_OPTIONS(false);
    702  1.1  kamil   handlePointerOverflowImpl(Data, Base, Result, Opts);
    703  1.1  kamil }
    704  1.1  kamil 
    705  1.1  kamil void __ubsan::__ubsan_handle_pointer_overflow_abort(PointerOverflowData *Data,
    706  1.1  kamil                                                     ValueHandle Base,
    707  1.1  kamil                                                     ValueHandle Result) {
    708  1.1  kamil   GET_REPORT_OPTIONS(true);
    709  1.1  kamil   handlePointerOverflowImpl(Data, Base, Result, Opts);
    710  1.1  kamil   Die();
    711  1.1  kamil }
    712  1.1  kamil 
    713  1.1  kamil static void handleCFIBadIcall(CFICheckFailData *Data, ValueHandle Function,
    714  1.1  kamil                               ReportOptions Opts) {
    715  1.1  kamil   if (Data->CheckKind != CFITCK_ICall && Data->CheckKind != CFITCK_NVMFCall)
    716  1.1  kamil     Die();
    717  1.1  kamil 
    718  1.1  kamil   SourceLocation Loc = Data->Loc.acquire();
    719  1.1  kamil   ErrorType ET = ErrorType::CFIBadType;
    720  1.1  kamil 
    721  1.1  kamil   if (ignoreReport(Loc, Opts, ET))
    722  1.1  kamil     return;
    723  1.1  kamil 
    724  1.1  kamil   ScopedReport R(Opts, Loc, ET);
    725  1.1  kamil 
    726  1.1  kamil   const char *CheckKindStr = Data->CheckKind == CFITCK_NVMFCall
    727  1.1  kamil                                  ? "non-virtual pointer to member function call"
    728  1.1  kamil                                  : "indirect function call";
    729  1.1  kamil   Diag(Loc, DL_Error, ET,
    730  1.1  kamil        "control flow integrity check for type %0 failed during %1")
    731  1.1  kamil       << Data->Type << CheckKindStr;
    732  1.1  kamil 
    733  1.1  kamil   SymbolizedStackHolder FLoc(getSymbolizedLocation(Function));
    734  1.1  kamil   const char *FName = FLoc.get()->info.function;
    735  1.1  kamil   if (!FName)
    736  1.1  kamil     FName = "(unknown)";
    737  1.1  kamil   Diag(FLoc, DL_Note, ET, "%0 defined here") << FName;
    738  1.1  kamil 
    739  1.1  kamil   // If the failure involved different DSOs for the check location and icall
    740  1.1  kamil   // target, report the DSO names.
    741  1.1  kamil   const char *DstModule = FLoc.get()->info.module;
    742  1.1  kamil   if (!DstModule)
    743  1.1  kamil     DstModule = "(unknown)";
    744  1.1  kamil 
    745  1.1  kamil   const char *SrcModule = Symbolizer::GetOrInit()->GetModuleNameForPc(Opts.pc);
    746  1.1  kamil   if (!SrcModule)
    747  1.1  kamil     SrcModule = "(unknown)";
    748  1.1  kamil 
    749  1.1  kamil   if (internal_strcmp(SrcModule, DstModule))
    750  1.1  kamil     Diag(Loc, DL_Note, ET,
    751  1.1  kamil          "check failed in %0, destination function located in %1")
    752  1.1  kamil         << SrcModule << DstModule;
    753  1.1  kamil }
    754  1.1  kamil 
    755  1.1  kamil namespace __ubsan {
    756  1.1  kamil 
    757  1.1  kamil #ifdef UBSAN_CAN_USE_CXXABI
    758  1.1  kamil 
    759  1.1  kamil #ifdef _WIN32
    760  1.1  kamil 
    761  1.1  kamil extern "C" void __ubsan_handle_cfi_bad_type_default(CFICheckFailData *Data,
    762  1.1  kamil                                                     ValueHandle Vtable,
    763  1.1  kamil                                                     bool ValidVtable,
    764  1.1  kamil                                                     ReportOptions Opts) {
    765  1.1  kamil   Die();
    766  1.1  kamil }
    767  1.1  kamil 
    768  1.1  kamil WIN_WEAK_ALIAS(__ubsan_handle_cfi_bad_type, __ubsan_handle_cfi_bad_type_default)
    769  1.1  kamil #else
    770  1.1  kamil SANITIZER_WEAK_ATTRIBUTE
    771  1.1  kamil #endif
    772  1.1  kamil void __ubsan_handle_cfi_bad_type(CFICheckFailData *Data, ValueHandle Vtable,
    773  1.1  kamil                                  bool ValidVtable, ReportOptions Opts);
    774  1.1  kamil 
    775  1.1  kamil #else
    776  1.1  kamil void __ubsan_handle_cfi_bad_type(CFICheckFailData *Data, ValueHandle Vtable,
    777  1.1  kamil                                  bool ValidVtable, ReportOptions Opts) {
    778  1.1  kamil   Die();
    779  1.1  kamil }
    780  1.1  kamil #endif
    781  1.1  kamil 
    782  1.1  kamil }  // namespace __ubsan
    783  1.1  kamil 
    784  1.1  kamil void __ubsan::__ubsan_handle_cfi_check_fail(CFICheckFailData *Data,
    785  1.1  kamil                                             ValueHandle Value,
    786  1.1  kamil                                             uptr ValidVtable) {
    787  1.1  kamil   GET_REPORT_OPTIONS(false);
    788  1.1  kamil   if (Data->CheckKind == CFITCK_ICall || Data->CheckKind == CFITCK_NVMFCall)
    789  1.1  kamil     handleCFIBadIcall(Data, Value, Opts);
    790  1.1  kamil   else
    791  1.1  kamil     __ubsan_handle_cfi_bad_type(Data, Value, ValidVtable, Opts);
    792  1.1  kamil }
    793  1.1  kamil 
    794  1.1  kamil void __ubsan::__ubsan_handle_cfi_check_fail_abort(CFICheckFailData *Data,
    795  1.1  kamil                                                   ValueHandle Value,
    796  1.1  kamil                                                   uptr ValidVtable) {
    797  1.1  kamil   GET_REPORT_OPTIONS(true);
    798  1.1  kamil   if (Data->CheckKind == CFITCK_ICall || Data->CheckKind == CFITCK_NVMFCall)
    799  1.1  kamil     handleCFIBadIcall(Data, Value, Opts);
    800  1.1  kamil   else
    801  1.1  kamil     __ubsan_handle_cfi_bad_type(Data, Value, ValidVtable, Opts);
    802  1.1  kamil   Die();
    803  1.1  kamil }
    804  1.1  kamil 
    805  1.1  kamil #endif  // CAN_SANITIZE_UB
    806