[cfe-commits] r60726 - in /cfe/trunk: include/clang/Analysis/PathSensitive/GRExprEngine.h lib/Analysis/GRExprEngine.cpp lib/Analysis/GRExprEngineInternalChecks.cpp
Ted Kremenek
kremenek at apple.com
Mon Dec 8 14:47:34 PST 2008
Author: kremenek
Date: Mon Dec 8 16:47:34 2008
New Revision: 60726
URL: http://llvm.org/viewvc/llvm-project?rev=60726&view=rev
Log:
Add checking for zero-sized VLAs.
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=60726&r1=60725&r2=60726&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h Mon Dec 8 16:47:34 2008
@@ -94,74 +94,70 @@
llvm::OwningPtr<GRSimpleAPICheck> BatchAuditor;
public:
- typedef llvm::SmallPtrSet<NodeTy*,2> UndefBranchesTy;
- typedef llvm::SmallPtrSet<NodeTy*,2> UndefStoresTy;
- typedef llvm::SmallPtrSet<NodeTy*,2> BadDerefTy;
- typedef llvm::SmallPtrSet<NodeTy*,2> BadCallsTy;
- typedef llvm::SmallPtrSet<NodeTy*,2> UndefReceiversTy;
+ typedef llvm::SmallPtrSet<NodeTy*,2> ErrorNodes;
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> RetsStackAddrTy;
- typedef llvm::SmallPtrSet<NodeTy*,2> RetsUndefTy;
- typedef llvm::SmallPtrSet<NodeTy*,2> OutOfBoundMemAccessesTy;
-protected:
-
/// RetsStackAddr - Nodes in the ExplodedGraph that result from returning
/// the address of a stack variable.
- RetsStackAddrTy RetsStackAddr;
+ ErrorNodes RetsStackAddr;
/// RetsUndef - Nodes in the ExplodedGraph that result from returning
/// an undefined value.
- RetsUndefTy RetsUndef;
+ ErrorNodes RetsUndef;
/// UndefBranches - Nodes in the ExplodedGraph that result from
/// taking a branch based on an undefined value.
- UndefBranchesTy UndefBranches;
+ ErrorNodes UndefBranches;
/// UndefStores - Sinks in the ExplodedGraph that result from
/// making a store to an undefined lvalue.
- UndefStoresTy UndefStores;
+ ErrorNodes UndefStores;
/// NoReturnCalls - Sinks in the ExplodedGraph that result from
// calling a function with the attribute "noreturn".
- NoReturnCallsTy NoReturnCalls;
+ ErrorNodes NoReturnCalls;
/// ImplicitNullDeref - Nodes in the ExplodedGraph that result from
/// taking a dereference on a symbolic pointer that MAY be NULL.
- BadDerefTy ImplicitNullDeref;
+ ErrorNodes ImplicitNullDeref;
/// ExplicitNullDeref - Nodes in the ExplodedGraph that result from
/// taking a dereference on a symbolic pointer that MUST be NULL.
- BadDerefTy ExplicitNullDeref;
+ ErrorNodes ExplicitNullDeref;
/// UnitDeref - Nodes in the ExplodedGraph that result from
/// taking a dereference on an undefined value.
- BadDerefTy UndefDeref;
+ ErrorNodes UndefDeref;
/// ImplicitBadDivides - Nodes in the ExplodedGraph that result from
/// evaluating a divide or modulo operation where the denominator
/// MAY be zero.
- BadDividesTy ImplicitBadDivides;
+ ErrorNodes ImplicitBadDivides;
/// ExplicitBadDivides - Nodes in the ExplodedGraph that result from
/// evaluating a divide or modulo operation where the denominator
/// MUST be zero or undefined.
- BadDividesTy ExplicitBadDivides;
+ ErrorNodes ExplicitBadDivides;
+
+ /// ImplicitZeroSizedVLA - Nodes in the ExplodedGraph that result from
+ /// constructing a zero-sized VLA where the size may be zero.
+ ErrorNodes ImplicitZeroSizedVLA;
+
+ /// ExplicitZeroSizedVLA - Nodes in the ExplodedGraph that result from
+ /// constructing a zero-sized VLA where the size must be zero.
+ ErrorNodes ExplicitZeroSizedVLA;
/// UndefResults - Nodes in the ExplodedGraph where the operands are defined
/// by the result is not. Excludes divide-by-zero errors.
- UndefResultsTy UndefResults;
+ ErrorNodes UndefResults;
/// BadCalls - Nodes in the ExplodedGraph resulting from calls to function
/// pointers that are NULL (or other constants) or Undefined.
- BadCallsTy BadCalls;
+ ErrorNodes BadCalls;
/// UndefReceiver - Nodes in the ExplodedGraph resulting from message
/// ObjC message expressions where the receiver is undefined (uninitialized).
- UndefReceiversTy UndefReceivers;
+ ErrorNodes UndefReceivers;
/// UndefArg - Nodes in the ExplodedGraph resulting from calls to functions
/// where a pass-by-value argument has an undefined value.
@@ -174,11 +170,11 @@
/// OutOfBoundMemAccesses - Nodes in the ExplodedGraph resulting from
/// out-of-bound memory accesses where the index MAY be out-of-bound.
- OutOfBoundMemAccessesTy ImplicitOOBMemAccesses;
+ ErrorNodes ImplicitOOBMemAccesses;
/// OutOfBoundMemAccesses - Nodes in the ExplodedGraph resulting from
/// out-of-bound memory accesses where the index MUST be out-of-bound.
- OutOfBoundMemAccessesTy ExplicitOOBMemAccesses;
+ ErrorNodes ExplicitOOBMemAccesses;
public:
GRExprEngine(CFG& cfg, Decl& CD, ASTContext& Ctx, LiveVariables& L,
@@ -298,19 +294,19 @@
return N->isSink() && UndefReceivers.count(const_cast<NodeTy*>(N)) != 0;
}
- typedef RetsStackAddrTy::iterator ret_stackaddr_iterator;
+ typedef ErrorNodes::iterator ret_stackaddr_iterator;
ret_stackaddr_iterator ret_stackaddr_begin() { return RetsStackAddr.begin(); }
ret_stackaddr_iterator ret_stackaddr_end() { return RetsStackAddr.end(); }
- typedef RetsUndefTy::iterator ret_undef_iterator;
+ typedef ErrorNodes::iterator ret_undef_iterator;
ret_undef_iterator ret_undef_begin() { return RetsUndef.begin(); }
ret_undef_iterator ret_undef_end() { return RetsUndef.end(); }
- typedef UndefBranchesTy::iterator undef_branch_iterator;
+ typedef ErrorNodes::iterator undef_branch_iterator;
undef_branch_iterator undef_branches_begin() { return UndefBranches.begin(); }
undef_branch_iterator undef_branches_end() { return UndefBranches.end(); }
- typedef BadDerefTy::iterator null_deref_iterator;
+ typedef ErrorNodes::iterator null_deref_iterator;
null_deref_iterator null_derefs_begin() { return ExplicitNullDeref.begin(); }
null_deref_iterator null_derefs_end() { return ExplicitNullDeref.end(); }
@@ -321,11 +317,11 @@
return ImplicitNullDeref.end();
}
- typedef BadDerefTy::iterator undef_deref_iterator;
+ typedef ErrorNodes::iterator undef_deref_iterator;
undef_deref_iterator undef_derefs_begin() { return UndefDeref.begin(); }
undef_deref_iterator undef_derefs_end() { return UndefDeref.end(); }
- typedef BadDividesTy::iterator bad_divide_iterator;
+ typedef ErrorNodes::iterator bad_divide_iterator;
bad_divide_iterator explicit_bad_divides_begin() {
return ExplicitBadDivides.begin();
@@ -343,11 +339,11 @@
return ImplicitBadDivides.end();
}
- typedef UndefResultsTy::iterator undef_result_iterator;
+ typedef ErrorNodes::iterator undef_result_iterator;
undef_result_iterator undef_results_begin() { return UndefResults.begin(); }
undef_result_iterator undef_results_end() { return UndefResults.end(); }
- typedef BadCallsTy::iterator bad_calls_iterator;
+ typedef ErrorNodes::iterator bad_calls_iterator;
bad_calls_iterator bad_calls_begin() { return BadCalls.begin(); }
bad_calls_iterator bad_calls_end() { return BadCalls.end(); }
@@ -362,7 +358,7 @@
return MsgExprUndefArgs.end();
}
- typedef UndefReceiversTy::iterator undef_receivers_iterator;
+ typedef ErrorNodes::iterator undef_receivers_iterator;
undef_receivers_iterator undef_receivers_begin() {
return UndefReceivers.begin();
@@ -372,7 +368,7 @@
return UndefReceivers.end();
}
- typedef OutOfBoundMemAccessesTy::iterator oob_memacc_iterator;
+ typedef ErrorNodes::iterator oob_memacc_iterator;
oob_memacc_iterator implicit_oob_memacc_begin() {
return ImplicitOOBMemAccesses.begin();
}
Modified: cfe/trunk/lib/Analysis/GRExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngine.cpp?rev=60726&r1=60725&r2=60726&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngine.cpp Mon Dec 8 16:47:34 2008
@@ -1773,8 +1773,7 @@
if (!D || !isa<VarDecl>(D))
return;
- const VarDecl* VD = dyn_cast<VarDecl>(D);
-
+ const VarDecl* VD = dyn_cast<VarDecl>(D);
Expr* InitEx = const_cast<Expr*>(VD->getInit());
// FIXME: static variables may have an initializer, but the second
@@ -1812,6 +1811,33 @@
}
else
St = StateMgr.BindDecl(St, VD, 0, Count);
+
+
+ // Check if 'VD' is a VLA and if so check if has a non-zero size.
+ QualType T = getContext().getCanonicalType(VD->getType());
+ if (VariableArrayType* VLA = dyn_cast<VariableArrayType>(T)) {
+ // FIXME: Handle multi-dimensional VLAs.
+
+ Expr* SE = VLA->getSizeExpr();
+ SVal Size = GetSVal(St, SE);
+
+ bool isFeasibleZero = false;
+ const GRState* ZeroSt = Assume(St, Size, false, isFeasibleZero);
+
+ bool isFeasibleNotZero = false;
+ St = Assume(St, Size, true, isFeasibleNotZero);
+
+ if (isFeasibleZero) {
+ if (NodeTy* N = Builder->generateNode(DS, ZeroSt, Pred)) {
+ N->markAsSink();
+ if (isFeasibleNotZero) ImplicitZeroSizedVLA.insert(N);
+ else ExplicitZeroSizedVLA.insert(N);
+ }
+ }
+
+ if (!isFeasibleNotZero)
+ continue;
+ }
MakeNode(Dst, DS, *I, St);
}
Modified: cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp?rev=60726&r1=60725&r2=60726&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp Mon Dec 8 16:47:34 2008
@@ -163,7 +163,7 @@
"Receiver in message expression is an uninitialized value.") {}
virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
- for (GRExprEngine::UndefReceiversTy::iterator I=Eng.undef_receivers_begin(),
+ for (GRExprEngine::ErrorNodes::iterator I=Eng.undef_receivers_begin(),
End = Eng.undef_receivers_end(); I!=End; ++I) {
// Generate a report for this bug.
@@ -331,6 +331,33 @@
Emit(BR, Eng.explicit_oob_memacc_begin(), Eng.explicit_oob_memacc_end());
}
};
+
+class VISIBILITY_HIDDEN ZeroSizeVLA : public BuiltinBug {
+
+public:
+ ZeroSizeVLA() : BuiltinBug("Zero-sized VLA",
+ "VLAs with zero-size are undefined.") {}
+
+ virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
+ for (GRExprEngine::ErrorNodes::iterator
+ I = Eng.ExplicitZeroSizedVLA.begin(),
+ E = Eng.ExplicitZeroSizedVLA.end(); I!=E; ++I) {
+
+ // Generate a report for this bug.
+ PostStmt PS = cast<PostStmt>((*I)->getLocation());
+ DeclStmt *DS = cast<DeclStmt>(PS.getStmt());
+ VarDecl* VD = cast<VarDecl>(*DS->decl_begin());
+ QualType T = Eng.getContext().getCanonicalType(VD->getType());
+ VariableArrayType* VT = cast<VariableArrayType>(T);
+
+ RangedBugReport report(*this, *I);
+ report.addRange(VT->getSizeExpr()->getSourceRange());
+
+ // Emit the warning.
+ BR.EmitWarning(report);
+ }
+ }
+};
//===----------------------------------------------------------------------===//
// __attribute__(nonnull) checking
@@ -403,5 +430,6 @@
Register(new BadMsgExprArg());
Register(new BadReceiver());
Register(new OutOfBoundMemoryAccess());
+ Register(new ZeroSizeVLA());
AddCheck(new CheckAttrNonNull(), Stmt::CallExprClass);
}
More information about the cfe-commits
mailing list