]> granicus.if.org Git - clang/commitdiff
Add checks for function calls via a function pointer that is NULL, Undefined,
authorTed Kremenek <kremenek@apple.com>
Fri, 29 Feb 2008 23:14:48 +0000 (23:14 +0000)
committerTed Kremenek <kremenek@apple.com>
Fri, 29 Feb 2008 23:14:48 +0000 (23:14 +0000)
or otherwise a constant integer value that doesn't evaluate to an address.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@47774 91177308-0d34-0410-b5e6-96231b3b80d8

Analysis/GRExprEngine.cpp
Analysis/GRSimpleVals.cpp
include/clang/Analysis/PathSensitive/GRExprEngine.h

index 2b94b4fafa9cb33ada703665a599d6b9e0926783..f05dd7acb13a31779f6f3ac0dece9be2607ba929 100644 (file)
@@ -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;
       }
index 366ffb70c6636faa5f28d8bc49ffa3448b41fcfc..d6c133f2dc2b34cb709702ba11dcaf61415d4bc8 100644 (file)
@@ -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();
index b4751666b2aa1a2e78986e977e297dc41506442f..cd8173ea0d927050d4e9a05232a3828703988fde 100644 (file)
@@ -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.