[PATCH] D136826: [clang][Interp] Make sure we free() allocated InitMaps

Timm Bäder via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Thu Oct 27 02:35:43 PDT 2022


tbaeder created this revision.
tbaeder added reviewers: aaron.ballman, erichkeane, tahonermann, shafik.
Herald added a project: All.
tbaeder requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

They get allocated when calling `initialize()` on a primitive array. And they get free'd when the array is fully initialized. However, when that never happens, they get leaked. Fix that by calling the destructor of global variables.

No test attached here, since the problem only exists when asan is used. However, the next patch I upload will test that `InitMap`s work.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D136826

Files:
  clang/lib/AST/Interp/Descriptor.cpp
  clang/lib/AST/Interp/InterpBlock.h
  clang/lib/AST/Interp/Pointer.cpp
  clang/lib/AST/Interp/Program.cpp
  clang/lib/AST/Interp/Program.h


Index: clang/lib/AST/Interp/Program.h
===================================================================
--- clang/lib/AST/Interp/Program.h
+++ clang/lib/AST/Interp/Program.h
@@ -47,6 +47,13 @@
     // here manually so they are properly freeing their resources.
     for (auto RecordPair : Records)
       RecordPair.second->~Record();
+
+    // Manually destroy all the blocks. They are almost all harmless,
+    // but primitive arrays might have an InitMap* heap allocated and
+    // that needs to be freed.
+    for (Global *G : Globals) {
+      G->block()->invokeDtor();
+    }
   }
 
   /// Marshals a native pointer to an ID for embedding in bytecode.
Index: clang/lib/AST/Interp/Program.cpp
===================================================================
--- clang/lib/AST/Interp/Program.cpp
+++ clang/lib/AST/Interp/Program.cpp
@@ -65,6 +65,7 @@
   unsigned Sz = Desc->getAllocSize();
   auto *G = new (Allocator, Sz) Global(Desc, /*isStatic=*/true,
                                        /*isExtern=*/false);
+  G->block()->invokeCtor();
   Globals.push_back(G);
 
   // Construct the string in storage.
Index: clang/lib/AST/Interp/Pointer.cpp
===================================================================
--- clang/lib/AST/Interp/Pointer.cpp
+++ clang/lib/AST/Interp/Pointer.cpp
@@ -146,7 +146,7 @@
   Descriptor *Desc = getFieldDesc();
   assert(Desc);
   if (Desc->isPrimitiveArray()) {
-    if (Pointee->IsStatic)
+    if (isStatic() && Base == 0)
       return true;
     // Primitive array field are stored in a bitset.
     InitMap *Map = getInitMap();
@@ -167,7 +167,11 @@
 
   assert(Desc);
   if (Desc->isArray()) {
-    if (Desc->isPrimitiveArray() && !Pointee->IsStatic) {
+    if (Desc->isPrimitiveArray()) {
+      // Primitive global arrays don't have an initmap.
+      if (isStatic() && Base == 0)
+        return;
+
       // Primitive array initializer.
       InitMap *&Map = getInitMap();
       if (Map == (InitMap *)-1)
Index: clang/lib/AST/Interp/InterpBlock.h
===================================================================
--- clang/lib/AST/Interp/InterpBlock.h
+++ clang/lib/AST/Interp/InterpBlock.h
@@ -100,6 +100,12 @@
                    /*isActive=*/true, Desc);
   }
 
+  // Invokes the Destructor.
+  void invokeDtor() {
+    if (Desc->DtorFn)
+      Desc->DtorFn(this, data(), Desc);
+  }
+
 protected:
   friend class Pointer;
   friend class DeadBlock;
Index: clang/lib/AST/Interp/Descriptor.cpp
===================================================================
--- clang/lib/AST/Interp/Descriptor.cpp
+++ clang/lib/AST/Interp/Descriptor.cpp
@@ -39,6 +39,11 @@
 
 template <typename T>
 static void dtorArrayTy(Block *, char *Ptr, Descriptor *D) {
+  InitMap *IM = *reinterpret_cast<InitMap **>(Ptr);
+  if (IM != (InitMap *)-1)
+    free(IM);
+
+  Ptr += sizeof(InitMap *);
   for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) {
     reinterpret_cast<T *>(Ptr)[I].~T();
   }
@@ -183,7 +188,7 @@
 }
 
 static BlockDtorFn getDtorArrayPrim(PrimType Type) {
-  COMPOSITE_TYPE_SWITCH(Type, return dtorArrayTy<T>, return nullptr);
+  TYPE_SWITCH(Type, return dtorArrayTy<T>);
 }
 
 static BlockMoveFn getMoveArrayPrim(PrimType Type) {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D136826.471087.patch
Type: text/x-patch
Size: 3203 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20221027/07e9b808/attachment-0001.bin>


More information about the cfe-commits mailing list