[cfe-commits] r56318 - in /cfe/trunk: include/clang/Analysis/PathSensitive/BasicValueFactory.h include/clang/Analysis/PathSensitive/GRExprEngine.h include/clang/Analysis/PathSensitive/GRState.h lib/AST/Type.cpp lib/Analysis/BasicValueFactory.cpp lib/Analysis/CheckNSError.cpp lib/Analysis/GRExprEngine.cpp lib/Analysis/GRState.cpp
Ted Kremenek
kremenek at apple.com
Thu Sep 18 16:09:54 PDT 2008
Author: kremenek
Date: Thu Sep 18 18:09:54 2008
New Revision: 56318
URL: http://llvm.org/viewvc/llvm-project?rev=56318&view=rev
Log:
Implement second part of PR 2600: NSError** parameter may be null, and should be checked before being dereferenced.
Modified:
cfe/trunk/include/clang/Analysis/PathSensitive/BasicValueFactory.h
cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h
cfe/trunk/include/clang/Analysis/PathSensitive/GRState.h
cfe/trunk/lib/AST/Type.cpp
cfe/trunk/lib/Analysis/BasicValueFactory.cpp
cfe/trunk/lib/Analysis/CheckNSError.cpp
cfe/trunk/lib/Analysis/GRExprEngine.cpp
cfe/trunk/lib/Analysis/GRState.cpp
Modified: cfe/trunk/include/clang/Analysis/PathSensitive/BasicValueFactory.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/BasicValueFactory.h?rev=56318&r1=56317&r2=56318&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/BasicValueFactory.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/BasicValueFactory.h Thu Sep 18 18:09:54 2008
@@ -77,6 +77,8 @@
const std::pair<RVal, RVal>&
getPersistentRValPair(const RVal& V1, const RVal& V2);
+
+ const RVal* getPersistentRVal(RVal X);
};
} // end clang namespace
Modified: cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h?rev=56318&r1=56317&r2=56318&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h Thu Sep 18 18:09:54 2008
@@ -293,6 +293,13 @@
null_deref_iterator null_derefs_begin() { return ExplicitNullDeref.begin(); }
null_deref_iterator null_derefs_end() { return ExplicitNullDeref.end(); }
+ null_deref_iterator implicit_null_derefs_begin() {
+ return ImplicitNullDeref.begin();
+ }
+ null_deref_iterator implicit_null_derefs_end() {
+ return ImplicitNullDeref.end();
+ }
+
typedef BadDerefTy::iterator undef_deref_iterator;
undef_deref_iterator undef_derefs_begin() { return UndefDeref.begin(); }
undef_deref_iterator undef_derefs_end() { return UndefDeref.end(); }
Modified: cfe/trunk/include/clang/Analysis/PathSensitive/GRState.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/GRState.h?rev=56318&r1=56317&r2=56318&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRState.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRState.h Thu Sep 18 18:09:54 2008
@@ -43,12 +43,25 @@
class GRStateManager;
class GRTransferFuncs;
+
+//===----------------------------------------------------------------------===//
+// GRStateTrait - Traits used by the Generic Data Map of a GRState.
+//===----------------------------------------------------------------------===//
+template <typename T> struct GRStatePartialTrait;
+
+template <typename T> struct GRStateTrait {
+ typedef typename T::data_type data_type;
+ static inline void* GDMIndex() { return &T::TagInt; }
+ static inline void* MakeVoidPtr(data_type D) { return (void*) D; }
+ static inline data_type MakeData(void* const* P) {
+ return P ? (data_type) *P : (data_type) 0;
+ }
+};
+
//===----------------------------------------------------------------------===//
// GRState- An ImmutableMap type Stmt*/Decl*/Symbols to RVals.
//===----------------------------------------------------------------------===//
-
-template<typename T> struct GRStateTrait;
/// GRState - This class encapsulates the actual data values for
/// for a "state" in our symbolic value tracking. It is intended to be
@@ -169,7 +182,13 @@
void print(std::ostream& Out, StoreManager& StoreMgr,
ConstraintManager& ConstraintMgr,
Printer **Beg = 0, Printer **End = 0,
- const char* nl = "\n", const char *sep = "") const;
+ const char* nl = "\n", const char *sep = "") const;
+
+ // Tags used for the Generic Data Map.
+ struct NullDerefTag {
+ static int TagInt;
+ typedef const RVal* data_type;
+ };
};
template<> struct GRTrait<GRState*> {
@@ -566,8 +585,7 @@
void printDOT(std::ostream& Out) const;
};
-
-
+
} // end clang namespace
#endif
Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=56318&r1=56317&r2=56318&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Thu Sep 18 18:09:54 2008
@@ -17,7 +17,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "llvm/ADT/StringExtras.h"
-#include <sstream>
+
using namespace clang;
bool QualType::isConstant(ASTContext& Ctx) const {
Modified: cfe/trunk/lib/Analysis/BasicValueFactory.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/BasicValueFactory.cpp?rev=56318&r1=56317&r2=56318&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/BasicValueFactory.cpp (original)
+++ cfe/trunk/lib/Analysis/BasicValueFactory.cpp Thu Sep 18 18:09:54 2008
@@ -247,3 +247,8 @@
return P->getValue();
}
+const RVal* BasicValueFactory::getPersistentRVal(RVal X) {
+ return &getPersistentRValWithData(X, 0).first;
+}
+
+
Modified: cfe/trunk/lib/Analysis/CheckNSError.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CheckNSError.cpp?rev=56318&r1=56317&r2=56318&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/CheckNSError.cpp (original)
+++ cfe/trunk/lib/Analysis/CheckNSError.cpp Thu Sep 18 18:09:54 2008
@@ -37,9 +37,16 @@
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 @@
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 @@
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);
+ }
+}
Modified: cfe/trunk/lib/Analysis/GRExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngine.cpp?rev=56318&r1=56317&r2=56318&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngine.cpp Thu Sep 18 18:09:54 2008
@@ -1010,10 +1010,15 @@
// "Assume" that the pointer is NULL.
bool isFeasibleNull = false;
- const GRState* StNull = Assume(St, LV, false, isFeasibleNull);
+ GRStateRef StNull = GRStateRef(Assume(St, LV, false, isFeasibleNull),
+ getStateManager());
if (isFeasibleNull) {
+ // Use the Generic Data Map to mark in the state what lval was null.
+ const RVal* PersistentLV = getBasicVals().getPersistentRVal(LV);
+ StNull = StNull.set<GRState::NullDerefTag>(PersistentLV);
+
// We don't use "MakeNode" here because the node will be a sink
// and we have no intention of processing it later.
Modified: cfe/trunk/lib/Analysis/GRState.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRState.cpp?rev=56318&r1=56317&r2=56318&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/GRState.cpp (original)
+++ cfe/trunk/lib/Analysis/GRState.cpp Thu Sep 18 18:09:54 2008
@@ -261,3 +261,9 @@
bool GRStateManager::isEqual(const GRState* state, Expr* Ex, uint64_t x) {
return isEqual(state, Ex, BasicVals.getValue(x, Ex->getType()));
}
+
+//===----------------------------------------------------------------------===//
+// Persistent values for indexing into the Generic Data Map.
+
+int GRState::NullDerefTag::TagInt = 0;
+
More information about the cfe-commits
mailing list