]> granicus.if.org Git - clang/commitdiff
Added extra check for calls to functions where we pass undefined values
authorTed Kremenek <kremenek@apple.com>
Fri, 29 Feb 2008 23:53:11 +0000 (23:53 +0000)
committerTed Kremenek <kremenek@apple.com>
Fri, 29 Feb 2008 23:53:11 +0000 (23:53 +0000)
as arguments.

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

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

index f05dd7acb13a31779f6f3ac0dece9be2607ba929..29330da7ebb6a6c7a0093463100074dda2413dfa 100644 (file)
@@ -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;
       }
index d6c133f2dc2b34cb709702ba11dcaf61415d4bc8..a2b6c95d2f50b2db6dc387f94016532ffc61e520 100644 (file)
@@ -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();
index cd8173ea0d927050d4e9a05232a3828703988fde..73fd5131919ce169b0dd250c241ceb0e6db7e5ca 100644 (file)
@@ -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);