diff options
author | Ted Kremenek <kremenek@apple.com> | 2008-12-08 22:47:34 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2008-12-08 22:47:34 +0000 |
commit | 8f7afdd21e20036f6236e297d2841abcadf86f96 (patch) | |
tree | 0f6c2455b7188bb4f86ecaa1d5376e0989ef6ef2 /clang | |
parent | e598370ae9638f198d718d9dab724d64a7f37718 (diff) | |
download | bcm5719-llvm-8f7afdd21e20036f6236e297d2841abcadf86f96.tar.gz bcm5719-llvm-8f7afdd21e20036f6236e297d2841abcadf86f96.zip |
Add checking for zero-sized VLAs.
llvm-svn: 60726
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/Analysis/PathSensitive/GRExprEngine.h | 72 | ||||
-rw-r--r-- | clang/lib/Analysis/GRExprEngine.cpp | 30 | ||||
-rw-r--r-- | clang/lib/Analysis/GRExprEngineInternalChecks.cpp | 30 |
3 files changed, 91 insertions, 41 deletions
diff --git a/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h b/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h index 6b9dc036795..80165c5686a 100644 --- a/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -94,74 +94,70 @@ protected: 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 @@ protected: /// 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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(); } diff --git a/clang/lib/Analysis/GRExprEngine.cpp b/clang/lib/Analysis/GRExprEngine.cpp index 8a32bfe9524..fb520675734 100644 --- a/clang/lib/Analysis/GRExprEngine.cpp +++ b/clang/lib/Analysis/GRExprEngine.cpp @@ -1773,8 +1773,7 @@ void GRExprEngine::VisitDeclStmt(DeclStmt* DS, NodeTy* Pred, NodeSet& Dst) { 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 @@ void GRExprEngine::VisitDeclStmt(DeclStmt* DS, NodeTy* Pred, NodeSet& Dst) { } 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); } diff --git a/clang/lib/Analysis/GRExprEngineInternalChecks.cpp b/clang/lib/Analysis/GRExprEngineInternalChecks.cpp index be7282314d0..8b484ab10c0 100644 --- a/clang/lib/Analysis/GRExprEngineInternalChecks.cpp +++ b/clang/lib/Analysis/GRExprEngineInternalChecks.cpp @@ -163,7 +163,7 @@ public: "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 @@ public: 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 @@ void GRExprEngine::RegisterInternalChecks() { Register(new BadMsgExprArg()); Register(new BadReceiver()); Register(new OutOfBoundMemoryAccess()); + Register(new ZeroSizeVLA()); AddCheck(new CheckAttrNonNull(), Stmt::CallExprClass); } |