Home | History | Annotate | 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_handlers.h"
     15 #include "ubsan_diag.h"
     16 
     17 #include "sanitizer_common/sanitizer_common.h"
     18 
     19 using namespace __sanitizer;
     20 using namespace __ubsan;
     21 
     22 namespace __ubsan {
     23   const char *TypeCheckKinds[] = {
     24     "load of", "store to", "reference binding to", "member access within",
     25     "member call on", "constructor call on", "downcast of", "downcast of"
     26   };
     27 }
     28 
     29 static void handleTypeMismatchImpl(TypeMismatchData *Data, ValueHandle Pointer,
     30                                    Location FallbackLoc) {
     31   Location Loc = Data->Loc.acquire();
     32 
     33   // Use the SourceLocation from Data to track deduplication, even if 'invalid'
     34   if (Loc.getSourceLocation().isDisabled())
     35     return;
     36   if (Data->Loc.isInvalid())
     37     Loc = FallbackLoc;
     38 
     39   if (!Pointer)
     40     Diag(Loc, DL_Error, "%0 null pointer of type %1")
     41       << TypeCheckKinds[Data->TypeCheckKind] << Data->Type;
     42   else if (Data->Alignment && (Pointer & (Data->Alignment - 1)))
     43     Diag(Loc, DL_Error, "%0 misaligned address %1 for type %3, "
     44                         "which requires %2 byte alignment")
     45       << TypeCheckKinds[Data->TypeCheckKind] << (void*)Pointer
     46       << Data->Alignment << Data->Type;
     47   else
     48     Diag(Loc, DL_Error, "%0 address %1 with insufficient space "
     49                         "for an object of type %2")
     50       << TypeCheckKinds[Data->TypeCheckKind] << (void*)Pointer << Data->Type;
     51   if (Pointer)
     52     Diag(Pointer, DL_Note, "pointer points here");
     53 }
     54 void __ubsan::__ubsan_handle_type_mismatch(TypeMismatchData *Data,
     55                                            ValueHandle Pointer) {
     56   handleTypeMismatchImpl(Data, Pointer, getCallerLocation());
     57 }
     58 void __ubsan::__ubsan_handle_type_mismatch_abort(TypeMismatchData *Data,
     59                                                  ValueHandle Pointer) {
     60   handleTypeMismatchImpl(Data, Pointer, getCallerLocation());
     61   Die();
     62 }
     63 
     64 /// \brief Common diagnostic emission for various forms of integer overflow.
     65 template<typename T> static void HandleIntegerOverflow(OverflowData *Data,
     66                                                        ValueHandle LHS,
     67                                                        const char *Operator,
     68                                                        T RHS) {
     69   SourceLocation Loc = Data->Loc.acquire();
     70   if (Loc.isDisabled())
     71     return;
     72 
     73   Diag(Loc, DL_Error, "%0 integer overflow: "
     74                       "%1 %2 %3 cannot be represented in type %4")
     75     << (Data->Type.isSignedIntegerTy() ? "signed" : "unsigned")
     76     << Value(Data->Type, LHS) << Operator << RHS << Data->Type;
     77 }
     78 
     79 void __ubsan::__ubsan_handle_add_overflow(OverflowData *Data,
     80                                           ValueHandle LHS, ValueHandle RHS) {
     81   HandleIntegerOverflow(Data, LHS, "+", Value(Data->Type, RHS));
     82 }
     83 void __ubsan::__ubsan_handle_add_overflow_abort(OverflowData *Data,
     84                                                  ValueHandle LHS,
     85                                                  ValueHandle RHS) {
     86   __ubsan_handle_add_overflow(Data, LHS, RHS);
     87   Die();
     88 }
     89 
     90 void __ubsan::__ubsan_handle_sub_overflow(OverflowData *Data,
     91                                           ValueHandle LHS, ValueHandle RHS) {
     92   HandleIntegerOverflow(Data, LHS, "-", Value(Data->Type, RHS));
     93 }
     94 void __ubsan::__ubsan_handle_sub_overflow_abort(OverflowData *Data,
     95                                                  ValueHandle LHS,
     96                                                  ValueHandle RHS) {
     97   __ubsan_handle_sub_overflow(Data, LHS, RHS);
     98   Die();
     99 }
    100 
    101 void __ubsan::__ubsan_handle_mul_overflow(OverflowData *Data,
    102                                           ValueHandle LHS, ValueHandle RHS) {
    103   HandleIntegerOverflow(Data, LHS, "*", Value(Data->Type, RHS));
    104 }
    105 void __ubsan::__ubsan_handle_mul_overflow_abort(OverflowData *Data,
    106                                                  ValueHandle LHS,
    107                                                  ValueHandle RHS) {
    108   __ubsan_handle_mul_overflow(Data, LHS, RHS);
    109   Die();
    110 }
    111 
    112 void __ubsan::__ubsan_handle_negate_overflow(OverflowData *Data,
    113                                              ValueHandle OldVal) {
    114   SourceLocation Loc = Data->Loc.acquire();
    115   if (Loc.isDisabled())
    116     return;
    117 
    118   if (Data->Type.isSignedIntegerTy())
    119     Diag(Loc, DL_Error,
    120          "negation of %0 cannot be represented in type %1; "
    121          "cast to an unsigned type to negate this value to itself")
    122       << Value(Data->Type, OldVal) << Data->Type;
    123   else
    124     Diag(Loc, DL_Error,
    125          "negation of %0 cannot be represented in type %1")
    126       << Value(Data->Type, OldVal) << Data->Type;
    127 }
    128 void __ubsan::__ubsan_handle_negate_overflow_abort(OverflowData *Data,
    129                                                     ValueHandle OldVal) {
    130   __ubsan_handle_negate_overflow(Data, OldVal);
    131   Die();
    132 }
    133 
    134 void __ubsan::__ubsan_handle_divrem_overflow(OverflowData *Data,
    135                                              ValueHandle LHS, ValueHandle RHS) {
    136   SourceLocation Loc = Data->Loc.acquire();
    137   if (Loc.isDisabled())
    138     return;
    139 
    140   Value LHSVal(Data->Type, LHS);
    141   Value RHSVal(Data->Type, RHS);
    142   if (RHSVal.isMinusOne())
    143     Diag(Loc, DL_Error,
    144          "division of %0 by -1 cannot be represented in type %1")
    145       << LHSVal << Data->Type;
    146   else
    147     Diag(Loc, DL_Error, "division by zero");
    148 }
    149 void __ubsan::__ubsan_handle_divrem_overflow_abort(OverflowData *Data,
    150                                                     ValueHandle LHS,
    151                                                     ValueHandle RHS) {
    152   __ubsan_handle_divrem_overflow(Data, LHS, RHS);
    153   Die();
    154 }
    155 
    156 void __ubsan::__ubsan_handle_shift_out_of_bounds(ShiftOutOfBoundsData *Data,
    157                                                  ValueHandle LHS,
    158                                                  ValueHandle RHS) {
    159   SourceLocation Loc = Data->Loc.acquire();
    160   if (Loc.isDisabled())
    161     return;
    162 
    163   Value LHSVal(Data->LHSType, LHS);
    164   Value RHSVal(Data->RHSType, RHS);
    165   if (RHSVal.isNegative())
    166     Diag(Loc, DL_Error, "shift exponent %0 is negative") << RHSVal;
    167   else if (RHSVal.getPositiveIntValue() >= Data->LHSType.getIntegerBitWidth())
    168     Diag(Loc, DL_Error,
    169          "shift exponent %0 is too large for %1-bit type %2")
    170       << RHSVal << Data->LHSType.getIntegerBitWidth() << Data->LHSType;
    171   else if (LHSVal.isNegative())
    172     Diag(Loc, DL_Error, "left shift of negative value %0") << LHSVal;
    173   else
    174     Diag(Loc, DL_Error,
    175          "left shift of %0 by %1 places cannot be represented in type %2")
    176       << LHSVal << RHSVal << Data->LHSType;
    177 }
    178 void __ubsan::__ubsan_handle_shift_out_of_bounds_abort(
    179                                                      ShiftOutOfBoundsData *Data,
    180                                                      ValueHandle LHS,
    181                                                      ValueHandle RHS) {
    182   __ubsan_handle_shift_out_of_bounds(Data, LHS, RHS);
    183   Die();
    184 }
    185 
    186 void __ubsan::__ubsan_handle_out_of_bounds(OutOfBoundsData *Data,
    187                                            ValueHandle Index) {
    188   SourceLocation Loc = Data->Loc.acquire();
    189   if (Loc.isDisabled())
    190     return;
    191 
    192   Value IndexVal(Data->IndexType, Index);
    193   Diag(Loc, DL_Error, "index %0 out of bounds for type %1")
    194     << IndexVal << Data->ArrayType;
    195 }
    196 void __ubsan::__ubsan_handle_out_of_bounds_abort(OutOfBoundsData *Data,
    197                                                  ValueHandle Index) {
    198   __ubsan_handle_out_of_bounds(Data, Index);
    199   Die();
    200 }
    201 
    202 void __ubsan::__ubsan_handle_builtin_unreachable(UnreachableData *Data) {
    203   Diag(Data->Loc, DL_Error, "execution reached a __builtin_unreachable() call");
    204   Die();
    205 }
    206 
    207 void __ubsan::__ubsan_handle_missing_return(UnreachableData *Data) {
    208   Diag(Data->Loc, DL_Error,
    209        "execution reached the end of a value-returning function "
    210        "without returning a value");
    211   Die();
    212 }
    213 
    214 void __ubsan::__ubsan_handle_vla_bound_not_positive(VLABoundData *Data,
    215                                                     ValueHandle Bound) {
    216   SourceLocation Loc = Data->Loc.acquire();
    217   if (Loc.isDisabled())
    218     return;
    219 
    220   Diag(Loc, DL_Error, "variable length array bound evaluates to "
    221                       "non-positive value %0")
    222     << Value(Data->Type, Bound);
    223 }
    224 void __ubsan::__ubsan_handle_vla_bound_not_positive_abort(VLABoundData *Data,
    225                                                            ValueHandle Bound) {
    226   __ubsan_handle_vla_bound_not_positive(Data, Bound);
    227   Die();
    228 }
    229 
    230 
    231 void __ubsan::__ubsan_handle_float_cast_overflow(FloatCastOverflowData *Data,
    232                                                  ValueHandle From) {
    233   // TODO: Add deduplication once a SourceLocation is generated for this check.
    234   Diag(getCallerLocation(), DL_Error,
    235        "value %0 is outside the range of representable values of type %2")
    236     << Value(Data->FromType, From) << Data->FromType << Data->ToType;
    237 }
    238 void __ubsan::__ubsan_handle_float_cast_overflow_abort(
    239                                                     FloatCastOverflowData *Data,
    240                                                     ValueHandle From) {
    241   Diag(getCallerLocation(), DL_Error,
    242        "value %0 is outside the range of representable values of type %2")
    243     << Value(Data->FromType, From) << Data->FromType << Data->ToType;
    244   Die();
    245 }
    246 
    247 void __ubsan::__ubsan_handle_load_invalid_value(InvalidValueData *Data,
    248                                                 ValueHandle Val) {
    249   SourceLocation Loc = Data->Loc.acquire();
    250   if (Loc.isDisabled())
    251     return;
    252 
    253   Diag(Loc, DL_Error,
    254        "load of value %0, which is not a valid value for type %1")
    255     << Value(Data->Type, Val) << Data->Type;
    256 }
    257 void __ubsan::__ubsan_handle_load_invalid_value_abort(InvalidValueData *Data,
    258                                                       ValueHandle Val) {
    259   __ubsan_handle_load_invalid_value(Data, Val);
    260   Die();
    261 }
    262 
    263 void __ubsan::__ubsan_handle_function_type_mismatch(
    264     FunctionTypeMismatchData *Data,
    265     ValueHandle Function) {
    266   const char *FName = "(unknown)";
    267 
    268   Location Loc = getFunctionLocation(Function, &FName);
    269 
    270   Diag(Data->Loc, DL_Error,
    271        "call to function %0 through pointer to incorrect function type %1")
    272     << FName << Data->Type;
    273   Diag(Loc, DL_Note, "%0 defined here") << FName;
    274 }
    275 
    276 void __ubsan::__ubsan_handle_function_type_mismatch_abort(
    277     FunctionTypeMismatchData *Data,
    278     ValueHandle Function) {
    279   __ubsan_handle_function_type_mismatch(Data, Function);
    280   Die();
    281 }
    282