diff options
-rw-r--r-- | clang/Analysis/GRExprEngine.cpp | 28 | ||||
-rw-r--r-- | clang/Analysis/GRSimpleVals.cpp | 5 | ||||
-rw-r--r-- | clang/include/clang/Analysis/PathSensitive/GRExprEngine.h | 13 |
3 files changed, 42 insertions, 4 deletions
diff --git a/clang/Analysis/GRExprEngine.cpp b/clang/Analysis/GRExprEngine.cpp index f05dd7acb13..29330da7ebb 100644 --- a/clang/Analysis/GRExprEngine.cpp +++ b/clang/Analysis/GRExprEngine.cpp @@ -481,12 +481,27 @@ void GRExprEngine::VisitCall(CallExpr* CE, NodeTy* Pred, NodeSet DstTmp; Visit(*AI, Pred, DstTmp); + if (DstTmp.empty()) DstTmp.Add(Pred); + Expr* CurrentArg = *AI; ++AI; - for (NodeSet::iterator DI=DstTmp.begin(), DE=DstTmp.end(); DI != DE; ++DI) + for (NodeSet::iterator DI=DstTmp.begin(), DE=DstTmp.end(); DI != DE; ++DI) { + if (GetRVal((*DI)->getState(), CurrentArg).isUndef()) { + + NodeTy* N = Builder->generateNode(CE, (*DI)->getState(), *DI); + + if (N) { + N->markAsSink(); + UndefArgs.insert(N); + } + + continue; + } + VisitCall(CE, *DI, AI, AE, Dst); + } return; } @@ -509,8 +524,10 @@ void GRExprEngine::VisitCall(CallExpr* CE, NodeTy* Pred, if (L.isUndef() || isa<lval::ConcreteInt>(L)) { NodeTy* N = Builder->generateNode(CE, St, *DI); - N->markAsSink(); - BadCalls.insert(N); + if (N) { + N->markAsSink(); + BadCalls.insert(N); + } continue; } @@ -1591,7 +1608,8 @@ struct VISIBILITY_HIDDEN DOTGraphTraits<GRExprEngine::NodeTy*> : GraphPrintCheckerState->isUndefControlFlow(N) || GraphPrintCheckerState->isBadDivide(N) || GraphPrintCheckerState->isUndefResult(N) || - GraphPrintCheckerState->isBadCall(N)) + GraphPrintCheckerState->isBadCall(N) || + GraphPrintCheckerState->isUndefArg(N)) return "color=\"red\",style=\"filled\""; if (GraphPrintCheckerState->isNoReturnCall(N)) @@ -1639,6 +1657,8 @@ struct VISIBILITY_HIDDEN DOTGraphTraits<GRExprEngine::NodeTy*> : Out << "\\|Call to function marked \"noreturn\"."; else if (GraphPrintCheckerState->isBadCall(N)) Out << "\\|Call to NULL/Undefined."; + else if (GraphPrintCheckerState->isUndefArg(N)) + Out << "\\|Argument in call is undefined"; break; } diff --git a/clang/Analysis/GRSimpleVals.cpp b/clang/Analysis/GRSimpleVals.cpp index d6c133f2dc2..a2b6c95d2f5 100644 --- a/clang/Analysis/GRSimpleVals.cpp +++ b/clang/Analysis/GRSimpleVals.cpp @@ -106,6 +106,11 @@ unsigned RunGRSimpleVals(CFG& cfg, FunctionDecl& FD, ASTContext& Ctx, CheckerState->bad_calls_begin(), CheckerState->bad_calls_end(), "Call using a NULL or undefined function pointer value."); + + EmitWarning(Diag, SrcMgr, + CheckerState->undef_arg_begin(), + CheckerState->undef_arg_end(), + "Pass-by-value argument in function or message expression is undefined."); #ifndef NDEBUG if (Visualize) CheckerState->ViewGraph(); diff --git a/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h b/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h index cd8173ea0d9..73fd5131919 100644 --- a/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -91,6 +91,7 @@ protected: typedef llvm::SmallPtrSet<NodeTy*,2> UndefStoresTy; typedef llvm::SmallPtrSet<NodeTy*,2> BadDerefTy; typedef llvm::SmallPtrSet<NodeTy*,2> BadCallsTy; + typedef llvm::SmallPtrSet<NodeTy*,2> UndefArgsTy; typedef llvm::SmallPtrSet<NodeTy*,2> BadDividesTy; typedef llvm::SmallPtrSet<NodeTy*,2> NoReturnCallsTy; typedef llvm::SmallPtrSet<NodeTy*,2> UndefResultsTy; @@ -132,6 +133,10 @@ protected: /// pointers that are NULL (or other constants) or Undefined. BadCallsTy BadCalls; + /// UndefArg - Nodes in the ExplodedGraph resulting from calls to functions + /// where a pass-by-value argument has an undefined value. + UndefArgsTy UndefArgs; + bool StateCleaned; public: @@ -203,6 +208,10 @@ public: return N->isSink() && BadCalls.count(const_cast<NodeTy*>(N)) != 0; } + bool isUndefArg(const NodeTy* N) const { + return N->isSink() && UndefArgs.count(const_cast<NodeTy*>(N)) != 0; + } + typedef BadDerefTy::iterator null_deref_iterator; null_deref_iterator null_derefs_begin() { return ExplicitNullDeref.begin(); } null_deref_iterator null_derefs_end() { return ExplicitNullDeref.end(); } @@ -223,6 +232,10 @@ public: bad_calls_iterator bad_calls_begin() { return BadCalls.begin(); } bad_calls_iterator bad_calls_end() { return BadCalls.end(); } + typedef UndefArgsTy::iterator undef_arg_iterator; + undef_arg_iterator undef_arg_begin() { return UndefArgs.begin(); } + undef_arg_iterator undef_arg_end() { return UndefArgs.end(); } + /// ProcessStmt - Called by GRCoreEngine. Used to generate new successor /// nodes by processing the 'effects' of a block-level statement. void ProcessStmt(Stmt* S, StmtNodeBuilder& builder); |