]> granicus.if.org Git - vim/commitdiff
patch 8.1.0800: may use a lot of memory when a function refers itself v8.1.0800
authorBram Moolenaar <Bram@vim.org>
Wed, 23 Jan 2019 22:00:30 +0000 (23:00 +0100)
committerBram Moolenaar <Bram@vim.org>
Wed, 23 Jan 2019 22:00:30 +0000 (23:00 +0100)
Problem:    May use a lot of memory when a function creates a cyclic
            reference.
Solution:   After saving a funccal many times, invoke the garbage collector.
            (closes #3835)

src/userfunc.c
src/version.c

index 6887c2c5c6ea4b08f8e3a214ef91f88d67fdf6ba..66e07b1f41ea3c70bb0a1302841dba1f155ad296 100644 (file)
@@ -651,6 +651,7 @@ cleanup_function_call(funccall_T *fc)
        listitem_T      *li;
        int             todo;
        dictitem_T      *v;
+       static int      made_copy = 0;
 
        /* "fc" is still in use.  This can happen when returning "a:000",
         * assigning "l:" to a global variable or defining a closure.
@@ -673,6 +674,16 @@ cleanup_function_call(funccall_T *fc)
        /* Make a copy of the a:000 items, since we didn't do that above. */
        for (li = fc->l_varlist.lv_first; li != NULL; li = li->li_next)
            copy_tv(&li->li_tv, &li->li_tv);
+
+       if (++made_copy == 10000)
+       {
+           // We have made a lot of copies.  This can happen when
+           // repetitively calling a function that creates a reference to
+           // itself somehow.  Call the garbage collector here to avoid using
+           // too much memory.
+           made_copy = 0;
+           (void)garbage_collect(FALSE);
+       }
     }
 }
 
@@ -723,6 +734,8 @@ call_user_func(
     line_breakcheck();         /* check for CTRL-C hit */
 
     fc = (funccall_T *)alloc(sizeof(funccall_T));
+    if (fc == NULL)
+       return;
     fc->caller = current_funccal;
     current_funccal = fc;
     fc->func = fp;
index d5ea08645e5e8ba3b5cce061243c43cd32498149..b8b06307ddaa7b8836a280d3d4d01b7396e54a19 100644 (file)
@@ -791,6 +791,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    800,
 /**/
     799,
 /**/