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