[cfe-commits] r65003 - in /cfe/trunk: include/clang/Analysis/PathSensitive/GRExprEngine.h lib/Analysis/GRExprEngine.cpp lib/Analysis/GRExprEngineInternalChecks.cpp
Ted Kremenek
kremenek at apple.com
Wed Feb 18 20:06:25 PST 2009
Author: kremenek
Date: Wed Feb 18 22:06:22 2009
New Revision: 65003
URL: http://llvm.org/viewvc/llvm-project?rev=65003&view=rev
Log:
Implemented simple check in <rdar://problem/6600344>: When the receiver of a
message expression is nil and the return type is struct then the returned value
is undefined or potentially garbage.
Modified:
cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h
cfe/trunk/lib/Analysis/GRExprEngine.cpp
cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp
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=65003&r1=65002&r2=65003&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h Wed Feb 18 22:06:22 2009
@@ -94,6 +94,16 @@
typedef llvm::SmallPtrSet<NodeTy*,2> ErrorNodes;
typedef llvm::DenseMap<NodeTy*, Expr*> UndefArgsTy;
+ /// NilReceiverStructRetExplicit - Nodes in the ExplodedGraph that resulted
+ /// from [x ...] with 'x' definitely being nil and the result was a 'struct'
+ // (an undefined value).
+ ErrorNodes NilReceiverStructRetExplicit;
+
+ /// NilReceiverStructRetImplicit - Nodes in the ExplodedGraph that resulted
+ /// from [x ...] with 'x' possibly being nil and the result was a 'struct'
+ // (an undefined value).
+ ErrorNodes NilReceiverStructRetImplicit;
+
/// RetsStackAddr - Nodes in the ExplodedGraph that result from returning
/// the address of a stack variable.
ErrorNodes RetsStackAddr;
@@ -300,6 +310,16 @@
return ImplicitNullDeref.end();
}
+ typedef ErrorNodes::iterator nil_receiver_struct_ret_iterator;
+
+ nil_receiver_struct_ret_iterator nil_receiver_struct_ret_begin() {
+ return NilReceiverStructRetExplicit.begin();
+ }
+
+ nil_receiver_struct_ret_iterator nil_receiver_struct_ret_end() {
+ return NilReceiverStructRetExplicit.end();
+ }
+
typedef ErrorNodes::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/lib/Analysis/GRExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngine.cpp?rev=65003&r1=65002&r2=65003&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngine.cpp Wed Feb 18 22:06:22 2009
@@ -1514,8 +1514,7 @@
SVal L = GetSVal(state, Receiver);
- // Check for undefined control-flow or calls to NULL.
-
+ // Check for undefined control-flow.
if (L.isUndef()) {
NodeTy* N = Builder->generateNode(ME, state, Pred);
@@ -1527,6 +1526,33 @@
return;
}
+ // "Assume" that the receiver is not NULL.
+ bool isFeasibleNotNull = false;
+ Assume(state, L, true, isFeasibleNotNull);
+
+ // "Assume" that the receiver is NULL.
+ bool isFeasibleNull = false;
+ const GRState *StNull = Assume(state, L, false, isFeasibleNull);
+
+ if (isFeasibleNull) {
+ // Check if the receiver was nil and the return value a struct.
+ if (ME->getType()->isRecordType()) {
+ // The [0 ...] expressions will return garbage. Flag either an
+ // explicit or implicit error. Because of the structure of this
+ // function we currently do not bifurfacte the state graph at
+ // this point.
+ // FIXME: We should bifurcate and fill the returned struct with
+ // garbage.
+ if (NodeTy* N = Builder->generateNode(ME, StNull, Pred)) {
+ N->markAsSink();
+ if (isFeasibleNotNull)
+ NilReceiverStructRetImplicit.insert(N);
+ else
+ NilReceiverStructRetExplicit.insert(N);
+ }
+ }
+ }
+
// Check if the "raise" message was sent.
if (ME->getSelector() == RaiseSel)
RaisesException = true;
Modified: cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp?rev=65003&r1=65002&r2=65003&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp Wed Feb 18 22:06:22 2009
@@ -71,6 +71,34 @@
}
};
+class VISIBILITY_HIDDEN NilReceiverStructRet : public BugType {
+ GRExprEngine &Eng;
+public:
+ NilReceiverStructRet(GRExprEngine* eng) :
+ BugType("nil receiver with struct return type", "Logic Errors"),
+ Eng(*eng) {}
+
+ void FlushReports(BugReporter& BR) {
+ for (GRExprEngine::nil_receiver_struct_ret_iterator
+ I=Eng.nil_receiver_struct_ret_begin(),
+ E=Eng.nil_receiver_struct_ret_end(); I!=E; ++I) {
+
+ std::string sbuf;
+ llvm::raw_string_ostream os(sbuf);
+ PostStmt P = cast<PostStmt>((*I)->getLocation());
+ ObjCMessageExpr *ME = cast<ObjCMessageExpr>(P.getStmt());
+ os << "The receiver in the message expression is 'nil' and results in the"
+ " returned value (of type '"
+ << ME->getType().getAsString()
+ << "') to be garbage or otherwise undefined.";
+
+ RangedBugReport *R = new RangedBugReport(*this, os.str().c_str(), *I);
+ R->addRange(ME->getReceiver()->getSourceRange());
+ BR.EmitReport(R);
+ }
+ }
+};
+
class VISIBILITY_HIDDEN UndefinedDeref : public BuiltinBug {
public:
UndefinedDeref(GRExprEngine* eng)
@@ -142,7 +170,8 @@
for (GRExprEngine::UndefArgsTy::iterator I=Eng.msg_expr_undef_arg_begin(),
E = Eng.msg_expr_undef_arg_end(); I!=E; ++I) {
// Generate a report for this bug.
- RangedBugReport *report = new RangedBugReport(*this, desc.c_str(), I->first);
+ RangedBugReport *report = new RangedBugReport(*this, desc.c_str(),
+ I->first);
report->addRange(I->second->getSourceRange());
BR.EmitReport(report);
}
@@ -431,6 +460,7 @@
BR.Register(new BadReceiver(this));
BR.Register(new OutOfBoundMemoryAccess(this));
BR.Register(new BadSizeVLA(this));
+ BR.Register(new NilReceiverStructRet(this));
// The following checks do not need to have their associated BugTypes
// explicitly registered with the BugReporter. If they issue any BugReports,
More information about the cfe-commits
mailing list