[PATCH] D30489: [analyzer] catch out of bounds for VLA

Daniel Marjamäki via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Mon Apr 10 11:54:01 PDT 2017


danielmarjamaki updated this revision to Diff 94509.
danielmarjamaki added a comment.

This is just work in progress!!

With these changes Clang static analyzer will detect overflow in this sample code:

  void foo(int X) {
    char *Data = new char[X];
    Data[X] = 0; // <- error
    delete[] Data;
  }

I updated SimpleSValBuilder so evalEQ can calculate a SVal when both lhs and rhs are symbols. Source code that used to have problems:

  DefinedOrUnknownSVal extentMatchesSize = svalBuilder.evalEQ(
      State, Extent, SizeInBytes.castAs<DefinedOrUnknownSVal>());

Inputs: Extent is "extent_$3{SymRegion{conj_$1{char *}}}" and SizeInBytes is "reg_$0<int X>".

Before my quick fix the return SVal is "Unknown".
With my quick fix it will return a SVal "(extent_$3{SymRegion{conj_$1{char *}}}) == (reg_$0<int X>)".

I also made a simple fix for the ConstraintManager. If the state says X==Y then the ConstraintManager should be able to evaluate Y>=X. My evalUgly loops through the constraints and matches them manually.

Do you have some feedback? Do you think my SimpleSValBuilder approach is fine to commit if I polish it? It was just a quick hack so I guess it might make some tests fail etc.

About the ConstraintManager fix. Is it a good idea to handle simple SymSymExpr constraints? Or should this be handled by Z3 instead?


Repository:
  rL LLVM

https://reviews.llvm.org/D30489

Files:
  include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
  lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
  lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp
  lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp


Index: lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
===================================================================
--- lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
+++ lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
@@ -547,6 +547,13 @@
       if (const llvm::APSInt *RHSValue = getKnownValue(state, rhs))
         return MakeSymIntVal(Sym, op, *RHSValue, resultTy);
 
+      if (!state->isTainted(rhs) && !state->isTainted(lhs)) {
+        const SymExpr *lhse = lhs.getAsSymExpr();
+        const SymExpr *rhse = rhs.getAsSymExpr();
+        return nonloc::SymbolVal(
+            SymMgr.getSymSymExpr(lhse, op, rhse, resultTy));
+      }
+
       // Give up -- this is not a symbolic expression we can handle.
       return makeSymExprValNN(state, op, InputLHS, InputRHS, resultTy);
     }
Index: lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp
===================================================================
--- lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp
+++ lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp
@@ -53,6 +53,19 @@
 ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef State,
                                                    NonLoc Cond,
                                                    bool Assumption) {
+  if (1) {
+    Optional<nonloc::SymbolVal> SymVal = Cond.getAs<nonloc::SymbolVal>();
+    if (SymVal && SymVal->isExpression()) {
+      const SymExpr *SE = SymVal->getSymbol();
+      if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(SE)) {
+        if (SSE->getOpcode() == BO_GE) {
+          SymSymExpr SSE2(SSE->getRHS(), BO_EQ, SSE->getLHS(), SSE->getType());
+          if (State->getConstraintManager().uglyEval(&SSE2, State))
+            return Assumption ? State : nullptr;
+        }
+      }
+    }
+  }
 
   // We cannot reason about SymSymExprs, and can only reason about some
   // SymIntExprs.
Index: lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
===================================================================
--- lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
+++ lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
@@ -287,6 +287,8 @@
   RangeConstraintManager(SubEngine *SE, SValBuilder &SVB)
       : RangedConstraintManager(SE, SVB) {}
 
+  virtual bool uglyEval(const SymSymExpr *SSE, ProgramStateRef state);
+
   //===------------------------------------------------------------------===//
   // Implementation for interface from ConstraintManager.
   //===------------------------------------------------------------------===//
@@ -723,6 +725,25 @@
 // Pretty-printing.
 //===------------------------------------------------------------------------===/
 
+bool RangeConstraintManager::uglyEval(const SymSymExpr *SSE,
+                                      ProgramStateRef State) {
+  ConstraintRangeTy Ranges = State->get<ConstraintRange>();
+  for (ConstraintRangeTy::iterator I = Ranges.begin(), E = Ranges.end(); I != E;
+       ++I) {
+    SymbolRef SR = I.getKey();
+    if (const SymSymExpr *SSE2 = dyn_cast<SymSymExpr>(SR)) {
+      if (SSE->getOpcode() != SSE2->getOpcode())
+        continue;
+      if (SSE->getLHS() != SSE2->getLHS())
+        continue;
+      if (SSE->getRHS() != SSE2->getRHS())
+        continue;
+      return true;
+    }
+  }
+  return false;
+}
+
 void RangeConstraintManager::print(ProgramStateRef St, raw_ostream &Out,
                                    const char *nl, const char *sep) {
 
Index: include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
===================================================================
--- include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
+++ include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
@@ -63,9 +63,12 @@
 public:
   ConstraintManager() : NotifyAssumeClients(true) {}
 
+  virtual bool uglyEval(const SymSymExpr *SSE, ProgramStateRef state) {
+    return false;
+  }
+
   virtual ~ConstraintManager();
-  virtual ProgramStateRef assume(ProgramStateRef state,
-                                 DefinedSVal Cond,
+  virtual ProgramStateRef assume(ProgramStateRef state, DefinedSVal Cond,
                                  bool Assumption) = 0;
 
   typedef std::pair<ProgramStateRef, ProgramStateRef> ProgramStatePair;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D30489.94509.patch
Type: text/x-patch
Size: 4251 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170410/20c0108c/attachment-0001.bin>


More information about the cfe-commits mailing list