ubsan_handlers.cc revision 296417
1245614Sandrew//===-- ubsan_handlers.cc -------------------------------------------------===// 2245614Sandrew// 3245614Sandrew// The LLVM Compiler Infrastructure 4245614Sandrew// 5245614Sandrew// This file is distributed under the University of Illinois Open Source 6245614Sandrew// License. See LICENSE.TXT for details. 7245614Sandrew// 8245614Sandrew//===----------------------------------------------------------------------===// 9245614Sandrew// 10245614Sandrew// Error logging entry points for the UBSan runtime. 11245614Sandrew// 12245614Sandrew//===----------------------------------------------------------------------===// 13245614Sandrew 14288943Sdim#include "ubsan_platform.h" 15288943Sdim#if CAN_SANITIZE_UB 16245614Sandrew#include "ubsan_handlers.h" 17245614Sandrew#include "ubsan_diag.h" 18245614Sandrew 19245614Sandrew#include "sanitizer_common/sanitizer_common.h" 20245614Sandrew 21245614Sandrewusing namespace __sanitizer; 22245614Sandrewusing namespace __ubsan; 23245614Sandrew 24296417Sdimnamespace __ubsan { 25296417Sdimbool ignoreReport(SourceLocation SLoc, ReportOptions Opts, ErrorType ET) { 26296417Sdim // We are not allowed to skip error report: if we are in unrecoverable 27296417Sdim // handler, we have to terminate the program right now, and therefore 28296417Sdim // have to print some diagnostic. 29296417Sdim // 30296417Sdim // Even if source location is disabled, it doesn't mean that we have 31296417Sdim // already report an error to the user: some concurrently running 32296417Sdim // thread could have acquired it, but not yet printed the report. 33296417Sdim if (Opts.FromUnrecoverableHandler) 34296417Sdim return false; 35296417Sdim return SLoc.isDisabled() || IsPCSuppressed(ET, Opts.pc, SLoc.getFilename()); 36276789Sdim} 37276789Sdim 38276789Sdimconst char *TypeCheckKinds[] = { 39245614Sandrew "load of", "store to", "reference binding to", "member access within", 40276789Sdim "member call on", "constructor call on", "downcast of", "downcast of", 41276789Sdim "upcast of", "cast to virtual base of"}; 42245614Sandrew} 43245614Sandrew 44245614Sandrewstatic void handleTypeMismatchImpl(TypeMismatchData *Data, ValueHandle Pointer, 45280031Sdim ReportOptions Opts) { 46245614Sandrew Location Loc = Data->Loc.acquire(); 47296417Sdim 48296417Sdim ErrorType ET; 49296417Sdim if (!Pointer) 50296417Sdim ET = ErrorType::NullPointerUse; 51296417Sdim else if (Data->Alignment && (Pointer & (Data->Alignment - 1))) 52296417Sdim ET = ErrorType::MisalignedPointerUse; 53296417Sdim else 54296417Sdim ET = ErrorType::InsufficientObjectSize; 55296417Sdim 56296417Sdim // Use the SourceLocation from Data to track deduplication, even if it's 57296417Sdim // invalid. 58296417Sdim if (ignoreReport(Loc.getSourceLocation(), Opts, ET)) 59245614Sandrew return; 60276789Sdim 61280031Sdim SymbolizedStackHolder FallbackLoc; 62280031Sdim if (Data->Loc.isInvalid()) { 63280031Sdim FallbackLoc.reset(getCallerLocation(Opts.pc)); 64245614Sandrew Loc = FallbackLoc; 65280031Sdim } 66245614Sandrew 67296417Sdim ScopedReport R(Opts, Loc, ET); 68276789Sdim 69296417Sdim switch (ET) { 70296417Sdim case ErrorType::NullPointerUse: 71245614Sandrew Diag(Loc, DL_Error, "%0 null pointer of type %1") 72296417Sdim << TypeCheckKinds[Data->TypeCheckKind] << Data->Type; 73296417Sdim break; 74296417Sdim case ErrorType::MisalignedPointerUse: 75245614Sandrew Diag(Loc, DL_Error, "%0 misaligned address %1 for type %3, " 76245614Sandrew "which requires %2 byte alignment") 77296417Sdim << TypeCheckKinds[Data->TypeCheckKind] << (void *)Pointer 78296417Sdim << Data->Alignment << Data->Type; 79296417Sdim break; 80296417Sdim case ErrorType::InsufficientObjectSize: 81245614Sandrew Diag(Loc, DL_Error, "%0 address %1 with insufficient space " 82245614Sandrew "for an object of type %2") 83296417Sdim << TypeCheckKinds[Data->TypeCheckKind] << (void *)Pointer << Data->Type; 84296417Sdim break; 85296417Sdim default: 86296417Sdim UNREACHABLE("unexpected error type!"); 87296417Sdim } 88296417Sdim 89245614Sandrew if (Pointer) 90245614Sandrew Diag(Pointer, DL_Note, "pointer points here"); 91245614Sandrew} 92276789Sdim 93245614Sandrewvoid __ubsan::__ubsan_handle_type_mismatch(TypeMismatchData *Data, 94245614Sandrew ValueHandle Pointer) { 95276789Sdim GET_REPORT_OPTIONS(false); 96280031Sdim handleTypeMismatchImpl(Data, Pointer, Opts); 97245614Sandrew} 98245614Sandrewvoid __ubsan::__ubsan_handle_type_mismatch_abort(TypeMismatchData *Data, 99245614Sandrew ValueHandle Pointer) { 100276789Sdim GET_REPORT_OPTIONS(true); 101280031Sdim handleTypeMismatchImpl(Data, Pointer, Opts); 102245614Sandrew Die(); 103245614Sandrew} 104245614Sandrew 105245614Sandrew/// \brief Common diagnostic emission for various forms of integer overflow. 106276789Sdimtemplate <typename T> 107276789Sdimstatic void handleIntegerOverflowImpl(OverflowData *Data, ValueHandle LHS, 108276789Sdim const char *Operator, T RHS, 109276789Sdim ReportOptions Opts) { 110245614Sandrew SourceLocation Loc = Data->Loc.acquire(); 111296417Sdim bool IsSigned = Data->Type.isSignedIntegerTy(); 112296417Sdim ErrorType ET = IsSigned ? ErrorType::SignedIntegerOverflow 113296417Sdim : ErrorType::UnsignedIntegerOverflow; 114296417Sdim 115296417Sdim if (ignoreReport(Loc, Opts, ET)) 116245614Sandrew return; 117245614Sandrew 118296417Sdim ScopedReport R(Opts, Loc, ET); 119276789Sdim 120245614Sandrew Diag(Loc, DL_Error, "%0 integer overflow: " 121245614Sandrew "%1 %2 %3 cannot be represented in type %4") 122296417Sdim << (IsSigned ? "signed" : "unsigned") 123245614Sandrew << Value(Data->Type, LHS) << Operator << RHS << Data->Type; 124245614Sandrew} 125245614Sandrew 126296417Sdim#define UBSAN_OVERFLOW_HANDLER(handler_name, op, unrecoverable) \ 127276789Sdim void __ubsan::handler_name(OverflowData *Data, ValueHandle LHS, \ 128276789Sdim ValueHandle RHS) { \ 129296417Sdim GET_REPORT_OPTIONS(unrecoverable); \ 130276789Sdim handleIntegerOverflowImpl(Data, LHS, op, Value(Data->Type, RHS), Opts); \ 131296417Sdim if (unrecoverable) \ 132296417Sdim Die(); \ 133276789Sdim } 134245614Sandrew 135276789SdimUBSAN_OVERFLOW_HANDLER(__ubsan_handle_add_overflow, "+", false) 136276789SdimUBSAN_OVERFLOW_HANDLER(__ubsan_handle_add_overflow_abort, "+", true) 137276789SdimUBSAN_OVERFLOW_HANDLER(__ubsan_handle_sub_overflow, "-", false) 138276789SdimUBSAN_OVERFLOW_HANDLER(__ubsan_handle_sub_overflow_abort, "-", true) 139276789SdimUBSAN_OVERFLOW_HANDLER(__ubsan_handle_mul_overflow, "*", false) 140276789SdimUBSAN_OVERFLOW_HANDLER(__ubsan_handle_mul_overflow_abort, "*", true) 141245614Sandrew 142276789Sdimstatic void handleNegateOverflowImpl(OverflowData *Data, ValueHandle OldVal, 143276789Sdim ReportOptions Opts) { 144245614Sandrew SourceLocation Loc = Data->Loc.acquire(); 145296417Sdim bool IsSigned = Data->Type.isSignedIntegerTy(); 146296417Sdim ErrorType ET = IsSigned ? ErrorType::SignedIntegerOverflow 147296417Sdim : ErrorType::UnsignedIntegerOverflow; 148296417Sdim 149296417Sdim if (ignoreReport(Loc, Opts, ET)) 150245614Sandrew return; 151245614Sandrew 152296417Sdim ScopedReport R(Opts, Loc, ET); 153276789Sdim 154296417Sdim if (IsSigned) 155245614Sandrew Diag(Loc, DL_Error, 156245614Sandrew "negation of %0 cannot be represented in type %1; " 157245614Sandrew "cast to an unsigned type to negate this value to itself") 158296417Sdim << Value(Data->Type, OldVal) << Data->Type; 159245614Sandrew else 160296417Sdim Diag(Loc, DL_Error, "negation of %0 cannot be represented in type %1") 161296417Sdim << Value(Data->Type, OldVal) << Data->Type; 162245614Sandrew} 163276789Sdim 164276789Sdimvoid __ubsan::__ubsan_handle_negate_overflow(OverflowData *Data, 165276789Sdim ValueHandle OldVal) { 166276789Sdim GET_REPORT_OPTIONS(false); 167276789Sdim handleNegateOverflowImpl(Data, OldVal, Opts); 168276789Sdim} 169245614Sandrewvoid __ubsan::__ubsan_handle_negate_overflow_abort(OverflowData *Data, 170245614Sandrew ValueHandle OldVal) { 171276789Sdim GET_REPORT_OPTIONS(true); 172276789Sdim handleNegateOverflowImpl(Data, OldVal, Opts); 173245614Sandrew Die(); 174245614Sandrew} 175245614Sandrew 176276789Sdimstatic void handleDivremOverflowImpl(OverflowData *Data, ValueHandle LHS, 177276789Sdim ValueHandle RHS, ReportOptions Opts) { 178245614Sandrew SourceLocation Loc = Data->Loc.acquire(); 179245614Sandrew Value LHSVal(Data->Type, LHS); 180245614Sandrew Value RHSVal(Data->Type, RHS); 181296417Sdim 182296417Sdim ErrorType ET; 183245614Sandrew if (RHSVal.isMinusOne()) 184296417Sdim ET = ErrorType::SignedIntegerOverflow; 185296417Sdim else if (Data->Type.isIntegerTy()) 186296417Sdim ET = ErrorType::IntegerDivideByZero; 187245614Sandrew else 188296417Sdim ET = ErrorType::FloatDivideByZero; 189296417Sdim 190296417Sdim if (ignoreReport(Loc, Opts, ET)) 191296417Sdim return; 192296417Sdim 193296417Sdim ScopedReport R(Opts, Loc, ET); 194296417Sdim 195296417Sdim switch (ET) { 196296417Sdim case ErrorType::SignedIntegerOverflow: 197296417Sdim Diag(Loc, DL_Error, "division of %0 by -1 cannot be represented in type %1") 198296417Sdim << LHSVal << Data->Type; 199296417Sdim break; 200296417Sdim default: 201245614Sandrew Diag(Loc, DL_Error, "division by zero"); 202296417Sdim break; 203296417Sdim } 204245614Sandrew} 205276789Sdim 206276789Sdimvoid __ubsan::__ubsan_handle_divrem_overflow(OverflowData *Data, 207276789Sdim ValueHandle LHS, ValueHandle RHS) { 208276789Sdim GET_REPORT_OPTIONS(false); 209276789Sdim handleDivremOverflowImpl(Data, LHS, RHS, Opts); 210276789Sdim} 211245614Sandrewvoid __ubsan::__ubsan_handle_divrem_overflow_abort(OverflowData *Data, 212245614Sandrew ValueHandle LHS, 213245614Sandrew ValueHandle RHS) { 214276789Sdim GET_REPORT_OPTIONS(true); 215276789Sdim handleDivremOverflowImpl(Data, LHS, RHS, Opts); 216245614Sandrew Die(); 217245614Sandrew} 218245614Sandrew 219276789Sdimstatic void handleShiftOutOfBoundsImpl(ShiftOutOfBoundsData *Data, 220276789Sdim ValueHandle LHS, ValueHandle RHS, 221276789Sdim ReportOptions Opts) { 222245614Sandrew SourceLocation Loc = Data->Loc.acquire(); 223296417Sdim Value LHSVal(Data->LHSType, LHS); 224296417Sdim Value RHSVal(Data->RHSType, RHS); 225296417Sdim 226296417Sdim ErrorType ET; 227296417Sdim if (RHSVal.isNegative() || 228296417Sdim RHSVal.getPositiveIntValue() >= Data->LHSType.getIntegerBitWidth()) 229296417Sdim ET = ErrorType::InvalidShiftExponent; 230296417Sdim else 231296417Sdim ET = ErrorType::InvalidShiftBase; 232296417Sdim 233296417Sdim if (ignoreReport(Loc, Opts, ET)) 234245614Sandrew return; 235245614Sandrew 236296417Sdim ScopedReport R(Opts, Loc, ET); 237276789Sdim 238296417Sdim if (ET == ErrorType::InvalidShiftExponent) { 239296417Sdim if (RHSVal.isNegative()) 240296417Sdim Diag(Loc, DL_Error, "shift exponent %0 is negative") << RHSVal; 241296417Sdim else 242296417Sdim Diag(Loc, DL_Error, "shift exponent %0 is too large for %1-bit type %2") 243296417Sdim << RHSVal << Data->LHSType.getIntegerBitWidth() << Data->LHSType; 244296417Sdim } else { 245296417Sdim if (LHSVal.isNegative()) 246296417Sdim Diag(Loc, DL_Error, "left shift of negative value %0") << LHSVal; 247296417Sdim else 248296417Sdim Diag(Loc, DL_Error, 249296417Sdim "left shift of %0 by %1 places cannot be represented in type %2") 250296417Sdim << LHSVal << RHSVal << Data->LHSType; 251296417Sdim } 252245614Sandrew} 253276789Sdim 254276789Sdimvoid __ubsan::__ubsan_handle_shift_out_of_bounds(ShiftOutOfBoundsData *Data, 255276789Sdim ValueHandle LHS, 256276789Sdim ValueHandle RHS) { 257276789Sdim GET_REPORT_OPTIONS(false); 258276789Sdim handleShiftOutOfBoundsImpl(Data, LHS, RHS, Opts); 259276789Sdim} 260245614Sandrewvoid __ubsan::__ubsan_handle_shift_out_of_bounds_abort( 261245614Sandrew ShiftOutOfBoundsData *Data, 262245614Sandrew ValueHandle LHS, 263245614Sandrew ValueHandle RHS) { 264276789Sdim GET_REPORT_OPTIONS(true); 265276789Sdim handleShiftOutOfBoundsImpl(Data, LHS, RHS, Opts); 266245614Sandrew Die(); 267245614Sandrew} 268245614Sandrew 269276789Sdimstatic void handleOutOfBoundsImpl(OutOfBoundsData *Data, ValueHandle Index, 270276789Sdim ReportOptions Opts) { 271251034Sed SourceLocation Loc = Data->Loc.acquire(); 272296417Sdim ErrorType ET = ErrorType::OutOfBoundsIndex; 273296417Sdim 274296417Sdim if (ignoreReport(Loc, Opts, ET)) 275251034Sed return; 276251034Sed 277296417Sdim ScopedReport R(Opts, Loc, ET); 278276789Sdim 279251034Sed Value IndexVal(Data->IndexType, Index); 280251034Sed Diag(Loc, DL_Error, "index %0 out of bounds for type %1") 281251034Sed << IndexVal << Data->ArrayType; 282251034Sed} 283276789Sdim 284276789Sdimvoid __ubsan::__ubsan_handle_out_of_bounds(OutOfBoundsData *Data, 285276789Sdim ValueHandle Index) { 286276789Sdim GET_REPORT_OPTIONS(false); 287276789Sdim handleOutOfBoundsImpl(Data, Index, Opts); 288276789Sdim} 289251034Sedvoid __ubsan::__ubsan_handle_out_of_bounds_abort(OutOfBoundsData *Data, 290251034Sed ValueHandle Index) { 291276789Sdim GET_REPORT_OPTIONS(true); 292276789Sdim handleOutOfBoundsImpl(Data, Index, Opts); 293251034Sed Die(); 294251034Sed} 295251034Sed 296276789Sdimstatic void handleBuiltinUnreachableImpl(UnreachableData *Data, 297276789Sdim ReportOptions Opts) { 298296417Sdim ScopedReport R(Opts, Data->Loc, ErrorType::UnreachableCall); 299276789Sdim Diag(Data->Loc, DL_Error, "execution reached a __builtin_unreachable() call"); 300276789Sdim} 301276789Sdim 302245614Sandrewvoid __ubsan::__ubsan_handle_builtin_unreachable(UnreachableData *Data) { 303276789Sdim GET_REPORT_OPTIONS(true); 304276789Sdim handleBuiltinUnreachableImpl(Data, Opts); 305245614Sandrew Die(); 306245614Sandrew} 307245614Sandrew 308276789Sdimstatic void handleMissingReturnImpl(UnreachableData *Data, ReportOptions Opts) { 309296417Sdim ScopedReport R(Opts, Data->Loc, ErrorType::MissingReturn); 310245614Sandrew Diag(Data->Loc, DL_Error, 311245614Sandrew "execution reached the end of a value-returning function " 312245614Sandrew "without returning a value"); 313276789Sdim} 314276789Sdim 315276789Sdimvoid __ubsan::__ubsan_handle_missing_return(UnreachableData *Data) { 316276789Sdim GET_REPORT_OPTIONS(true); 317276789Sdim handleMissingReturnImpl(Data, Opts); 318245614Sandrew Die(); 319245614Sandrew} 320245614Sandrew 321276789Sdimstatic void handleVLABoundNotPositive(VLABoundData *Data, ValueHandle Bound, 322276789Sdim ReportOptions Opts) { 323245614Sandrew SourceLocation Loc = Data->Loc.acquire(); 324296417Sdim ErrorType ET = ErrorType::NonPositiveVLAIndex; 325296417Sdim 326296417Sdim if (ignoreReport(Loc, Opts, ET)) 327245614Sandrew return; 328245614Sandrew 329296417Sdim ScopedReport R(Opts, Loc, ET); 330276789Sdim 331245614Sandrew Diag(Loc, DL_Error, "variable length array bound evaluates to " 332245614Sandrew "non-positive value %0") 333245614Sandrew << Value(Data->Type, Bound); 334245614Sandrew} 335276789Sdim 336276789Sdimvoid __ubsan::__ubsan_handle_vla_bound_not_positive(VLABoundData *Data, 337276789Sdim ValueHandle Bound) { 338276789Sdim GET_REPORT_OPTIONS(false); 339276789Sdim handleVLABoundNotPositive(Data, Bound, Opts); 340276789Sdim} 341245614Sandrewvoid __ubsan::__ubsan_handle_vla_bound_not_positive_abort(VLABoundData *Data, 342276789Sdim ValueHandle Bound) { 343276789Sdim GET_REPORT_OPTIONS(true); 344276789Sdim handleVLABoundNotPositive(Data, Bound, Opts); 345245614Sandrew Die(); 346245614Sandrew} 347245614Sandrew 348296417Sdimstatic bool looksLikeFloatCastOverflowDataV1(void *Data) { 349296417Sdim // First field is either a pointer to filename or a pointer to a 350296417Sdim // TypeDescriptor. 351296417Sdim u8 *FilenameOrTypeDescriptor; 352296417Sdim internal_memcpy(&FilenameOrTypeDescriptor, Data, 353296417Sdim sizeof(FilenameOrTypeDescriptor)); 354245614Sandrew 355296417Sdim // Heuristic: For float_cast_overflow, the TypeKind will be either TK_Integer 356296417Sdim // (0x0), TK_Float (0x1) or TK_Unknown (0xff). If both types are known, 357296417Sdim // adding both bytes will be 0 or 1 (for BE or LE). If it were a filename, 358296417Sdim // adding two printable characters will not yield such a value. Otherwise, 359296417Sdim // if one of them is 0xff, this is most likely TK_Unknown type descriptor. 360296417Sdim u16 MaybeFromTypeKind = 361296417Sdim FilenameOrTypeDescriptor[0] + FilenameOrTypeDescriptor[1]; 362296417Sdim return MaybeFromTypeKind < 2 || FilenameOrTypeDescriptor[0] == 0xff || 363296417Sdim FilenameOrTypeDescriptor[1] == 0xff; 364296417Sdim} 365296417Sdim 366296417Sdimstatic void handleFloatCastOverflow(void *DataPtr, ValueHandle From, 367296417Sdim ReportOptions Opts) { 368296417Sdim SymbolizedStackHolder CallerLoc; 369296417Sdim Location Loc; 370296417Sdim const TypeDescriptor *FromType, *ToType; 371296417Sdim ErrorType ET = ErrorType::FloatCastOverflow; 372296417Sdim 373296417Sdim if (looksLikeFloatCastOverflowDataV1(DataPtr)) { 374296417Sdim auto Data = reinterpret_cast<FloatCastOverflowData *>(DataPtr); 375296417Sdim CallerLoc.reset(getCallerLocation(Opts.pc)); 376296417Sdim Loc = CallerLoc; 377296417Sdim FromType = &Data->FromType; 378296417Sdim ToType = &Data->ToType; 379296417Sdim } else { 380296417Sdim auto Data = reinterpret_cast<FloatCastOverflowDataV2 *>(DataPtr); 381296417Sdim SourceLocation SLoc = Data->Loc.acquire(); 382296417Sdim if (ignoreReport(SLoc, Opts, ET)) 383296417Sdim return; 384296417Sdim Loc = SLoc; 385296417Sdim FromType = &Data->FromType; 386296417Sdim ToType = &Data->ToType; 387296417Sdim } 388296417Sdim 389296417Sdim ScopedReport R(Opts, Loc, ET); 390296417Sdim 391276789Sdim Diag(Loc, DL_Error, 392276789Sdim "value %0 is outside the range of representable values of type %2") 393296417Sdim << Value(*FromType, From) << *FromType << *ToType; 394276789Sdim} 395276789Sdim 396296417Sdimvoid __ubsan::__ubsan_handle_float_cast_overflow(void *Data, ValueHandle From) { 397276789Sdim GET_REPORT_OPTIONS(false); 398276789Sdim handleFloatCastOverflow(Data, From, Opts); 399245614Sandrew} 400296417Sdimvoid __ubsan::__ubsan_handle_float_cast_overflow_abort(void *Data, 401296417Sdim ValueHandle From) { 402276789Sdim GET_REPORT_OPTIONS(true); 403276789Sdim handleFloatCastOverflow(Data, From, Opts); 404245614Sandrew Die(); 405245614Sandrew} 406245614Sandrew 407276789Sdimstatic void handleLoadInvalidValue(InvalidValueData *Data, ValueHandle Val, 408276789Sdim ReportOptions Opts) { 409274201Sdim SourceLocation Loc = Data->Loc.acquire(); 410296417Sdim // This check could be more precise if we used different handlers for 411296417Sdim // -fsanitize=bool and -fsanitize=enum. 412296417Sdim bool IsBool = (0 == internal_strcmp(Data->Type.getTypeName(), "'bool'")); 413296417Sdim ErrorType ET = 414296417Sdim IsBool ? ErrorType::InvalidBoolLoad : ErrorType::InvalidEnumLoad; 415296417Sdim 416296417Sdim if (ignoreReport(Loc, Opts, ET)) 417274201Sdim return; 418274201Sdim 419296417Sdim ScopedReport R(Opts, Loc, ET); 420276789Sdim 421274201Sdim Diag(Loc, DL_Error, 422245614Sandrew "load of value %0, which is not a valid value for type %1") 423245614Sandrew << Value(Data->Type, Val) << Data->Type; 424245614Sandrew} 425276789Sdim 426276789Sdimvoid __ubsan::__ubsan_handle_load_invalid_value(InvalidValueData *Data, 427276789Sdim ValueHandle Val) { 428276789Sdim GET_REPORT_OPTIONS(false); 429276789Sdim handleLoadInvalidValue(Data, Val, Opts); 430276789Sdim} 431245614Sandrewvoid __ubsan::__ubsan_handle_load_invalid_value_abort(InvalidValueData *Data, 432245614Sandrew ValueHandle Val) { 433276789Sdim GET_REPORT_OPTIONS(true); 434276789Sdim handleLoadInvalidValue(Data, Val, Opts); 435245614Sandrew Die(); 436245614Sandrew} 437274201Sdim 438276789Sdimstatic void handleFunctionTypeMismatch(FunctionTypeMismatchData *Data, 439276789Sdim ValueHandle Function, 440276789Sdim ReportOptions Opts) { 441280031Sdim SourceLocation CallLoc = Data->Loc.acquire(); 442296417Sdim ErrorType ET = ErrorType::FunctionTypeMismatch; 443296417Sdim 444296417Sdim if (ignoreReport(CallLoc, Opts, ET)) 445280031Sdim return; 446274201Sdim 447296417Sdim ScopedReport R(Opts, CallLoc, ET); 448274201Sdim 449280031Sdim SymbolizedStackHolder FLoc(getSymbolizedLocation(Function)); 450280031Sdim const char *FName = FLoc.get()->info.function; 451280031Sdim if (!FName) 452280031Sdim FName = "(unknown)"; 453276789Sdim 454280031Sdim Diag(CallLoc, DL_Error, 455274201Sdim "call to function %0 through pointer to incorrect function type %1") 456280031Sdim << FName << Data->Type; 457280031Sdim Diag(FLoc, DL_Note, "%0 defined here") << FName; 458274201Sdim} 459274201Sdim 460276789Sdimvoid 461276789Sdim__ubsan::__ubsan_handle_function_type_mismatch(FunctionTypeMismatchData *Data, 462276789Sdim ValueHandle Function) { 463276789Sdim GET_REPORT_OPTIONS(false); 464276789Sdim handleFunctionTypeMismatch(Data, Function, Opts); 465276789Sdim} 466276789Sdim 467274201Sdimvoid __ubsan::__ubsan_handle_function_type_mismatch_abort( 468276789Sdim FunctionTypeMismatchData *Data, ValueHandle Function) { 469276789Sdim GET_REPORT_OPTIONS(true); 470276789Sdim handleFunctionTypeMismatch(Data, Function, Opts); 471274201Sdim Die(); 472274201Sdim} 473276789Sdim 474276789Sdimstatic void handleNonNullReturn(NonNullReturnData *Data, ReportOptions Opts) { 475276789Sdim SourceLocation Loc = Data->Loc.acquire(); 476296417Sdim ErrorType ET = ErrorType::InvalidNullReturn; 477296417Sdim 478296417Sdim if (ignoreReport(Loc, Opts, ET)) 479276789Sdim return; 480276789Sdim 481296417Sdim ScopedReport R(Opts, Loc, ET); 482276789Sdim 483276789Sdim Diag(Loc, DL_Error, "null pointer returned from function declared to never " 484276789Sdim "return null"); 485276789Sdim if (!Data->AttrLoc.isInvalid()) 486276789Sdim Diag(Data->AttrLoc, DL_Note, "returns_nonnull attribute specified here"); 487276789Sdim} 488276789Sdim 489276789Sdimvoid __ubsan::__ubsan_handle_nonnull_return(NonNullReturnData *Data) { 490276789Sdim GET_REPORT_OPTIONS(false); 491276789Sdim handleNonNullReturn(Data, Opts); 492276789Sdim} 493276789Sdim 494276789Sdimvoid __ubsan::__ubsan_handle_nonnull_return_abort(NonNullReturnData *Data) { 495276789Sdim GET_REPORT_OPTIONS(true); 496276789Sdim handleNonNullReturn(Data, Opts); 497276789Sdim Die(); 498276789Sdim} 499276789Sdim 500276789Sdimstatic void handleNonNullArg(NonNullArgData *Data, ReportOptions Opts) { 501276789Sdim SourceLocation Loc = Data->Loc.acquire(); 502296417Sdim ErrorType ET = ErrorType::InvalidNullArgument; 503296417Sdim 504296417Sdim if (ignoreReport(Loc, Opts, ET)) 505276789Sdim return; 506276789Sdim 507296417Sdim ScopedReport R(Opts, Loc, ET); 508276789Sdim 509276789Sdim Diag(Loc, DL_Error, "null pointer passed as argument %0, which is declared to " 510276789Sdim "never be null") << Data->ArgIndex; 511276789Sdim if (!Data->AttrLoc.isInvalid()) 512276789Sdim Diag(Data->AttrLoc, DL_Note, "nonnull attribute specified here"); 513276789Sdim} 514276789Sdim 515276789Sdimvoid __ubsan::__ubsan_handle_nonnull_arg(NonNullArgData *Data) { 516276789Sdim GET_REPORT_OPTIONS(false); 517276789Sdim handleNonNullArg(Data, Opts); 518276789Sdim} 519276789Sdim 520276789Sdimvoid __ubsan::__ubsan_handle_nonnull_arg_abort(NonNullArgData *Data) { 521276789Sdim GET_REPORT_OPTIONS(true); 522276789Sdim handleNonNullArg(Data, Opts); 523276789Sdim Die(); 524276789Sdim} 525288943Sdim 526296417Sdimstatic void handleCFIBadIcall(CFIBadIcallData *Data, ValueHandle Function, 527296417Sdim ReportOptions Opts) { 528296417Sdim SourceLocation Loc = Data->Loc.acquire(); 529296417Sdim ErrorType ET = ErrorType::CFIBadType; 530296417Sdim 531296417Sdim if (ignoreReport(Loc, Opts, ET)) 532296417Sdim return; 533296417Sdim 534296417Sdim ScopedReport R(Opts, Loc, ET); 535296417Sdim 536296417Sdim Diag(Loc, DL_Error, "control flow integrity check for type %0 failed during " 537296417Sdim "indirect function call") 538296417Sdim << Data->Type; 539296417Sdim 540296417Sdim SymbolizedStackHolder FLoc(getSymbolizedLocation(Function)); 541296417Sdim const char *FName = FLoc.get()->info.function; 542296417Sdim if (!FName) 543296417Sdim FName = "(unknown)"; 544296417Sdim Diag(FLoc, DL_Note, "%0 defined here") << FName; 545296417Sdim} 546296417Sdim 547296417Sdimvoid __ubsan::__ubsan_handle_cfi_bad_icall(CFIBadIcallData *Data, 548296417Sdim ValueHandle Function) { 549296417Sdim GET_REPORT_OPTIONS(false); 550296417Sdim handleCFIBadIcall(Data, Function, Opts); 551296417Sdim} 552296417Sdim 553296417Sdimvoid __ubsan::__ubsan_handle_cfi_bad_icall_abort(CFIBadIcallData *Data, 554296417Sdim ValueHandle Function) { 555296417Sdim GET_REPORT_OPTIONS(true); 556296417Sdim handleCFIBadIcall(Data, Function, Opts); 557296417Sdim Die(); 558296417Sdim} 559296417Sdim 560288943Sdim#endif // CAN_SANITIZE_UB 561