[clang] 2fb3bec - [analyzer] Fix crash for array-delete of UnknownVal values.

Tomasz Kamiński via cfe-commits cfe-commits at lists.llvm.org
Wed Nov 9 06:17:41 PST 2022


Author: Tomasz Kamiński
Date: 2022-11-09T15:06:46+01:00
New Revision: 2fb3bec932ede7704724abb71e8270e0b4c201f6

URL: https://github.com/llvm/llvm-project/commit/2fb3bec932ede7704724abb71e8270e0b4c201f6
DIFF: https://github.com/llvm/llvm-project/commit/2fb3bec932ede7704724abb71e8270e0b4c201f6.diff

LOG: [analyzer] Fix crash for array-delete of UnknownVal values.

We now skip the destruction of array elements for `delete[] p`,
if the value of `p` is UnknownVal and does not have corresponding region.
This eliminate the crash in `getDynamicElementCount` on that
region and matches the behavior for deleting the array of
non-constant range.

Reviewed By: isuckatcs

Differential Revision: https://reviews.llvm.org/D136671

Added: 
    

Modified: 
    clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp
    clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
    clang/test/Analysis/dtor-array.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp b/clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp
index db9698b4086e9..6a86536492cd3 100644
--- a/clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp
+++ b/clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp
@@ -44,6 +44,7 @@ DefinedOrUnknownSVal getDynamicElementCount(ProgramStateRef State,
                                             const MemRegion *MR,
                                             SValBuilder &SVB,
                                             QualType ElementTy) {
+  assert(MR != nullptr && "Not-null region expected");
   MR = MR->StripCasts();
 
   DefinedOrUnknownSVal Size = getDynamicExtent(State, MR, SVB);

diff  --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index a90e17fc496d2..4528dbc0cc36f 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1241,6 +1241,7 @@ ExprEngine::prepareStateForArrayDestruction(const ProgramStateRef State,
                                             const QualType &ElementTy,
                                             const LocationContext *LCtx,
                                             SVal *ElementCountVal) {
+  assert(Region != nullptr && "Not-null region expected");	
 
   QualType Ty = ElementTy.getDesugaredType(getContext());
   while (const auto *NTy = dyn_cast<ArrayType>(Ty))
@@ -1420,31 +1421,32 @@ void ExprEngine::ProcessDeleteDtor(const CFGDeleteDtor Dtor,
   const MemRegion *ArgR = ArgVal.getAsRegion();
 
   if (DE->isArrayForm()) {
-    SVal ElementCount;
-    std::tie(State, Idx) =
-        prepareStateForArrayDestruction(State, ArgR, DTy, LCtx, &ElementCount);
-
     CallOpts.IsArrayCtorOrDtor = true;
     // Yes, it may even be a multi-dimensional array.
     while (const auto *AT = getContext().getAsArrayType(DTy))
       DTy = AT->getElementType();
 
-    // If we're about to destruct a 0 length array, don't run any of the
-    // destructors.
-    if (ElementCount.isConstant() &&
-        ElementCount.getAsInteger()->getLimitedValue() == 0) {
+    if (ArgR) {
+      SVal ElementCount;
+      std::tie(State, Idx) = prepareStateForArrayDestruction(
+          State, ArgR, DTy, LCtx, &ElementCount);
 
-      static SimpleProgramPointTag PT(
-          "ExprEngine", "Skipping 0 length array delete destruction");
-      PostImplicitCall PP(getDtorDecl(DTy), DE->getBeginLoc(), LCtx, &PT);
-      NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
-      Bldr.generateNode(PP, Pred->getState(), Pred);
-      return;
-    }
+      // If we're about to destruct a 0 length array, don't run any of the
+      // destructors.
+      if (ElementCount.isConstant() &&
+          ElementCount.getAsInteger()->getLimitedValue() == 0) {
+
+        static SimpleProgramPointTag PT(
+            "ExprEngine", "Skipping 0 length array delete destruction");
+        PostImplicitCall PP(getDtorDecl(DTy), DE->getBeginLoc(), LCtx, &PT);
+        NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
+        Bldr.generateNode(PP, Pred->getState(), Pred);
+        return;
+      }
 
-    if (ArgR)
       ArgR = State->getLValue(DTy, svalBuilder.makeArrayIndex(Idx), ArgVal)
                  .getAsRegion();
+    }
   }
 
   NodeBuilder Bldr(Pred, Dst, getBuilderContext());

diff  --git a/clang/test/Analysis/dtor-array.cpp b/clang/test/Analysis/dtor-array.cpp
index ab0a939232173..84a34af922516 100644
--- a/clang/test/Analysis/dtor-array.cpp
+++ b/clang/test/Analysis/dtor-array.cpp
@@ -344,3 +344,36 @@ void nonConstantRegionExtent(){
   // region to a conjured symbol.
   clang_analyzer_eval(InlineDtor::dtorCalled == 0); // expected-warning {{TRUE}} expected-warning {{FALSE}}
 }
+
+namespace crash6 {
+
+struct NonTrivialItem {
+  ~NonTrivialItem();
+};
+
+struct WeirdVec {
+  void clear() {
+    delete[] data;
+    size = 0;
+  }
+  NonTrivialItem *data;
+  unsigned size;
+};
+
+void top(int j) {
+  WeirdVec *p = new WeirdVec;
+
+  p[j].size = 0;
+  delete[] p->data; // no-crash
+}
+
+template <typename T>
+T make_unknown() {
+  return reinterpret_cast<T>(static_cast<int>(0.404));
+}
+
+void directUnknownSymbol() {
+  delete[] make_unknown<NonTrivialItem*>(); // no-crash
+}
+
+}


        


More information about the cfe-commits mailing list