]> granicus.if.org Git - vim/commitdiff
patch 8.2.0704: Vim9: memory leak in disassemble test v8.2.0704
authorBram Moolenaar <Bram@vim.org>
Wed, 6 May 2020 20:18:17 +0000 (22:18 +0200)
committerBram Moolenaar <Bram@vim.org>
Wed, 6 May 2020 20:18:17 +0000 (22:18 +0200)
Problem:    Vim9: memory leak in disassemble test.
Solution:   Decrement refcount when creating funccal.

src/version.c
src/vim9execute.c

index b507c89b28d75cbb3160e6165d6fb5963d4a4d07..f22b37d4cb8060130dcdee50b59d7c5ad8aba1ba 100644 (file)
@@ -746,6 +746,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    704,
 /**/
     703,
 /**/
index 9651f5e9b2ea5c9e4594a3075f6d5dfed1088e6b..cc677b001344c8fcfc4711996c71e8042d5d1f6c 100644 (file)
@@ -270,7 +270,7 @@ handle_closure_in_use(ectx_T *ectx, int free_arguments)
            int refcount = tv->vval.v_partial->pt_refcount;
            int i;
 
-           // A Reference in a local variables doesn't count, its get
+           // A Reference in a local variables doesn't count, it gets
            // unreferenced on return.
            for (i = 0; i < dfunc->df_varcount; ++i)
            {
@@ -323,6 +323,32 @@ handle_closure_in_use(ectx_T *ectx, int free_arguments)
        for (idx = 0; idx < dfunc->df_varcount; ++idx)
        {
            tv = STACK_TV(ectx->ec_frame_idx + STACK_FRAME_SIZE + idx);
+
+           // Do not copy a partial created for a local function.
+           // TODO: this won't work if the closure actually uses it.  But when
+           // keeping it it gets complicated: it will create a reference cycle
+           // inside the partial, thus needs special handling for garbage
+           // collection.
+           if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL)
+           {
+               int i;
+               typval_T *ctv;
+
+               for (i = 0; i < dfunc->df_closure_count; ++i)
+               {
+                   ctv = STACK_TV(ectx->ec_frame_idx + STACK_FRAME_SIZE
+                                                    + dfunc->df_varcount + i);
+                   if (tv->vval.v_partial == ctv->vval.v_partial)
+                       break;
+               }
+               if (i < dfunc->df_closure_count)
+               {
+                   (stack + argcount + STACK_FRAME_SIZE + idx)->v_type =
+                                                                  VAR_UNKNOWN;
+                   continue;
+               }
+           }
+
            *(stack + argcount + STACK_FRAME_SIZE + idx) = *tv;
            tv->v_type = VAR_UNKNOWN;
        }