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, 30 insertions, 16 deletions
diff --git a/clang/Analysis/GRExprEngine.cpp b/clang/Analysis/GRExprEngine.cpp index 2b94b4fafa9..f05dd7acb13 100644 --- a/clang/Analysis/GRExprEngine.cpp +++ b/clang/Analysis/GRExprEngine.cpp @@ -507,11 +507,10 @@ void GRExprEngine::VisitCall(CallExpr* CE, NodeTy* Pred, // Check for undefined control-flow. - if (L.isUndef()) { - + if (L.isUndef() || isa<lval::ConcreteInt>(L)) { NodeTy* N = Builder->generateNode(CE, St, *DI); N->markAsSink(); - UndefBranches.insert(N); + BadCalls.insert(N); continue; } @@ -1591,7 +1590,8 @@ struct VISIBILITY_HIDDEN DOTGraphTraits<GRExprEngine::NodeTy*> : GraphPrintCheckerState->isUndefStore(N) || GraphPrintCheckerState->isUndefControlFlow(N) || GraphPrintCheckerState->isBadDivide(N) || - GraphPrintCheckerState->isUndefResult(N)) + GraphPrintCheckerState->isUndefResult(N) || + GraphPrintCheckerState->isBadCall(N)) return "color=\"red\",style=\"filled\""; if (GraphPrintCheckerState->isNoReturnCall(N)) @@ -1623,26 +1623,22 @@ struct VISIBILITY_HIDDEN DOTGraphTraits<GRExprEngine::NodeTy*> : L.getStmt()->printPretty(Out); - if (GraphPrintCheckerState->isImplicitNullDeref(N)) { + if (GraphPrintCheckerState->isImplicitNullDeref(N)) Out << "\\|Implicit-Null Dereference.\\l"; - } - else if (GraphPrintCheckerState->isExplicitNullDeref(N)) { + else if (GraphPrintCheckerState->isExplicitNullDeref(N)) Out << "\\|Explicit-Null Dereference.\\l"; - } - else if (GraphPrintCheckerState->isUndefDeref(N)) { + else if (GraphPrintCheckerState->isUndefDeref(N)) Out << "\\|Dereference of undefialied value.\\l"; - } - else if (GraphPrintCheckerState->isUndefStore(N)) { + else if (GraphPrintCheckerState->isUndefStore(N)) Out << "\\|Store to Undefined LVal."; - } - else if (GraphPrintCheckerState->isBadDivide(N)) { + else if (GraphPrintCheckerState->isBadDivide(N)) Out << "\\|Divide-by zero or undefined value."; - } - else if (GraphPrintCheckerState->isUndefResult(N)) { + else if (GraphPrintCheckerState->isUndefResult(N)) Out << "\\|Result of operation is undefined."; - } else if (GraphPrintCheckerState->isNoReturnCall(N)) Out << "\\|Call to function marked \"noreturn\"."; + else if (GraphPrintCheckerState->isBadCall(N)) + Out << "\\|Call to NULL/Undefined."; break; } diff --git a/clang/Analysis/GRSimpleVals.cpp b/clang/Analysis/GRSimpleVals.cpp index 366ffb70c66..d6c133f2dc2 100644 --- a/clang/Analysis/GRSimpleVals.cpp +++ b/clang/Analysis/GRSimpleVals.cpp @@ -101,6 +101,11 @@ unsigned RunGRSimpleVals(CFG& cfg, FunctionDecl& FD, ASTContext& Ctx, CheckerState->undef_results_begin(), CheckerState->undef_results_end(), "Result of operation is undefined."); + + EmitWarning(Diag, SrcMgr, + CheckerState->bad_calls_begin(), + CheckerState->bad_calls_end(), + "Call using a NULL or undefined function pointer value."); #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 b4751666b2a..cd8173ea0d9 100644 --- a/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -90,6 +90,7 @@ protected: 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> BadDividesTy; typedef llvm::SmallPtrSet<NodeTy*,2> NoReturnCallsTy; typedef llvm::SmallPtrSet<NodeTy*,2> UndefResultsTy; @@ -127,6 +128,10 @@ protected: /// by the result is not. Excludes divide-by-zero errors. UndefResultsTy UndefResults; + /// BadCalls - Nodes in the ExplodedGraph resulting from calls to function + /// pointers that are NULL (or other constants) or Undefined. + BadCallsTy BadCalls; + bool StateCleaned; public: @@ -194,6 +199,10 @@ public: return N->isSink() && UndefResults.count(const_cast<NodeTy*>(N)) != 0; } + bool isBadCall(const NodeTy* N) const { + return N->isSink() && BadCalls.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(); } @@ -209,6 +218,10 @@ public: typedef UndefResultsTy::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; + bad_calls_iterator bad_calls_begin() { return BadCalls.begin(); } + bad_calls_iterator bad_calls_end() { return BadCalls.end(); } /// ProcessStmt - Called by GRCoreEngine. Used to generate new successor /// nodes by processing the 'effects' of a block-level statement. |