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