[cfe-commits] r145985 - in /cfe/trunk: include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h lib/StaticAnalyzer/Core/ProgramState.cpp lib/StaticAnalyzer/Core/RegionStore.cpp lib/StaticAnalyzer/Core/SValBuilder.cpp lib/StaticAnalyzer/Core/SVals.cpp lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp lib/StaticAnalyzer/Core/Store.cpp lib/StaticAnalyzer/Core/SymbolManager.cpp test/Analysis/taint-tester.c

Anna Zaks ganna at apple.com
Tue Dec 6 15:12:28 PST 2011


Author: zaks
Date: Tue Dec  6 17:12:27 2011
New Revision: 145985

URL: http://llvm.org/viewvc/llvm-project?rev=145985&view=rev
Log:
[analyzer] Propagate taint through NonLoc to NonLoc casts.

 - Created a new SymExpr type - SymbolCast.
 - SymbolCast is created when we don't know how to simplify a NonLoc to
NonLoc casts.
 - A bit of code refactoring: introduced dispatchCast to have better
code reuse, remove a goto.
 - Updated the test case to showcase the new taint flow.

Modified:
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
    cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/SValBuilder.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/SVals.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/SymbolManager.cpp
    cfe/trunk/test/Analysis/taint-tester.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=145985&r1=145984&r2=145985&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h Tue Dec  6 17:12:27 2011
@@ -48,11 +48,13 @@
   /// The width of the scalar type used for array indices.
   const unsigned ArrayIndexWidth;
 
+  virtual SVal evalCastFromNonLoc(NonLoc val, QualType castTy) = 0;
+  virtual SVal evalCastFromLoc(Loc val, QualType castTy) = 0;
+
 public:
   // FIXME: Make these protected again once RegionStoreManager correctly
   // handles loads from different bound value types.
-  virtual SVal evalCastFromNonLoc(NonLoc val, QualType castTy) = 0;
-  virtual SVal evalCastFromLoc(Loc val, QualType castTy) = 0;
+  virtual SVal dispatchCast(SVal val, QualType castTy) = 0;
 
 public:
   SValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context,
@@ -243,6 +245,9 @@
   NonLoc makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
                     const SymExpr *rhs, QualType type);
 
+  /// \brief Create a NonLoc value for cast.
+  NonLoc makeNonLoc(const SymExpr *operand, QualType fromTy, QualType toTy);
+
   nonloc::ConcreteInt makeTruthVal(bool b, QualType type) {
     return nonloc::ConcreteInt(BasicVals.getTruthValue(b, type));
   }

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h?rev=145985&r1=145984&r2=145985&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h Tue Dec  6 17:12:27 2011
@@ -299,6 +299,7 @@
   }
 };
 
+/// \brief Value representing integer constant.
 class ConcreteInt : public NonLoc {
 public:
   explicit ConcreteInt(const llvm::APSInt& V) : NonLoc(ConcreteIntKind, &V) {}

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h?rev=145985&r1=145984&r2=145985&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h Tue Dec  6 17:12:27 2011
@@ -48,7 +48,7 @@
               MetadataKind,
               BEGIN_SYMBOLS = RegionValueKind,
               END_SYMBOLS = MetadataKind,
-              SymIntKind, SymSymKind };
+              SymIntKind, SymSymKind, CastSymbolKind };
 private:
   Kind K;
 
@@ -276,6 +276,42 @@
   }
 };
 
+/// \brief Represents a cast expression.
+class SymbolCast : public SymExpr {
+  const SymExpr *Operand;
+  /// Type of the operand.
+  QualType FromTy;
+  /// The type of the result.
+  QualType ToTy;
+
+public:
+  SymbolCast(const SymExpr *In, QualType From, QualType To) :
+    SymExpr(CastSymbolKind), Operand(In), FromTy(From), ToTy(To) { }
+
+  QualType getType(ASTContext &C) const { return ToTy; }
+
+  const SymExpr *getOperand() const { return Operand; };
+
+  void dumpToStream(raw_ostream &os) const;
+
+  static void Profile(llvm::FoldingSetNodeID& ID,
+                      const SymExpr *In, QualType From, QualType To) {
+    ID.AddInteger((unsigned) CastSymbolKind);
+    ID.AddPointer(In);
+    ID.Add(From);
+    ID.Add(To);
+  }
+
+  void Profile(llvm::FoldingSetNodeID& ID) {
+    Profile(ID, Operand, FromTy, ToTy);
+  }
+
+  // Implement isa<T> support.
+  static inline bool classof(const SymExpr *SE) {
+    return SE->getKind() == CastSymbolKind;
+  }
+};
+
 /// SymIntExpr - Represents symbolic expression like 'x' + 3.
 class SymIntExpr : public SymExpr {
   const SymExpr *LHS;
@@ -408,6 +444,9 @@
                                           QualType T, unsigned VisitCount,
                                           const void *SymbolTag = 0);
 
+  const SymbolCast* getCastSymbol(const SymExpr *Operand,
+                                  QualType From, QualType To);
+
   const SymIntExpr *getSymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
                                   const llvm::APSInt& rhs, QualType t);
 

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp?rev=145985&r1=145984&r2=145985&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp Tue Dec  6 17:12:27 2011
@@ -560,6 +560,8 @@
     case SymExpr::ExtentKind:
     case SymExpr::MetadataKind:
       break;
+    case SymExpr::CastSymbolKind:
+      return scan(cast<SymbolCast>(sym)->getOperand());
     case SymExpr::SymIntKind:
       return scan(cast<SymIntExpr>(sym)->getLHS());
     case SymExpr::SymSymKind: {
@@ -672,10 +674,15 @@
   if (!Sym)
     return false;
 
+  // TODO: Can we use symbol_iterator (like removeDeadBindingsWorker) here?
+
   // Check taint on derived symbols.
   if (const SymbolDerived *SD = dyn_cast<SymbolDerived>(Sym))
     return isTainted(SD->getParentSymbol(), Kind);
 
+  if (const SymbolCast *SC = dyn_cast<SymbolCast>(Sym))
+    return (isTainted(SC->getOperand(), Kind));
+
   if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(Sym))
     return isTainted(SIE->getLHS(), Kind);
 

Modified: cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp?rev=145985&r1=145984&r2=145985&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp Tue Dec  6 17:12:27 2011
@@ -1720,7 +1720,7 @@
   if (const MemRegion *R = V.getAsRegion())
     AddToWorkList(R);
 
-    // Update the set of live symbols.
+  // Update the set of live symbols.
   for (SVal::symbol_iterator SI=V.symbol_begin(), SE=V.symbol_end();
        SI!=SE;++SI)
     SymReaper.markLive(*SI);

Modified: cfe/trunk/lib/StaticAnalyzer/Core/SValBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/SValBuilder.cpp?rev=145985&r1=145984&r2=145985&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/SValBuilder.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/SValBuilder.cpp Tue Dec  6 17:12:27 2011
@@ -56,6 +56,12 @@
   return nonloc::SymbolVal(SymMgr.getSymSymExpr(lhs, op, rhs, type));
 }
 
+NonLoc SValBuilder::makeNonLoc(const SymExpr *operand,
+                               QualType fromTy, QualType toTy) {
+  assert(operand);
+  assert(!Loc::isLocType(toTy));
+  return nonloc::SymbolVal(SymMgr.getCastSymbol(operand, fromTy, toTy));
+}
 
 SVal SValBuilder::convertToArrayIndex(SVal val) {
   if (val.isUnknownOrUndef())
@@ -220,21 +226,7 @@
   if (!castTy->isVariableArrayType() && !originalTy->isVariableArrayType())
     if (Context.hasSameUnqualifiedType(castTy, originalTy))
       return val;
-
-  // Check for casts to real or complex numbers.  We don't handle these at all
-  // right now.
-  if (castTy->isFloatingType() || castTy->isAnyComplexType())
-    return UnknownVal();
   
-  // Check for casts from integers to integers.
-  if (castTy->isIntegerType() && originalTy->isIntegerType()) {
-    if (isa<Loc>(val))
-      // This can be a cast to ObjC property of type int.
-      return evalCastFromLoc(cast<Loc>(val), castTy);
-    else
-      return evalCastFromNonLoc(cast<NonLoc>(val), castTy);
-  }
-
   // Check for casts from pointers to integers.
   if (castTy->isIntegerType() && Loc::isLocType(originalTy))
     return evalCastFromLoc(cast<Loc>(val), castTy);
@@ -249,7 +241,7 @@
       }
       return LV->getLoc();
     }
-    goto DispatchCast;
+    return dispatchCast(val, castTy);
   }
 
   // Just pass through function and block pointers.
@@ -323,8 +315,9 @@
     return R ? SVal(loc::MemRegionVal(R)) : UnknownVal();
   }
 
-DispatchCast:
-  // All other cases.
-  return isa<Loc>(val) ? evalCastFromLoc(cast<Loc>(val), castTy)
-                       : evalCastFromNonLoc(cast<NonLoc>(val), castTy);
+  // Check for casts from integers to integers.
+  if (castTy->isIntegerType() && originalTy->isIntegerType())
+    return dispatchCast(val, castTy);
+
+  return dispatchCast(val, castTy);
 }

Modified: cfe/trunk/lib/StaticAnalyzer/Core/SVals.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/SVals.cpp?rev=145985&r1=145984&r2=145985&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/SVals.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/SVals.cpp Tue Dec  6 17:12:27 2011
@@ -91,6 +91,7 @@
   return 0;
 }
 
+// TODO: The next 3 functions have to be simplified.
 /// getAsSymbol - If this Sval wraps a symbol return that SymbolRef.
 ///  Otherwise return 0.
 // FIXME: should we consider SymbolRef wrapped in CodeTextRegion?
@@ -168,6 +169,10 @@
   const SymExpr *SE = itr.back();
   itr.pop_back();
 
+  if (const SymbolCast *SC = dyn_cast<SymbolCast>(SE)) {
+    itr.push_back(SC->getOperand());
+    return;
+  }
   if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SE)) {
     itr.push_back(SIE->getLHS());
     return;

Modified: cfe/trunk/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp?rev=145985&r1=145984&r2=145985&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp Tue Dec  6 17:12:27 2011
@@ -20,6 +20,7 @@
 namespace {
 class SimpleSValBuilder : public SValBuilder {
 protected:
+  virtual SVal dispatchCast(SVal val, QualType castTy);
   virtual SVal evalCastFromNonLoc(NonLoc val, QualType castTy);
   virtual SVal evalCastFromLoc(Loc val, QualType castTy);
 
@@ -57,6 +58,11 @@
 // Transfer function for Casts.
 //===----------------------------------------------------------------------===//
 
+SVal SimpleSValBuilder::dispatchCast(SVal val, QualType castTy) {
+  return isa<Loc>(val) ? evalCastFromLoc(cast<Loc>(val), castTy)
+                       : evalCastFromNonLoc(cast<NonLoc>(val), castTy);
+}
+
 SVal SimpleSValBuilder::evalCastFromNonLoc(NonLoc val, QualType castTy) {
 
   bool isLocType = Loc::isLocType(castTy);
@@ -86,6 +92,8 @@
     if (T->isIntegerType() && castTy->isIntegerType())
       return val;
 
+    if (!isLocType)
+      return makeNonLoc(se, T, castTy);
     return UnknownVal();
   }
 

Modified: cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp?rev=145985&r1=145984&r2=145985&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp Tue Dec  6 17:12:27 2011
@@ -212,7 +212,7 @@
 SVal StoreManager::CastRetrievedVal(SVal V, const TypedValueRegion *R,
                                     QualType castTy, bool performTestOnly) {
   
-  if (castTy.isNull())
+  if (castTy.isNull() || V.isUnknownOrUndef())
     return V;
   
   ASTContext &Ctx = svalBuilder.getContext();
@@ -227,12 +227,8 @@
     return V;
   }
   
-  if (const Loc *L = dyn_cast<Loc>(&V))
-    return svalBuilder.evalCastFromLoc(*L, castTy);
-  else if (const NonLoc *NL = dyn_cast<NonLoc>(&V))
-    return svalBuilder.evalCastFromNonLoc(*NL, castTy);
-  
-  return V;
+  assert(isa<Loc>(&V) || isa<NonLoc>(&V));
+  return svalBuilder.dispatchCast(V, castTy);
 }
 
 SVal StoreManager::getLValueFieldOrIvar(const Decl *D, SVal Base) {

Modified: cfe/trunk/lib/StaticAnalyzer/Core/SymbolManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/SymbolManager.cpp?rev=145985&r1=145984&r2=145985&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/SymbolManager.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/SymbolManager.cpp Tue Dec  6 17:12:27 2011
@@ -66,6 +66,12 @@
   os << ')';
 }
 
+void SymbolCast::dumpToStream(raw_ostream &os) const {
+  os << '(' << ToTy.getAsString() << ") (";
+  Operand->dumpToStream(os);
+  os << ')';
+}
+
 void SymbolConjured::dumpToStream(raw_ostream &os) const {
   os << "conj_$" << getSymbolID() << '{' << T.getAsString() << '}';
 }
@@ -174,6 +180,22 @@
   return cast<SymbolMetadata>(SD);
 }
 
+const SymbolCast*
+SymbolManager::getCastSymbol(const SymExpr *Op,
+                             QualType From, QualType To) {
+  llvm::FoldingSetNodeID ID;
+  SymbolCast::Profile(ID, Op, From, To);
+  void *InsertPos;
+  SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
+  if (!data) {
+    data = (SymbolCast*) BPAlloc.Allocate<SymbolCast>();
+    new (data) SymbolCast(Op, From, To);
+    DataSet.InsertNode(data, InsertPos);
+  }
+
+  return cast<SymbolCast>(data);
+}
+
 const SymIntExpr *SymbolManager::getSymIntExpr(const SymExpr *lhs,
                                                BinaryOperator::Opcode op,
                                                const llvm::APSInt& v,

Modified: cfe/trunk/test/Analysis/taint-tester.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/taint-tester.c?rev=145985&r1=145984&r2=145985&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/taint-tester.c (original)
+++ cfe/trunk/test/Analysis/taint-tester.c Tue Dec  6 17:12:27 2011
@@ -12,4 +12,12 @@
   scanf("%d", &n);
   addr += n;// expected-warning {{tainted}}
   *addr = n; // expected-warning 2 {{tainted}}
+
+  double tdiv = n / 30; // expected-warning 3 {{tainted}}
+  char *loc_cast = (char *) n; // expected-warning {{tainted}}
+  char tinc = tdiv++; // expected-warning {{tainted}}
+  int tincdec = (char)tinc--; // expected-warning 2 {{tainted}}
+  int tprtarithmetic1 = *(addr+1);
+
+
 }





More information about the cfe-commits mailing list