]> granicus.if.org Git - clang/commitdiff
Added transfer function support for checking for divide-by-zero errors.
authorTed Kremenek <kremenek@apple.com>
Mon, 25 Feb 2008 17:51:31 +0000 (17:51 +0000)
committerTed Kremenek <kremenek@apple.com>
Mon, 25 Feb 2008 17:51:31 +0000 (17:51 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@47547 91177308-0d34-0410-b5e6-96231b3b80d8

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

index 2931d2aa6d84f58be4baf86194fbf0a05097014b..74fadcc9e36fbd25295e01db157e943cff0ebcec 100644 (file)
@@ -850,6 +850,33 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
 
       BinaryOperator::Opcode Op = B->getOpcode();
       
+      if (Op == BinaryOperator::Div) { // Check for divide-by-zero.
+        
+        // First, "assume" that the denominator is 0.
+        
+        bool isFeasible = false;
+        StateTy ZeroSt = Assume(St, RightV, false, isFeasible);
+        
+        if (isFeasible) {
+          NodeTy* DivZeroNode = Builder->generateNode(B, ZeroSt, N2);
+          
+          if (DivZeroNode) {
+            DivZeroNode->markAsSink();
+            DivZeroes.insert(DivZeroNode);
+          }
+        }
+        
+        // Second, "assume" that the denominator cannot be 0.
+        
+        isFeasible = false;
+        St = Assume(St, RightV, true, isFeasible);
+        
+        if (!isFeasible)
+          continue;
+        
+        // Fall-through.  The logic below processes the divide.
+      }
+      
       if (Op <= BinaryOperator::Or) {
         
         // Process non-assignements except commas or short-circuited
@@ -964,8 +991,35 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
           RightV = EvalCast(RightV, CTy);
           
           // Evaluate operands and promote to result type.
+
+          if (Op == BinaryOperator::Div) { // Check for divide-by-zero.
+                        
+            // First, "assume" that the denominator is 0.
+            
+            bool isFeasible = false;
+            StateTy ZeroSt = Assume(St, RightV, false, isFeasible);
+            
+            if (isFeasible) {
+              NodeTy* DivZeroNode = Builder->generateNode(B, ZeroSt, N2);
+              
+              if (DivZeroNode) {
+                DivZeroNode->markAsSink();
+                DivZeroes.insert(DivZeroNode);
+              }
+            }
+            
+            // Second, "assume" that the denominator cannot be 0.
+            
+            isFeasible = false;
+            St = Assume(St, RightV, true, isFeasible);
+            
+            if (!isFeasible)
+              continue;
+            
+            // Fall-through.  The logic below processes the divide.
+          }
+
           RVal Result = EvalCast(EvalBinOp(Op, V, RightV), B->getType());
-          
           St = SetRVal(SetRVal(St, B, Result), LeftLV, Result);
         }
       }
index 7fa5297daa2a32473ea4903e182d2c2d38eb8a59..bc8bec78e1a11b24511bf140cc6d6ee7d01a00e0 100644 (file)
@@ -114,18 +114,30 @@ protected:
   ///  taking a branch based on an uninitialized value.
   typedef llvm::SmallPtrSet<NodeTy*,5> UninitBranchesTy;
   UninitBranchesTy UninitBranches;
+
+  typedef llvm::SmallPtrSet<NodeTy*,5> UninitStoresTy;
+  typedef llvm::SmallPtrSet<NodeTy*,5> BadDerefTy;
+  typedef llvm::SmallPtrSet<NodeTy*,5> DivZerosTy;
   
   /// UninitStores - Sinks in the ExplodedGraph that result from
   ///  making a store to an uninitialized lvalue.
-  typedef llvm::SmallPtrSet<NodeTy*,5> UninitStoresTy;
   UninitStoresTy UninitStores;
   
   /// ImplicitNullDeref - Nodes in the ExplodedGraph that result from
-  ///  taking a dereference on a symbolic pointer that may be NULL.
-  typedef llvm::SmallPtrSet<NodeTy*,5> BadDerefTy;
+  ///  taking a dereference on a symbolic pointer that MAY be NULL.
   BadDerefTy ImplicitNullDeref;
+    
+  /// ExplicitNullDeref - Nodes in the ExplodedGraph that result from
+  ///  taking a dereference on a symbolic pointer that MUST be NULL.
   BadDerefTy ExplicitNullDeref;
+  
+  /// UnitDeref - Nodes in the ExplodedGraph that result from
+  ///  taking a dereference on an uninitialized value.
   BadDerefTy UninitDeref;
+
+  /// DivZeroes - Nodes in the ExplodedGraph that result from evaluating
+  ///  a divide-by-zero.
+  DivZerosTy DivZeroes;
   
   bool StateCleaned;