diff options
author | Ted Kremenek <kremenek@apple.com> | 2008-09-18 23:09:54 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2008-09-18 23:09:54 +0000 |
commit | 7360fda1efd88fd28ca2882579676dbd8569c181 (patch) | |
tree | 923c21a0fa78f3ce6a44f56489f01e5e8c29adaf /lib/Analysis/CheckNSError.cpp | |
parent | 644f5fc35c9d093b2ae1e8f43cf5a70680b5945a (diff) |
Implement second part of PR 2600: NSError** parameter may be null, and should be checked before being dereferenced.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@56318 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/CheckNSError.cpp')
-rw-r--r-- | lib/Analysis/CheckNSError.cpp | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/lib/Analysis/CheckNSError.cpp b/lib/Analysis/CheckNSError.cpp index 4c7f2cf25d..d39fa0a86a 100644 --- a/lib/Analysis/CheckNSError.cpp +++ b/lib/Analysis/CheckNSError.cpp @@ -37,9 +37,16 @@ class VISIBILITY_HIDDEN NSErrorCheck : public BugTypeCacheLocation { bool CheckArgument(QualType ArgTy, IdentifierInfo* NSErrorII); + void CheckParamDeref(VarDecl* V, GRStateRef state, GRExprEngine& Eng, + GRBugReporter& BR); + + const char* desc; public: + NSErrorCheck() : desc(0) {} + void EmitWarnings(BugReporter& BR) { EmitGRWarnings(cast<GRBugReporter>(BR));} const char* getName() const { return "NSError** null dereference"; } + const char* getDescription() const { return desc; } }; } // end anonymous namespace @@ -77,6 +84,14 @@ void NSErrorCheck::EmitGRWarnings(GRBugReporter& BR) { CodeDecl.getLocation()); } + + // Scan the NSError** parameters for an implicit null dereference. + for (llvm::SmallVectorImpl<VarDecl*>::iterator I=Params.begin(), + E=Params.end(); I!=E; ++I) + for (GRExprEngine::GraphTy::roots_iterator RI=G.roots_begin(), + RE=G.roots_end(); RI!=RE; ++RI) + CheckParamDeref(*I, GRStateRef((*RI)->getState(), Eng.getStateManager()), + Eng, BR); } void NSErrorCheck::CheckSignature(ObjCMethodDecl& M, QualType& ResultTy, @@ -104,3 +119,36 @@ bool NSErrorCheck::CheckArgument(QualType ArgTy, IdentifierInfo* NSErrorII) { if (!IT) return false; return IT->getDecl()->getIdentifier() == NSErrorII; } + +void NSErrorCheck::CheckParamDeref(VarDecl* Param, GRStateRef rootState, + GRExprEngine& Eng, GRBugReporter& BR) { + + RVal ParamRVal = rootState.GetRVal(lval::DeclVal(Param)); + + // FIXME: For now assume that ParamRVal is symbolic. We need to generalize + // this later. + lval::SymbolVal* SV = dyn_cast<lval::SymbolVal>(&ParamRVal); + if (!SV) return; + + // Iterate over the implicit-null dereferences. + for (GRExprEngine::null_deref_iterator I=Eng.implicit_null_derefs_begin(), + E=Eng.implicit_null_derefs_end(); I!=E; ++I) { + + GRStateRef state = GRStateRef((*I)->getState(), Eng.getStateManager()); + const RVal* X = state.get<GRState::NullDerefTag>(); + const lval::SymbolVal* SVX = dyn_cast_or_null<lval::SymbolVal>(X); + if (!SVX || SVX->getSymbol() != SV->getSymbol()) continue; + + // Emit an error. + BugReport R(*this, *I); + + std::string msg; + llvm::raw_string_ostream os(msg); + os << "Potential null dereference. According to coding standards in " + "'Creating and Returning NSError Objects' the parameter '" + << Param->getName() << "' may be null."; + desc = os.str().c_str(); + + BR.EmitWarning(R); + } +} |