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