[cfe-commits] r144932 - in /cfe/trunk: include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h lib/StaticAnalyzer/Core/ExprEngineC.cpp lib/StaticAnalyzer/Core/SValBuilder.cpp lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp test/Analysis/taint-generic.c

Anna Zaks ganna at apple.com
Thu Nov 17 15:07:28 PST 2011


Author: zaks
Date: Thu Nov 17 17:07:28 2011
New Revision: 144932

URL: http://llvm.org/viewvc/llvm-project?rev=144932&view=rev
Log:
[analyzer] Do not conjure a symbol when we need to propagate taint.

When the solver and SValBuilder cannot reason about symbolic expressions (ex: (x+1)*y ), the analyzer conjures a new symbol with no ties to the past. This helps it to recover some path-sensitivity. However, this breaks the taint propagation.

With this commit, we are going to construct the expression even if we cannot reason about it later on if an operand is tainted.

Also added some comments and asserts.

Modified:
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/SValBuilder.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
    cfe/trunk/test/Analysis/taint-generic.c

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h?rev=144932&r1=144931&r2=144932&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h Thu Nov 17 17:07:28 2011
@@ -72,19 +72,33 @@
 
   virtual SVal evalComplement(NonLoc val) = 0;
 
+  /// Create a new value which represents a binary expression with two non
+  /// location operands.
   virtual SVal evalBinOpNN(const ProgramState *state, BinaryOperator::Opcode op,
                            NonLoc lhs, NonLoc rhs, QualType resultTy) = 0;
 
+  /// Create a new value which represents a binary expression with two memory
+  /// location operands.
   virtual SVal evalBinOpLL(const ProgramState *state, BinaryOperator::Opcode op,
                            Loc lhs, Loc rhs, QualType resultTy) = 0;
 
+  /// Create a new value which represents a binary expression with a memory
+  /// location and non location operands. For example, this would be used to
+  /// evaluate a pointer arithmetic operation.
   virtual SVal evalBinOpLN(const ProgramState *state, BinaryOperator::Opcode op,
                            Loc lhs, NonLoc rhs, QualType resultTy) = 0;
 
-  /// getKnownValue - evaluates a given SVal. If the SVal has only one possible
-  ///  (integer) value, that value is returned. Otherwise, returns NULL.
+  /// Evaluates a given SVal. If the SVal has only one possible (integer) value,
+  /// that value is returned. Otherwise, returns NULL.
   virtual const llvm::APSInt *getKnownValue(const ProgramState *state, SVal val) = 0;
   
+  /// Handles generation of the value in case the builder is not smart enough to
+  /// handle the given binary expression. Depending on the state, decides to
+  /// either keep the expression or forget the history and generate an
+  /// UnknownVal.
+  SVal generateUnknownVal(const ProgramState *state, BinaryOperator::Opcode op,
+                          NonLoc lhs, NonLoc rhs, QualType resultTy);
+
   SVal evalBinOp(const ProgramState *state, BinaryOperator::Opcode op,
                  SVal lhs, SVal rhs, QualType type);
   

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp?rev=144932&r1=144931&r2=144932&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp Thu Nov 17 17:07:28 2011
@@ -361,7 +361,8 @@
       // UnknownVal.
       if ((InitVal.isUnknown() ||
            !getConstraintManager().canReasonAbout(InitVal)) &&
-          !VD->getType()->isReferenceType()) {
+          !VD->getType()->isReferenceType() &&
+          !Pred->getState()->isTainted(InitVal)) {
         InitVal = svalBuilder.getConjuredSymbolVal(NULL, InitEx,
                                  currentBuilderContext->getCurrentBlockCount());
       }

Modified: cfe/trunk/lib/StaticAnalyzer/Core/SValBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/SValBuilder.cpp?rev=144932&r1=144931&r2=144932&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/SValBuilder.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/SValBuilder.cpp Thu Nov 17 17:07:28 2011
@@ -43,12 +43,14 @@
   // The Environment ensures we always get a persistent APSInt in
   // BasicValueFactory, so we don't need to get the APSInt from
   // BasicValueFactory again.
+  assert(lhs);
   assert(!Loc::isLocType(type));
   return nonloc::SymExprVal(SymMgr.getSymIntExpr(lhs, op, rhs, type));
 }
 
 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(!Loc::isLocType(type));
   return nonloc::SymExprVal(SymMgr.getSymSymExpr(lhs, op, rhs, type));
@@ -162,6 +164,29 @@
 
 //===----------------------------------------------------------------------===//
 
+SVal SValBuilder::generateUnknownVal(const ProgramState *State,
+                                     BinaryOperator::Opcode Op,
+                                     NonLoc LHS, NonLoc RHS,
+                                     QualType ResultTy) {
+  // If operands are tainted, create a symbol to ensure that we propagate taint.
+  if (State->isTainted(RHS) || State->isTainted(LHS)) {
+    const SymExpr *symLHS;
+    const SymExpr *symRHS;
+
+    if (const nonloc::ConcreteInt *rInt = dyn_cast<nonloc::ConcreteInt>(&RHS)) {
+      symLHS = LHS.getAsSymExpr();
+      return makeNonLoc(symLHS, Op, rInt->getValue(), ResultTy);
+    }
+    // TODO: Handle the case when lhs is ConcreteInt.
+
+    symLHS = LHS.getAsSymExpr();
+    symRHS = RHS.getAsSymExpr();
+    return makeNonLoc(symLHS, Op, symRHS, ResultTy);
+  }
+  return UnknownVal();
+}
+
+
 SVal SValBuilder::evalBinOp(const ProgramState *state, BinaryOperator::Opcode op,
                             SVal lhs, SVal rhs, QualType type) {
 

Modified: cfe/trunk/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp?rev=144932&r1=144931&r2=144932&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp Thu Nov 17 17:07:28 2011
@@ -298,7 +298,7 @@
   while (1) {
     switch (lhs.getSubKind()) {
     default:
-      return UnknownVal();
+      return generateUnknownVal(state, op, lhs, rhs, resultTy);
     case nonloc::LocAsIntegerKind: {
       Loc lhsL = cast<nonloc::LocAsInteger>(lhs).getLoc();
       switch (rhs.getSubKind()) {
@@ -321,7 +321,7 @@
               return makeTruthVal(true, resultTy);
             default:
               // This case also handles pointer arithmetic.
-              return UnknownVal();
+              return generateUnknownVal(state, op, lhs, rhs, resultTy);
           }
       }
     }
@@ -333,7 +333,7 @@
         dyn_cast<SymIntExpr>(selhs->getSymbolicExpression());
 
       if (!symIntExpr)
-        return UnknownVal();
+        return generateUnknownVal(state, op, lhs, rhs, resultTy);
 
       // Is this a logical not? (!x is represented as x == 0.)
       if (op == BO_EQ && rhs.isZeroConstant()) {
@@ -381,7 +381,7 @@
       // For now, only handle expressions whose RHS is a constant.
       const nonloc::ConcreteInt *rhsInt = dyn_cast<nonloc::ConcreteInt>(&rhs);
       if (!rhsInt)
-        return UnknownVal();
+        return generateUnknownVal(state, op, lhs, rhs, resultTy);
 
       // If both the LHS and the current expression are additive,
       // fold their constants.
@@ -467,9 +467,9 @@
             if (lhsValue == 0)
               // At this point lhs and rhs have been swapped.
               return rhs;
-            return UnknownVal();
+            return generateUnknownVal(state, op, lhs, rhs, resultTy);
           default:
-            return UnknownVal();
+            return generateUnknownVal(state, op, lhs, rhs, resultTy);
         }
       }
     }
@@ -529,7 +529,7 @@
                              resultTy);
       }
 
-      return UnknownVal();
+      return generateUnknownVal(state, op, lhs, rhs, resultTy);
     }
     }
   }

Modified: cfe/trunk/test/Analysis/taint-generic.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/taint-generic.c?rev=144932&r1=144931&r2=144932&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/taint-generic.c (original)
+++ cfe/trunk/test/Analysis/taint-generic.c Thu Nov 17 17:07:28 2011
@@ -12,3 +12,17 @@
   scanf("%d", &n);
   Buffer[n] = 1; // expected-warning {{Out of bound memory access }}
 }
+
+void bufferScanfArithmetic1(int x) {
+  int n;
+  scanf("%d", &n);
+  int m = (n - 3);
+  Buffer[m] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void bufferScanfArithmetic2(int x) {
+  int n;
+  scanf("%d", &n);
+  int m = (n + 3) * x;
+  Buffer[m] = 1; // expected-warning {{Out of bound memory access }}
+}





More information about the cfe-commits mailing list