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