[cfe-commits] r62395 - in /cfe/trunk: lib/Analysis/GRExprEngine.cpp test/Analysis/null-deref-ps.c

Ted Kremenek kremenek at apple.com
Fri Jan 16 17:54:17 PST 2009


Author: kremenek
Date: Fri Jan 16 19:54:16 2009
New Revision: 62395

URL: http://llvm.org/viewvc/llvm-project?rev=62395&view=rev
Log:
Fix analyzer crash found when scanning Wine sources where the analyzer used old logic to determine the value of a switch 'case' label.

Modified:
    cfe/trunk/lib/Analysis/GRExprEngine.cpp
    cfe/trunk/test/Analysis/null-deref-ps.c

Modified: cfe/trunk/lib/Analysis/GRExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngine.cpp?rev=62395&r1=62394&r2=62395&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngine.cpp Fri Jan 16 19:54:16 2009
@@ -698,10 +698,8 @@
 
 /// ProcessSwitch - Called by GRCoreEngine.  Used to generate successor
 ///  nodes by processing the 'effects' of a switch statement.
-void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) {
-  
-  typedef SwitchNodeBuilder::iterator iterator;
-  
+void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) {  
+  typedef SwitchNodeBuilder::iterator iterator;  
   const GRState* St = builder.getState();  
   Expr* CondE = builder.getCondition();
   SVal  CondV = GetSVal(St, CondE);
@@ -711,38 +709,32 @@
     UndefBranches.insert(N);
     return;
   }
-  
-  const GRState*  DefaultSt = St;
-  
-  // While most of this can be assumed (such as the signedness), having it
-  // just computed makes sure everything makes the same assumptions end-to-end.
-  
-  unsigned bits = getContext().getTypeSize(CondE->getType());
 
-  APSInt V1(bits, false);
-  APSInt V2 = V1;
+  const GRState*  DefaultSt = St;  
   bool DefaultFeasible = false;
   
   for (iterator I = builder.begin(), EI = builder.end(); I != EI; ++I) {
-
     CaseStmt* Case = cast<CaseStmt>(I.getCase());
-    
-    // Evaluate the case.
-    if (!Case->getLHS()->isIntegerConstantExpr(V1, getContext(), 0, true)) {
-      assert (false && "Case condition must evaluate to an integer constant.");
-      return;
-    }
-    
+
+    // Evaluate the LHS of the case value.
+    Expr::EvalResult V1;
+    bool b = Case->getLHS()->Evaluate(V1, getContext());    
+    
+    // Sanity checks.  These go away in Release builds.
+    assert(b && V1.Val.isInt() && !V1.HasSideEffects 
+             && "Case condition must evaluate to an integer constant.");
+    b = b; // silence unused variable warning    
+    assert(V1.Val.getInt().getBitWidth() == 
+           getContext().getTypeSize(CondE->getType()));
+           
     // Get the RHS of the case, if it exists.
+    Expr::EvalResult V2;
     
     if (Expr* E = Case->getRHS()) {
-      if (!E->isIntegerConstantExpr(V2, getContext(), 0, true)) {
-        assert (false &&
-                "Case condition (RHS) must evaluate to an integer constant.");
-        return ;
-      }
-      
-      assert (V1 <= V2);
+      b = E->Evaluate(V2, getContext());
+      assert(b && V2.Val.isInt() && !V2.HasSideEffects 
+             && "Case condition must evaluate to an integer constant.");
+      b = b; // silence unused variable warning
     }
     else
       V2 = V1;
@@ -752,12 +744,10 @@
     //  This should be easy once we have "ranges" for NonLVals.
         
     do {
-      nonloc::ConcreteInt CaseVal(getBasicVals().getValue(V1));
-      
+      nonloc::ConcreteInt CaseVal(getBasicVals().getValue(V1.Val.getInt()));      
       SVal Res = EvalBinOp(BinaryOperator::EQ, CondV, CaseVal);
       
-      // Now "assume" that the case matches.
-      
+      // Now "assume" that the case matches.      
       bool isFeasible = false;      
       const GRState* StNew = Assume(St, Res, true, isFeasible);
       
@@ -783,11 +773,11 @@
       }
 
       // Concretize the next value in the range.
-      if (V1 == V2)
+      if (V1.Val.getInt() == V2.Val.getInt())
         break;
       
-      ++V1;
-      assert (V1 <= V2);
+      ++V1.Val.getInt();
+      assert (V1.Val.getInt() <= V2.Val.getInt());
       
     } while (true);
   }

Modified: cfe/trunk/test/Analysis/null-deref-ps.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/null-deref-ps.c?rev=62395&r1=62394&r2=62395&view=diff

==============================================================================
--- cfe/trunk/test/Analysis/null-deref-ps.c (original)
+++ cfe/trunk/test/Analysis/null-deref-ps.c Fri Jan 16 19:54:16 2009
@@ -188,3 +188,26 @@
   }
 }
 
+// Test case for switch statements with weird case arms.
+typedef int     BOOL, *PBOOL, *LPBOOL;
+typedef long    LONG_PTR, *PLONG_PTR;
+typedef unsigned long ULONG_PTR, *PULONG_PTR;
+typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR;
+typedef LONG_PTR LRESULT;
+typedef struct _F12ITEM *HF12ITEM;
+
+void f12(HF12ITEM i, char *q) {
+  char *p = 0;
+  switch ((DWORD_PTR) i) {
+  case 0 ... 10:
+    p = q;
+    break;
+  case (DWORD_PTR) ((HF12ITEM) - 65535):
+    return;
+  default:
+    return;
+  }
+  
+  *p = 1; // no-warning
+}
+





More information about the cfe-commits mailing list