]> granicus.if.org Git - clang/commitdiff
[analyzer] Fix inconsistency on when SValBuilder assumes that 2
authorAnna Zaks <ganna@apple.com>
Fri, 9 Dec 2011 03:34:02 +0000 (03:34 +0000)
committerAnna Zaks <ganna@apple.com>
Fri, 9 Dec 2011 03:34:02 +0000 (03:34 +0000)
types are equivalent.

+ A taint test which tests bitwise operations and which was
triggering an assertion due to presence of the integer to integer cast.

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

include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
lib/StaticAnalyzer/Core/SValBuilder.cpp
lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
test/Analysis/taint-tester.c

index bbc5b660d5292282c1626ab303271995a44f506a..fd29e45c3d1510abcb3ff818dfb29c88070e61bd 100644 (file)
@@ -68,6 +68,17 @@ public:
 
   virtual ~SValBuilder() {}
 
+  bool haveSameType(const SymExpr *Sym1, const SymExpr *Sym2) {
+    return haveSameType(Sym1->getType(Context), Sym2->getType(Context));
+  }
+
+  bool haveSameType(QualType Ty1, QualType Ty2) {
+    // FIXME: Remove the second disjunct when we support symbolic
+    // truncation/extension.
+    return (Context.getCanonicalType(Ty1) == Context.getCanonicalType(Ty2) ||
+            (Ty2->isIntegerType() && Ty2->isIntegerType()));
+  }
+
   SVal evalCast(SVal val, QualType castTy, QualType originalType);
   
   virtual SVal evalMinus(NonLoc val) = 0;
index ff0a85a5723c4b166fb8717e72121de6f2dfed2e..f381f1a5ad9b6da4a6637cfd3bad036a42ba6fc9 100644 (file)
@@ -37,7 +37,6 @@ DefinedOrUnknownSVal SValBuilder::makeZeroVal(QualType type) {
   return UnknownVal();
 }
 
-
 NonLoc SValBuilder::makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
                                 const llvm::APSInt& rhs, QualType type) {
   // The Environment ensures we always get a persistent APSInt in
@@ -51,7 +50,7 @@ NonLoc SValBuilder::makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
 NonLoc SValBuilder::makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
                                const SymExpr *rhs, QualType type) {
   assert(lhs && rhs);
-  assert(SymMgr.getType(lhs) == SymMgr.getType(rhs));
+  assert(haveSameType(lhs->getType(Context), rhs->getType(Context)) == true);
   assert(!Loc::isLocType(type));
   return nonloc::SymbolVal(SymMgr.getSymSymExpr(lhs, op, rhs, type));
 }
index 89d9dc0242974785a910e3e86c25c47d393b3175..a7b67fbe8a50b2ddd3abc56d2d88c546810e564e 100644 (file)
@@ -80,16 +80,14 @@ SVal SimpleSValBuilder::evalCastFromNonLoc(NonLoc val, QualType castTy) {
 
   if (const SymExpr *se = val.getAsSymbolicExpression()) {
     QualType T = Context.getCanonicalType(se->getType(Context));
-    if (T == Context.getCanonicalType(castTy))
-      return val;
-    
+    // If types are the same or both are integers, ignore the cast.
     // FIXME: Remove this hack when we support symbolic truncation/extension.
     // HACK: If both castTy and T are integers, ignore the cast.  This is
     // not a permanent solution.  Eventually we want to precisely handle
     // extension/truncation of symbolic integers.  This prevents us from losing
     // precision when we assign 'x = y' and 'y' is symbolic and x and y are
     // different integer types.
-    if (T->isIntegerType() && castTy->isIntegerType())
+   if (haveSameType(T, castTy))
       return val;
 
     if (!isLocType)
@@ -483,7 +481,7 @@ SVal SimpleSValBuilder::evalBinOpNN(const ProgramState *state,
         // Otherwise, make a SymbolVal out of the expression.
         return MakeSymIntVal(symIntExpr, op, rhsInt->getValue(), resultTy);
 
-      // LHS is a simple symbol.
+      // LHS is a simple symbol (not a symbolic expression).
       } else {
         nonloc::SymbolVal *slhs = cast<nonloc::SymbolVal>(&lhs);
         SymbolRef Sym = slhs->getSymbol();
index f1dd5d0f030c64b766a03ebcc7b6aaf2cf076669..8a82cd397ae42a1367e33b24322dbdefb884d4b1 100644 (file)
@@ -55,3 +55,18 @@ void taintTracking(int x) {
   int ty = xy.y; // FIXME: This should be tainted as well.
   char ntz = xy.z;// no warning
 }
+
+void BitwiseOp(int in, char inn) {
+  // Taint on bitwise operations, integer to integer cast.
+  int m;
+  int x = 0;
+  scanf("%d", &x);
+  int y = (in << (x << in)) * 5;// expected-warning 4 {{tainted}}
+  // The next line tests integer to integer cast.
+  int z = y & inn; // expected-warning 2 {{tainted}}
+  if (y == 5) // expected-warning 2 {{tainted}}
+    m = z | z;// expected-warning 4 {{tainted}}
+  else
+    m = inn;
+  int mm = m; // expected-warning   {{tainted}}
+}