[PATCH] D115932: [Analyzer] Create and handle SymbolCast for pointer to integral conversion

Gabor Marton via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Fri Dec 17 04:47:03 PST 2021


martong created this revision.
martong added reviewers: steakhal, NoQ, ASDenysPetrov.
Herald added subscribers: manas, gamesh411, dkrupp, donat.nagy, Szelethus, mikhail.ramalho, a.sidorin, rnkovacs, szepet, baloghadamsoftware, xazax.hun.
Herald added a reviewer: Szelethus.
martong requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Currently, pointer to integral type casts are not modeled properly in
the symbol tree.
Below

  void foo(int *p) {
    12 - (long)p;
  }

the resulting symbol for the BinOP is an IntSymExpr. LHS is `12` and the RHS is
`&SymRegion{reg_$0<int * p>}`.

Even though, the `SVal` that is created for `(long)p` is correctly an
`LocAsInteger`, we loose this information when we build up the symbol tree for
`12 - (long)p`. To preserve the cast, we have to create a new node in
the symbol tree that represents it: the `SymbolCast`. This
is what this patch does.

This reverts D115149 <https://reviews.llvm.org/D115149>, except the test cases.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D115932

Files:
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValVisitor.h
  clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
  clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp


Index: clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
+++ clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
@@ -1204,7 +1204,23 @@
       return SVB.makeSymbolVal(S);
     }
 
-    // TODO: Support SymbolCast.
+    SVal VisitSymbolCast(const SymbolCast *Cast) {
+      SVal Castee = Visit(Cast->getOperand());
+      const auto &Context = SVB.getContext();
+      QualType CastTy = Cast->getType();
+
+      // Cast a pointer to an integral type.
+      if (Castee.getAs<Loc>() && !Loc::isLocType(CastTy)) {
+        const unsigned BitWidth = Context.getIntWidth(CastTy);
+        if (Castee.getAsSymbol())
+          return SVB.makeLocAsInteger(Castee.castAs<Loc>(), BitWidth);
+        if (auto X = Castee.getAs<loc::ConcreteInt>())
+          return SVB.makeIntVal(X->getValue());
+        // FIXME other cases?
+      }
+
+      return Base::VisitSymbolCast(Cast);
+    }
 
     SVal VisitSymIntExpr(const SymIntExpr *S) {
       auto I = Cached.find(S);
Index: clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -412,6 +412,15 @@
   SymbolRef symLHS = LHS.getAsSymbol();
   SymbolRef symRHS = RHS.getAsSymbol();
 
+  // FIXME This should be done in getAsSymbol. But then getAsSymbol should be
+  // the member function of SValBuilder (?)
+  if (symRHS)
+    if (auto RLocAsInt = RHS.getAs<nonloc::LocAsInteger>()) {
+      auto FromTy = symRHS->getType();
+      auto ToTy = RLocAsInt->getType(this->Context);
+      symRHS = this->getSymbolManager().getCastSymbol(symRHS, FromTy, ToTy);
+    }
+
   // TODO: When the Max Complexity is reached, we should conjure a symbol
   // instead of generating an Unknown value and propagate the taint info to it.
   const unsigned MaxComp = AnOpts.MaxSymbolComplexity;
@@ -459,23 +468,14 @@
     return evalBinOpLN(state, op, *LV, rhs.castAs<NonLoc>(), type);
   }
 
-  if (const Optional<Loc> RV = rhs.getAs<Loc>()) {
-    const auto IsCommutative = [](BinaryOperatorKind Op) {
-      return Op == BO_Mul || Op == BO_Add || Op == BO_And || Op == BO_Xor ||
-             Op == BO_Or;
-    };
+  if (Optional<Loc> RV = rhs.getAs<Loc>()) {
+    // Support pointer arithmetic where the addend is on the left
+    // and the pointer on the right.
 
-    if (IsCommutative(op)) {
-      // Swap operands.
-      return evalBinOpLN(state, op, *RV, lhs.castAs<NonLoc>(), type);
-    }
+    assert(op == BO_Add);
 
-    // If the right operand is a concrete int location then we have nothing
-    // better but to treat it as a simple nonloc.
-    if (auto RV = rhs.getAs<loc::ConcreteInt>()) {
-      const nonloc::ConcreteInt RhsAsLoc = makeIntVal(RV->getValue());
-      return evalBinOpNN(state, op, lhs.castAs<NonLoc>(), RhsAsLoc, type);
-    }
+    // Commute the operands.
+    return evalBinOpLN(state, op, *RV, lhs.castAs<NonLoc>(), type);
   }
 
   return evalBinOpNN(state, op, lhs.castAs<NonLoc>(), rhs.castAs<NonLoc>(),
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValVisitor.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValVisitor.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValVisitor.h
@@ -141,6 +141,7 @@
   using SValVisitor<ImplClass, RetTy>::Visit;
   using SymExprVisitor<ImplClass, RetTy>::Visit;
   using MemRegionVisitor<ImplClass, RetTy>::Visit;
+  using Base = FullSValVisitor;
 };
 
 } // end namespace ento


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D115932.395095.patch
Type: text/x-patch
Size: 3687 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20211217/f9a265a1/attachment.bin>


More information about the cfe-commits mailing list