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