[cfe-commits] r48980 - in /cfe/trunk: include/clang/Analysis/PathSensitive/GRExprEngine.h lib/Analysis/GRExprEngine.cpp lib/Analysis/GRSimpleVals.cpp test/Analysis/stack-addr-ps.c
Ted Kremenek
kremenek at apple.com
Mon Mar 31 08:02:59 PDT 2008
Author: kremenek
Date: Mon Mar 31 10:02:58 2008
New Revision: 48980
URL: http://llvm.org/viewvc/llvm-project?rev=48980&view=rev
Log:
Added path-sensitive check for return statements that return the address
of a stack variable. This is the path-sensitive version of a check that
is already done during semantic analysis.
Added:
cfe/trunk/test/Analysis/stack-addr-ps.c
Modified:
cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h
cfe/trunk/lib/Analysis/GRExprEngine.cpp
cfe/trunk/lib/Analysis/GRSimpleVals.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=48980&r1=48979&r2=48980&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h Mon Mar 31 10:02:58 2008
@@ -86,8 +86,12 @@
typedef llvm::DenseMap<NodeTy*, Expr*> UndefArgsTy;
typedef llvm::SmallPtrSet<NodeTy*,2> BadDividesTy;
typedef llvm::SmallPtrSet<NodeTy*,2> NoReturnCallsTy;
- typedef llvm::SmallPtrSet<NodeTy*,2> UndefResultsTy;
+ typedef llvm::SmallPtrSet<NodeTy*,2> UndefResultsTy;
+ typedef llvm::SmallPtrSet<NodeTy*,2> RetsStackAddrTy;
+ /// RetsStackAddr - Nodes in the ExplodedGraph that result from returning
+ /// the address of a stack variable.
+ RetsStackAddrTy RetsStackAddr;
/// UndefBranches - Nodes in the ExplodedGraph that result from
/// taking a branch based on an undefined value.
@@ -179,6 +183,10 @@
/// in the ExplodedGraph.
ValueState* getInitialState();
+ bool isRetStackAddr(const NodeTy* N) const {
+ return N->isSink() && RetsStackAddr.count(const_cast<NodeTy*>(N)) != 0;
+ }
+
bool isUndefControlFlow(const NodeTy* N) const {
return N->isSink() && UndefBranches.count(const_cast<NodeTy*>(N)) != 0;
}
@@ -229,6 +237,10 @@
return N->isSink() && UndefReceivers.count(const_cast<NodeTy*>(N)) != 0;
}
+ typedef RetsStackAddrTy::iterator ret_stackaddr_iterator;
+ ret_stackaddr_iterator ret_stackaddr_begin() { return RetsStackAddr.begin(); }
+ ret_stackaddr_iterator ret_stackaddr_end() { return RetsStackAddr.end(); }
+
typedef UndefBranchesTy::iterator undef_branch_iterator;
undef_branch_iterator undef_branches_begin() { return UndefBranches.begin(); }
undef_branch_iterator undef_branches_end() { return UndefBranches.end(); }
@@ -476,6 +488,9 @@
/// VisitLogicalExpr - Transfer function logic for '&&', '||'
void VisitLogicalExpr(BinaryOperator* B, NodeTy* Pred, NodeSet& Dst);
+ /// VisitReturnStmt - Transfer function logic for return statements.
+ void VisitReturnStmt(ReturnStmt* R, NodeTy* Pred, NodeSet& Dst);
+
/// VisitSizeOfAlignOfTypeExpr - Transfer function for sizeof(type).
void VisitSizeOfAlignOfTypeExpr(SizeOfAlignOfTypeExpr* Ex, NodeTy* Pred,
NodeSet& Dst);
Modified: cfe/trunk/lib/Analysis/GRExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngine.cpp?rev=48980&r1=48979&r2=48980&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngine.cpp Mon Mar 31 10:02:58 2008
@@ -1190,6 +1190,50 @@
MakeNode(Dst, ME, Pred, St);
}
+void GRExprEngine::VisitReturnStmt(ReturnStmt* S, NodeTy* Pred, NodeSet& Dst) {
+
+ Expr* R = S->getRetValue();
+
+ if (!R) {
+ Dst.Add(Pred);
+ return;
+ }
+
+ QualType T = R->getType();
+
+ if (T->isPointerType() || T->isReferenceType()) {
+
+ // Check if any of the return values return the address of a stack variable.
+
+ NodeSet Tmp;
+ Visit(R, Pred, Tmp);
+
+ for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
+ RVal X = GetRVal((*I)->getState(), R);
+
+ if (isa<lval::DeclVal>(X)) {
+
+ if (cast<lval::DeclVal>(X).getDecl()->hasLocalStorage()) {
+
+ // Create a special node representing the v
+
+ NodeTy* RetStackNode = Builder->generateNode(S, GetState(*I), *I);
+
+ if (RetStackNode) {
+ RetStackNode->markAsSink();
+ RetsStackAddr.insert(RetStackNode);
+ }
+
+ continue;
+ }
+ }
+
+ Dst.Add(*I);
+ }
+ }
+ else
+ Visit(R, Pred, Dst);
+}
void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
GRExprEngine::NodeTy* Pred,
@@ -1625,14 +1669,8 @@
// that users can quickly query what was the state at the
// exit points of a function.
- case Stmt::ReturnStmtClass: {
- if (Expr* R = cast<ReturnStmt>(S)->getRetValue())
- Visit(R, Pred, Dst);
- else
- Dst.Add(Pred);
-
- break;
- }
+ case Stmt::ReturnStmtClass:
+ VisitReturnStmt(cast<ReturnStmt>(S), Pred, Dst); break;
case Stmt::UnaryOperatorClass: {
UnaryOperator* U = cast<UnaryOperator>(S);
Modified: cfe/trunk/lib/Analysis/GRSimpleVals.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRSimpleVals.cpp?rev=48980&r1=48979&r2=48980&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/GRSimpleVals.cpp (original)
+++ cfe/trunk/lib/Analysis/GRSimpleVals.cpp Mon Mar 31 10:02:58 2008
@@ -166,6 +166,11 @@
CheckerState->undef_receivers_begin(),
CheckerState->undef_receivers_end(),
"Receiver in message expression is an uninitialized value.");
+
+ EmitWarning(Diag, SrcMgr,
+ CheckerState->ret_stackaddr_begin(),
+ CheckerState->ret_stackaddr_end(),
+ "Address of stack-allocated variable returned.");
FoundationCheck.get()->ReportResults(Diag);
#ifndef NDEBUG
Added: cfe/trunk/test/Analysis/stack-addr-ps.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/stack-addr-ps.c?rev=48980&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/stack-addr-ps.c (added)
+++ cfe/trunk/test/Analysis/stack-addr-ps.c Mon Mar 31 10:02:58 2008
@@ -0,0 +1,21 @@
+// RUN: clang -grsimple -verify %s
+
+int* f1() {
+ int x = 0;
+ return &x; // expected-warning{{Address of stack-allocated variable returned.}} expected-warning{{address of stack memory associated with local variable 'x' returned}}
+}
+
+int* f2(int y) {
+ return &y; // expected-warning{{Address of stack-allocated variable returned.}} expected-warning{{address of stack memory associated with local variable 'y' returned}}
+}
+
+int* f3(int x, int *y) {
+ int w = 0;
+
+ if (x)
+ y = &w;
+
+ return y; // expected-warning{{Address of stack-allocated variable returned.}}
+}
+
+
More information about the cfe-commits
mailing list