]> granicus.if.org Git - clang/commitdiff
Fix false positive null dereference by unifying code paths in GRSimpleVals for
authorTed Kremenek <kremenek@apple.com>
Mon, 4 May 2009 17:53:11 +0000 (17:53 +0000)
committerTed Kremenek <kremenek@apple.com>
Mon, 4 May 2009 17:53:11 +0000 (17:53 +0000)
'==' and '!=' (some code in the '!=' was not replicated in the '==' code,
causing some constraints to get lost).

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

lib/Analysis/GRSimpleVals.cpp
lib/Analysis/GRSimpleVals.h
test/Analysis/null-deref-ps.c

index 860013872e490e04f69134578bce6f9c1b128e15..3d1c76412cfd1b574ed6dc4fdf506c1879f9d823 100644 (file)
@@ -249,15 +249,11 @@ SVal GRSimpleVals::EvalBinOp(GRExprEngine& Eng, BinaryOperator::Opcode Op,
                              Loc L, Loc R) {
   
   switch (Op) {
-
     default:
-      return UnknownVal();
-      
+      return UnknownVal();      
     case BinaryOperator::EQ:
-      return EvalEQ(Eng, L, R);
-      
     case BinaryOperator::NE:
-      return EvalNE(Eng, L, R);      
+      return EvalEquality(Eng, L, R, Op == BinaryOperator::EQ);
   }
 }
 
@@ -286,14 +282,14 @@ SVal GRSimpleVals::EvalBinOp(GRExprEngine& Eng, BinaryOperator::Opcode Op,
 // FIXME: All this logic will be revamped when we have MemRegion::getLocation()
 // implemented.
 
-SVal GRSimpleVals::EvalEQ(GRExprEngine& Eng, Loc L, Loc R) {
+SVal GRSimpleVals::EvalEquality(GRExprEngine& Eng, Loc L, Loc R, bool isEqual) {
   
   BasicValueFactory& BasicVals = Eng.getBasicVals();
 
   switch (L.getSubKind()) {
 
     default:
-      assert(false && "EQ not implemented for this Loc.");
+      assert(false && "EQ/NE not implemented for this Loc.");
       return UnknownVal();
       
     case loc::ConcreteIntKind:
@@ -302,8 +298,21 @@ SVal GRSimpleVals::EvalEQ(GRExprEngine& Eng, Loc L, Loc R) {
         bool b = cast<loc::ConcreteInt>(L).getValue() ==
                  cast<loc::ConcreteInt>(R).getValue();
         
+        // Are we computing '!='?  Flip the result.
+        if (!isEqual)
+          b = !b;
+        
         return NonLoc::MakeIntTruthVal(BasicVals, b);
       }
+      else if (SymbolRef Sym = R.getAsSymbol()) {
+        const SymIntExpr * SE =
+        Eng.getSymbolManager().getSymIntExpr(Sym,
+                                             isEqual ? BinaryOperator::EQ
+                                                     : BinaryOperator::NE,
+                                             cast<loc::ConcreteInt>(L).getValue(),
+                                             Eng.getContext().IntTy);
+        return nonloc::SymExprVal(SE);
+      }
       
       break;
       
@@ -311,7 +320,9 @@ SVal GRSimpleVals::EvalEQ(GRExprEngine& Eng, Loc L, Loc R) {
       if (SymbolRef LSym = L.getAsLocSymbol()) {
         if (isa<loc::ConcreteInt>(R)) {
           const SymIntExpr *SE =
-            Eng.getSymbolManager().getSymIntExpr(LSym, BinaryOperator::EQ,
+            Eng.getSymbolManager().getSymIntExpr(LSym,
+                                           isEqual ? BinaryOperator::EQ
+                                                   : BinaryOperator::NE,
                                            cast<loc::ConcreteInt>(R).getValue(),
                                            Eng.getContext().IntTy);
         
@@ -323,58 +334,10 @@ SVal GRSimpleVals::EvalEQ(GRExprEngine& Eng, Loc L, Loc R) {
     // Fall-through.
       
     case loc::GotoLabelKind:
-      return NonLoc::MakeIntTruthVal(BasicVals, L == R);
-  }
-  
-  return NonLoc::MakeIntTruthVal(BasicVals, false);
-}
-
-SVal GRSimpleVals::EvalNE(GRExprEngine& Eng, Loc L, Loc R) {
-  
-  BasicValueFactory& BasicVals = Eng.getBasicVals();
-
-  switch (L.getSubKind()) {
-
-    default:
-      assert(false && "NE not implemented for this Loc.");
-      return UnknownVal();
-      
-    case loc::ConcreteIntKind:
-      
-      if (isa<loc::ConcreteInt>(R)) {
-        bool b = cast<loc::ConcreteInt>(L).getValue() !=
-                 cast<loc::ConcreteInt>(R).getValue();
-        
-        return NonLoc::MakeIntTruthVal(BasicVals, b);
-      }
-      else if (SymbolRef Sym = R.getAsSymbol()) {
-        const SymIntExpr * SE =
-          Eng.getSymbolManager().getSymIntExpr(Sym, BinaryOperator::NE,
-                                           cast<loc::ConcreteInt>(L).getValue(),
-                                             Eng.getContext().IntTy);
-        return nonloc::SymExprVal(SE);
-      }
-      
-      break;
-
-    case loc::MemRegionKind: {
-      if (SymbolRef LSym = L.getAsLocSymbol()) {
-        if (isa<loc::ConcreteInt>(R)) {
-          const SymIntExpr* SE =
-            Eng.getSymbolManager().getSymIntExpr(LSym, BinaryOperator::NE,
-                                          cast<loc::ConcreteInt>(R).getValue(),
-                                                 Eng.getContext().IntTy);
-          return nonloc::SymExprVal(SE);
-        }
-      }
-      // Fall through:
-    }
-      
-    case loc::GotoLabelKind:
-      return NonLoc::MakeIntTruthVal(BasicVals, L != R);
+      return NonLoc::MakeIntTruthVal(BasicVals, isEqual ? L == R : L != R);
   }
   
-  return NonLoc::MakeIntTruthVal(BasicVals, true);
+  return NonLoc::MakeIntTruthVal(BasicVals, isEqual ? false : true);
 }
 
 //===----------------------------------------------------------------------===//
index efe7c631ab2e001c99df186a58b0d2a704c83cf1..1258cbc1bf487962537710b8a0247065aa78e5c3 100644 (file)
@@ -77,10 +77,8 @@ public:
   
 protected:
   
-  // Equality operators for Locs.
-  
-  SVal EvalEQ(GRExprEngine& Engine, Loc L, Loc R);
-  SVal EvalNE(GRExprEngine& Engine, Loc L, Loc R);
+  // Equality (==, !=) operators for Locs.  
+  SVal EvalEquality(GRExprEngine& Engine, Loc L, Loc R, bool isEqual);
 };
   
 } // end clang namespace
index 7f1db8749c13f8ba003d6b034996ead7da555b73..09b9c2ffa3b754821293c1b414b43122e0805919 100644 (file)
@@ -139,9 +139,9 @@ int* f7c(int *x) {
   
   if (((void*)0) != x)
     return x;
-    
-  // THIS IS WRONG.  THIS NEEDS TO BE FIXED.
-  *p = 1; // expected-warning{{null}}
+
+  // If we reach here then 'p' is not null.
+  *p = 1; // no-warning
   return x;
 }