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