1 //===--- CallAndMessageChecker.cpp ------------------------------*- C++ -*--==// 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 // This defines CallAndMessageChecker, a builtin checker that checks for various 10 // errors of call and objc message expressions. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "clang/AST/ExprCXX.h" 15 #include "clang/AST/ParentMap.h" 16 #include "clang/Basic/TargetInfo.h" 17 #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" 18 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 19 #include "clang/StaticAnalyzer/Core/Checker.h" 20 #include "clang/StaticAnalyzer/Core/CheckerManager.h" 21 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" 22 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 23 #include "llvm/ADT/SmallString.h" 24 #include "llvm/ADT/StringExtras.h" 25 #include "llvm/Support/Casting.h" 26 #include "llvm/Support/raw_ostream.h" 27 28 using namespace clang; 29 using namespace ento; 30 31 namespace { 32 33 class CallAndMessageChecker 34 : public Checker<check::PreObjCMessage, check::ObjCMessageNil, 35 check::PreCall> { 36 mutable std::unique_ptr<BugType> BT_call_null; 37 mutable std::unique_ptr<BugType> BT_call_undef; 38 mutable std::unique_ptr<BugType> BT_cxx_call_null; 39 mutable std::unique_ptr<BugType> BT_cxx_call_undef; 40 mutable std::unique_ptr<BugType> BT_call_arg; 41 mutable std::unique_ptr<BugType> BT_cxx_delete_undef; 42 mutable std::unique_ptr<BugType> BT_msg_undef; 43 mutable std::unique_ptr<BugType> BT_objc_prop_undef; 44 mutable std::unique_ptr<BugType> BT_objc_subscript_undef; 45 mutable std::unique_ptr<BugType> BT_msg_arg; 46 mutable std::unique_ptr<BugType> BT_msg_ret; 47 mutable std::unique_ptr<BugType> BT_call_few_args; 48 49 public: 50 enum CheckKind { CK_CallAndMessageUnInitRefArg, CK_NumCheckKinds }; 51 52 DefaultBool ChecksEnabled[CK_NumCheckKinds]; 53 54 void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const; 55 56 /// Fill in the return value that results from messaging nil based on the 57 /// return type and architecture and diagnose if the return value will be 58 /// garbage. 59 void checkObjCMessageNil(const ObjCMethodCall &msg, CheckerContext &C) const; 60 61 void checkPreCall(const CallEvent &Call, CheckerContext &C) const; 62 63 ProgramStateRef checkFunctionPointerCall(const CallExpr *CE, 64 CheckerContext &C, 65 ProgramStateRef State) const; 66 67 ProgramStateRef checkCXXMethodCall(const CXXInstanceCall *CC, 68 CheckerContext &C, 69 ProgramStateRef State) const; 70 71 ProgramStateRef checkParameterCount(const CallEvent &Call, CheckerContext &C, 72 ProgramStateRef State) const; 73 74 ProgramStateRef checkCXXDeallocation(const CXXDeallocatorCall *DC, 75 CheckerContext &C, 76 ProgramStateRef State) const; 77 78 ProgramStateRef checkArgInitializedness(const CallEvent &Call, 79 CheckerContext &C, 80 ProgramStateRef State) const; 81 82 private: 83 bool PreVisitProcessArg(CheckerContext &C, SVal V, SourceRange ArgRange, 84 const Expr *ArgEx, int ArgumentNumber, 85 bool CheckUninitFields, const CallEvent &Call, 86 std::unique_ptr<BugType> &BT, 87 const ParmVarDecl *ParamDecl) const; 88 89 static void emitBadCall(BugType *BT, CheckerContext &C, const Expr *BadE); 90 void emitNilReceiverBug(CheckerContext &C, const ObjCMethodCall &msg, 91 ExplodedNode *N) const; 92 93 void HandleNilReceiver(CheckerContext &C, 94 ProgramStateRef state, 95 const ObjCMethodCall &msg) const; 96 97 void LazyInit_BT(const char *desc, std::unique_ptr<BugType> &BT) const { 98 if (!BT) 99 BT.reset(new BuiltinBug(this, desc)); 100 } 101 bool uninitRefOrPointer(CheckerContext &C, const SVal &V, 102 SourceRange ArgRange, const Expr *ArgEx, 103 std::unique_ptr<BugType> &BT, 104 const ParmVarDecl *ParamDecl, const char *BD, 105 int ArgumentNumber) const; 106 }; 107 } // end anonymous namespace 108 109 void CallAndMessageChecker::emitBadCall(BugType *BT, CheckerContext &C, 110 const Expr *BadE) { 111 ExplodedNode *N = C.generateErrorNode(); 112 if (!N) 113 return; 114 115 auto R = std::make_unique<PathSensitiveBugReport>(*BT, BT->getDescription(), N); 116 if (BadE) { 117 R->addRange(BadE->getSourceRange()); 118 if (BadE->isGLValue()) 119 BadE = bugreporter::getDerefExpr(BadE); 120 bugreporter::trackExpressionValue(N, BadE, *R); 121 } 122 C.emitReport(std::move(R)); 123 } 124 125 static void describeUninitializedArgumentInCall(const CallEvent &Call, 126 int ArgumentNumber, 127 llvm::raw_svector_ostream &Os) { 128 switch (Call.getKind()) { 129 case CE_ObjCMessage: { 130 const ObjCMethodCall &Msg = cast<ObjCMethodCall>(Call); 131 switch (Msg.getMessageKind()) { 132 case OCM_Message: 133 Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1) 134 << " argument in message expression is an uninitialized value"; 135 return; 136 case OCM_PropertyAccess: 137 assert(Msg.isSetter() && "Getters have no args"); 138 Os << "Argument for property setter is an uninitialized value"; 139 return; 140 case OCM_Subscript: 141 if (Msg.isSetter() && (ArgumentNumber == 0)) 142 Os << "Argument for subscript setter is an uninitialized value"; 143 else 144 Os << "Subscript index is an uninitialized value"; 145 return; 146 } 147 llvm_unreachable("Unknown message kind."); 148 } 149 case CE_Block: 150 Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1) 151 << " block call argument is an uninitialized value"; 152 return; 153 default: 154 Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1) 155 << " function call argument is an uninitialized value"; 156 return; 157 } 158 } 159 160 bool CallAndMessageChecker::uninitRefOrPointer( 161 CheckerContext &C, const SVal &V, SourceRange ArgRange, const Expr *ArgEx, 162 std::unique_ptr<BugType> &BT, const ParmVarDecl *ParamDecl, const char *BD, 163 int ArgumentNumber) const { 164 if (!ChecksEnabled[CK_CallAndMessageUnInitRefArg]) 165 return false; 166 167 // No parameter declaration available, i.e. variadic function argument. 168 if(!ParamDecl) 169 return false; 170 171 // If parameter is declared as pointer to const in function declaration, 172 // then check if corresponding argument in function call is 173 // pointing to undefined symbol value (uninitialized memory). 174 SmallString<200> Buf; 175 llvm::raw_svector_ostream Os(Buf); 176 177 if (ParamDecl->getType()->isPointerType()) { 178 Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1) 179 << " function call argument is a pointer to uninitialized value"; 180 } else if (ParamDecl->getType()->isReferenceType()) { 181 Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1) 182 << " function call argument is an uninitialized value"; 183 } else 184 return false; 185 186 if(!ParamDecl->getType()->getPointeeType().isConstQualified()) 187 return false; 188 189 if (const MemRegion *SValMemRegion = V.getAsRegion()) { 190 const ProgramStateRef State = C.getState(); 191 const SVal PSV = State->getSVal(SValMemRegion, C.getASTContext().CharTy); 192 if (PSV.isUndef()) { 193 if (ExplodedNode *N = C.generateErrorNode()) { 194 LazyInit_BT(BD, BT); 195 auto R = std::make_unique<PathSensitiveBugReport>(*BT, Os.str(), N); 196 R->addRange(ArgRange); 197 if (ArgEx) 198 bugreporter::trackExpressionValue(N, ArgEx, *R); 199 200 C.emitReport(std::move(R)); 201 } 202 return true; 203 } 204 } 205 return false; 206 } 207 208 namespace { 209 class FindUninitializedField { 210 public: 211 SmallVector<const FieldDecl *, 10> FieldChain; 212 213 private: 214 StoreManager &StoreMgr; 215 MemRegionManager &MrMgr; 216 Store store; 217 218 public: 219 FindUninitializedField(StoreManager &storeMgr, MemRegionManager &mrMgr, 220 Store s) 221 : StoreMgr(storeMgr), MrMgr(mrMgr), store(s) {} 222 223 bool Find(const TypedValueRegion *R) { 224 QualType T = R->getValueType(); 225 if (const RecordType *RT = T->getAsStructureType()) { 226 const RecordDecl *RD = RT->getDecl()->getDefinition(); 227 assert(RD && "Referred record has no definition"); 228 for (const auto *I : RD->fields()) { 229 const FieldRegion *FR = MrMgr.getFieldRegion(I, R); 230 FieldChain.push_back(I); 231 T = I->getType(); 232 if (T->getAsStructureType()) { 233 if (Find(FR)) 234 return true; 235 } else { 236 const SVal &V = StoreMgr.getBinding(store, loc::MemRegionVal(FR)); 237 if (V.isUndef()) 238 return true; 239 } 240 FieldChain.pop_back(); 241 } 242 } 243 244 return false; 245 } 246 }; 247 } // namespace 248 249 bool CallAndMessageChecker::PreVisitProcessArg(CheckerContext &C, 250 SVal V, 251 SourceRange ArgRange, 252 const Expr *ArgEx, 253 int ArgumentNumber, 254 bool CheckUninitFields, 255 const CallEvent &Call, 256 std::unique_ptr<BugType> &BT, 257 const ParmVarDecl *ParamDecl 258 ) const { 259 const char *BD = "Uninitialized argument value"; 260 261 if (uninitRefOrPointer(C, V, ArgRange, ArgEx, BT, ParamDecl, BD, 262 ArgumentNumber)) 263 return true; 264 265 if (V.isUndef()) { 266 if (ExplodedNode *N = C.generateErrorNode()) { 267 LazyInit_BT(BD, BT); 268 // Generate a report for this bug. 269 SmallString<200> Buf; 270 llvm::raw_svector_ostream Os(Buf); 271 describeUninitializedArgumentInCall(Call, ArgumentNumber, Os); 272 auto R = std::make_unique<PathSensitiveBugReport>(*BT, Os.str(), N); 273 274 R->addRange(ArgRange); 275 if (ArgEx) 276 bugreporter::trackExpressionValue(N, ArgEx, *R); 277 C.emitReport(std::move(R)); 278 } 279 return true; 280 } 281 282 if (!CheckUninitFields) 283 return false; 284 285 if (auto LV = V.getAs<nonloc::LazyCompoundVal>()) { 286 const LazyCompoundValData *D = LV->getCVData(); 287 FindUninitializedField F(C.getState()->getStateManager().getStoreManager(), 288 C.getSValBuilder().getRegionManager(), 289 D->getStore()); 290 291 if (F.Find(D->getRegion())) { 292 if (ExplodedNode *N = C.generateErrorNode()) { 293 LazyInit_BT(BD, BT); 294 SmallString<512> Str; 295 llvm::raw_svector_ostream os(Str); 296 os << "Passed-by-value struct argument contains uninitialized data"; 297 298 if (F.FieldChain.size() == 1) 299 os << " (e.g., field: '" << *F.FieldChain[0] << "')"; 300 else { 301 os << " (e.g., via the field chain: '"; 302 bool first = true; 303 for (SmallVectorImpl<const FieldDecl *>::iterator 304 DI = F.FieldChain.begin(), DE = F.FieldChain.end(); DI!=DE;++DI){ 305 if (first) 306 first = false; 307 else 308 os << '.'; 309 os << **DI; 310 } 311 os << "')"; 312 } 313 314 // Generate a report for this bug. 315 auto R = std::make_unique<PathSensitiveBugReport>(*BT, os.str(), N); 316 R->addRange(ArgRange); 317 318 if (ArgEx) 319 bugreporter::trackExpressionValue(N, ArgEx, *R); 320 // FIXME: enhance track back for uninitialized value for arbitrary 321 // memregions 322 C.emitReport(std::move(R)); 323 } 324 return true; 325 } 326 } 327 328 return false; 329 } 330 331 ProgramStateRef CallAndMessageChecker::checkFunctionPointerCall( 332 const CallExpr *CE, CheckerContext &C, ProgramStateRef State) const { 333 334 const Expr *Callee = CE->getCallee()->IgnoreParens(); 335 const LocationContext *LCtx = C.getLocationContext(); 336 SVal L = State->getSVal(Callee, LCtx); 337 338 if (L.isUndef()) { 339 if (!BT_call_undef) 340 BT_call_undef.reset(new BuiltinBug( 341 this, "Called function pointer is an uninitialized pointer value")); 342 emitBadCall(BT_call_undef.get(), C, Callee); 343 return nullptr; 344 } 345 346 ProgramStateRef StNonNull, StNull; 347 std::tie(StNonNull, StNull) = State->assume(L.castAs<DefinedOrUnknownSVal>()); 348 349 if (StNull && !StNonNull) { 350 if (!BT_call_null) 351 BT_call_null.reset(new BuiltinBug( 352 this, "Called function pointer is null (null dereference)")); 353 emitBadCall(BT_call_null.get(), C, Callee); 354 return nullptr; 355 } 356 357 return StNonNull; 358 } 359 360 ProgramStateRef CallAndMessageChecker::checkParameterCount( 361 const CallEvent &Call, CheckerContext &C, ProgramStateRef State) const { 362 363 // If we have a function or block declaration, we can make sure we pass 364 // enough parameters. 365 unsigned Params = Call.parameters().size(); 366 if (Call.getNumArgs() >= Params) 367 return State; 368 369 ExplodedNode *N = C.generateErrorNode(); 370 if (!N) 371 return nullptr; 372 373 LazyInit_BT("Function call with too few arguments", BT_call_few_args); 374 375 SmallString<512> Str; 376 llvm::raw_svector_ostream os(Str); 377 if (isa<AnyFunctionCall>(Call)) { 378 os << "Function "; 379 } else { 380 assert(isa<BlockCall>(Call)); 381 os << "Block "; 382 } 383 os << "taking " << Params << " argument" << (Params == 1 ? "" : "s") 384 << " is called with fewer (" << Call.getNumArgs() << ")"; 385 386 C.emitReport( 387 std::make_unique<PathSensitiveBugReport>(*BT_call_few_args, os.str(), N)); 388 return nullptr; 389 } 390 391 ProgramStateRef CallAndMessageChecker::checkCXXMethodCall( 392 const CXXInstanceCall *CC, CheckerContext &C, ProgramStateRef State) const { 393 394 SVal V = CC->getCXXThisVal(); 395 if (V.isUndef()) { 396 if (!BT_cxx_call_undef) 397 BT_cxx_call_undef.reset( 398 new BuiltinBug(this, "Called C++ object pointer is uninitialized")); 399 emitBadCall(BT_cxx_call_undef.get(), C, CC->getCXXThisExpr()); 400 return nullptr; 401 } 402 403 ProgramStateRef StNonNull, StNull; 404 std::tie(StNonNull, StNull) = State->assume(V.castAs<DefinedOrUnknownSVal>()); 405 406 if (StNull && !StNonNull) { 407 if (!BT_cxx_call_null) 408 BT_cxx_call_null.reset( 409 new BuiltinBug(this, "Called C++ object pointer is null")); 410 emitBadCall(BT_cxx_call_null.get(), C, CC->getCXXThisExpr()); 411 return nullptr; 412 } 413 414 return StNonNull; 415 } 416 417 ProgramStateRef 418 CallAndMessageChecker::checkCXXDeallocation(const CXXDeallocatorCall *DC, 419 CheckerContext &C, 420 ProgramStateRef State) const { 421 const CXXDeleteExpr *DE = DC->getOriginExpr(); 422 assert(DE); 423 SVal Arg = C.getSVal(DE->getArgument()); 424 if (!Arg.isUndef()) 425 return State; 426 427 StringRef Desc; 428 ExplodedNode *N = C.generateErrorNode(); 429 if (!N) 430 return nullptr; 431 if (!BT_cxx_delete_undef) 432 BT_cxx_delete_undef.reset( 433 new BuiltinBug(this, "Uninitialized argument value")); 434 if (DE->isArrayFormAsWritten()) 435 Desc = "Argument to 'delete[]' is uninitialized"; 436 else 437 Desc = "Argument to 'delete' is uninitialized"; 438 BugType *BT = BT_cxx_delete_undef.get(); 439 auto R = std::make_unique<PathSensitiveBugReport>(*BT, Desc, N); 440 bugreporter::trackExpressionValue(N, DE, *R); 441 C.emitReport(std::move(R)); 442 return nullptr; 443 } 444 445 ProgramStateRef CallAndMessageChecker::checkArgInitializedness( 446 const CallEvent &Call, CheckerContext &C, ProgramStateRef State) const { 447 448 const Decl *D = Call.getDecl(); 449 450 // Don't check for uninitialized field values in arguments if the 451 // caller has a body that is available and we have the chance to inline it. 452 // This is a hack, but is a reasonable compromise betweens sometimes warning 453 // and sometimes not depending on if we decide to inline a function. 454 const bool checkUninitFields = 455 !(C.getAnalysisManager().shouldInlineCall() && (D && D->getBody())); 456 457 std::unique_ptr<BugType> *BT; 458 if (isa<ObjCMethodCall>(Call)) 459 BT = &BT_msg_arg; 460 else 461 BT = &BT_call_arg; 462 463 const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D); 464 for (unsigned i = 0, e = Call.getNumArgs(); i != e; ++i) { 465 const ParmVarDecl *ParamDecl = nullptr; 466 if (FD && i < FD->getNumParams()) 467 ParamDecl = FD->getParamDecl(i); 468 if (PreVisitProcessArg(C, Call.getArgSVal(i), Call.getArgSourceRange(i), 469 Call.getArgExpr(i), i, checkUninitFields, Call, *BT, 470 ParamDecl)) 471 return nullptr; 472 } 473 return State; 474 } 475 476 void CallAndMessageChecker::checkPreCall(const CallEvent &Call, 477 CheckerContext &C) const { 478 ProgramStateRef State = C.getState(); 479 480 if (const CallExpr *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr())) 481 State = checkFunctionPointerCall(CE, C, State); 482 483 if (!State) 484 return; 485 486 if (Call.getDecl()) 487 State = checkParameterCount(Call, C, State); 488 489 if (!State) 490 return; 491 492 if (const auto *CC = dyn_cast<CXXInstanceCall>(&Call)) 493 State = checkCXXMethodCall(CC, C, State); 494 495 if (!State) 496 return; 497 498 if (const auto *DC = dyn_cast<CXXDeallocatorCall>(&Call)) 499 State = checkCXXDeallocation(DC, C, State); 500 501 if (!State) 502 return; 503 504 State = checkArgInitializedness(Call, C, State); 505 506 // If we make it here, record our assumptions about the callee. 507 C.addTransition(State); 508 } 509 510 void CallAndMessageChecker::checkPreObjCMessage(const ObjCMethodCall &msg, 511 CheckerContext &C) const { 512 SVal recVal = msg.getReceiverSVal(); 513 if (recVal.isUndef()) { 514 if (ExplodedNode *N = C.generateErrorNode()) { 515 BugType *BT = nullptr; 516 switch (msg.getMessageKind()) { 517 case OCM_Message: 518 if (!BT_msg_undef) 519 BT_msg_undef.reset(new BuiltinBug(this, 520 "Receiver in message expression " 521 "is an uninitialized value")); 522 BT = BT_msg_undef.get(); 523 break; 524 case OCM_PropertyAccess: 525 if (!BT_objc_prop_undef) 526 BT_objc_prop_undef.reset(new BuiltinBug( 527 this, "Property access on an uninitialized object pointer")); 528 BT = BT_objc_prop_undef.get(); 529 break; 530 case OCM_Subscript: 531 if (!BT_objc_subscript_undef) 532 BT_objc_subscript_undef.reset(new BuiltinBug( 533 this, "Subscript access on an uninitialized object pointer")); 534 BT = BT_objc_subscript_undef.get(); 535 break; 536 } 537 assert(BT && "Unknown message kind."); 538 539 auto R = std::make_unique<PathSensitiveBugReport>(*BT, BT->getDescription(), N); 540 const ObjCMessageExpr *ME = msg.getOriginExpr(); 541 R->addRange(ME->getReceiverRange()); 542 543 // FIXME: getTrackNullOrUndefValueVisitor can't handle "super" yet. 544 if (const Expr *ReceiverE = ME->getInstanceReceiver()) 545 bugreporter::trackExpressionValue(N, ReceiverE, *R); 546 C.emitReport(std::move(R)); 547 } 548 return; 549 } 550 } 551 552 void CallAndMessageChecker::checkObjCMessageNil(const ObjCMethodCall &msg, 553 CheckerContext &C) const { 554 HandleNilReceiver(C, C.getState(), msg); 555 } 556 557 void CallAndMessageChecker::emitNilReceiverBug(CheckerContext &C, 558 const ObjCMethodCall &msg, 559 ExplodedNode *N) const { 560 561 if (!BT_msg_ret) 562 BT_msg_ret.reset( 563 new BuiltinBug(this, "Receiver in message expression is 'nil'")); 564 565 const ObjCMessageExpr *ME = msg.getOriginExpr(); 566 567 QualType ResTy = msg.getResultType(); 568 569 SmallString<200> buf; 570 llvm::raw_svector_ostream os(buf); 571 os << "The receiver of message '"; 572 ME->getSelector().print(os); 573 os << "' is nil"; 574 if (ResTy->isReferenceType()) { 575 os << ", which results in forming a null reference"; 576 } else { 577 os << " and returns a value of type '"; 578 msg.getResultType().print(os, C.getLangOpts()); 579 os << "' that will be garbage"; 580 } 581 582 auto report = 583 std::make_unique<PathSensitiveBugReport>(*BT_msg_ret, os.str(), N); 584 report->addRange(ME->getReceiverRange()); 585 // FIXME: This won't track "self" in messages to super. 586 if (const Expr *receiver = ME->getInstanceReceiver()) { 587 bugreporter::trackExpressionValue(N, receiver, *report); 588 } 589 C.emitReport(std::move(report)); 590 } 591 592 static bool supportsNilWithFloatRet(const llvm::Triple &triple) { 593 return (triple.getVendor() == llvm::Triple::Apple && 594 (triple.isiOS() || triple.isWatchOS() || 595 !triple.isMacOSXVersionLT(10,5))); 596 } 597 598 void CallAndMessageChecker::HandleNilReceiver(CheckerContext &C, 599 ProgramStateRef state, 600 const ObjCMethodCall &Msg) const { 601 ASTContext &Ctx = C.getASTContext(); 602 static CheckerProgramPointTag Tag(this, "NilReceiver"); 603 604 // Check the return type of the message expression. A message to nil will 605 // return different values depending on the return type and the architecture. 606 QualType RetTy = Msg.getResultType(); 607 CanQualType CanRetTy = Ctx.getCanonicalType(RetTy); 608 const LocationContext *LCtx = C.getLocationContext(); 609 610 if (CanRetTy->isStructureOrClassType()) { 611 // Structure returns are safe since the compiler zeroes them out. 612 SVal V = C.getSValBuilder().makeZeroVal(RetTy); 613 C.addTransition(state->BindExpr(Msg.getOriginExpr(), LCtx, V), &Tag); 614 return; 615 } 616 617 // Other cases: check if sizeof(return type) > sizeof(void*) 618 if (CanRetTy != Ctx.VoidTy && C.getLocationContext()->getParentMap() 619 .isConsumedExpr(Msg.getOriginExpr())) { 620 // Compute: sizeof(void *) and sizeof(return type) 621 const uint64_t voidPtrSize = Ctx.getTypeSize(Ctx.VoidPtrTy); 622 const uint64_t returnTypeSize = Ctx.getTypeSize(CanRetTy); 623 624 if (CanRetTy.getTypePtr()->isReferenceType()|| 625 (voidPtrSize < returnTypeSize && 626 !(supportsNilWithFloatRet(Ctx.getTargetInfo().getTriple()) && 627 (Ctx.FloatTy == CanRetTy || 628 Ctx.DoubleTy == CanRetTy || 629 Ctx.LongDoubleTy == CanRetTy || 630 Ctx.LongLongTy == CanRetTy || 631 Ctx.UnsignedLongLongTy == CanRetTy)))) { 632 if (ExplodedNode *N = C.generateErrorNode(state, &Tag)) 633 emitNilReceiverBug(C, Msg, N); 634 return; 635 } 636 637 // Handle the safe cases where the return value is 0 if the 638 // receiver is nil. 639 // 640 // FIXME: For now take the conservative approach that we only 641 // return null values if we *know* that the receiver is nil. 642 // This is because we can have surprises like: 643 // 644 // ... = [[NSScreens screens] objectAtIndex:0]; 645 // 646 // What can happen is that [... screens] could return nil, but 647 // it most likely isn't nil. We should assume the semantics 648 // of this case unless we have *a lot* more knowledge. 649 // 650 SVal V = C.getSValBuilder().makeZeroVal(RetTy); 651 C.addTransition(state->BindExpr(Msg.getOriginExpr(), LCtx, V), &Tag); 652 return; 653 } 654 655 C.addTransition(state); 656 } 657 658 void ento::registerCallAndMessageChecker(CheckerManager &mgr) { 659 mgr.registerChecker<CallAndMessageChecker>(); 660 } 661 662 bool ento::shouldRegisterCallAndMessageChecker(const CheckerManager &mgr) { 663 return true; 664 } 665 666 #define REGISTER_CHECKER(name) \ 667 void ento::register##name(CheckerManager &mgr) { \ 668 CallAndMessageChecker *checker = mgr.getChecker<CallAndMessageChecker>(); \ 669 checker->ChecksEnabled[CallAndMessageChecker::CK_##name] = true; \ 670 \ 671 } \ 672 \ 673 bool ento::shouldRegister##name(const CheckerManager &mgr) { return true; } 674 675 REGISTER_CHECKER(CallAndMessageUnInitRefArg) 676