From 2ded35a576e3899553ea0ccfcbf5cbdb3d8cf664 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Fri, 29 Feb 2008 23:53:11 +0000 Subject: [PATCH] Added extra check for calls to functions where we pass undefined values as arguments. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@47778 91177308-0d34-0410-b5e6-96231b3b80d8 --- Analysis/GRExprEngine.cpp | 28 ++++++++++++++++--- Analysis/GRSimpleVals.cpp | 5 ++++ .../Analysis/PathSensitive/GRExprEngine.h | 13 +++++++++ 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/Analysis/GRExprEngine.cpp b/Analysis/GRExprEngine.cpp index f05dd7acb1..29330da7eb 100644 --- a/Analysis/GRExprEngine.cpp +++ b/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(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 : 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 : 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/Analysis/GRSimpleVals.cpp b/Analysis/GRSimpleVals.cpp index d6c133f2dc..a2b6c95d2f 100644 --- a/Analysis/GRSimpleVals.cpp +++ b/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/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h index cd8173ea0d..73fd513191 100644 --- a/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -91,6 +91,7 @@ protected: typedef llvm::SmallPtrSet UndefStoresTy; typedef llvm::SmallPtrSet BadDerefTy; typedef llvm::SmallPtrSet BadCallsTy; + typedef llvm::SmallPtrSet UndefArgsTy; typedef llvm::SmallPtrSet BadDividesTy; typedef llvm::SmallPtrSet NoReturnCallsTy; typedef llvm::SmallPtrSet 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(N)) != 0; } + bool isUndefArg(const NodeTy* N) const { + return N->isSink() && UndefArgs.count(const_cast(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); -- 2.40.0