• R/O
  • SSH

vim: 提交

Mirror of the Vim source from https://github.com/vim/vim


Commit MetaInfo

修訂fb69b43d73f3d45623b45761f418a14be27fe35d (tree)
時間2020-09-20 01:30:04
作者Bram Moolenaar <Bram@vim....>
CommiterBram Moolenaar

Log Message

patch 8.2.1712: Vim9: leaking memory when calling a lambda

Commit: https://github.com/vim/vim/commit/a05e524f3aa8eadc2dbd0ad8ff6db9407ac7ac7e
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Sep 19 18:19:19 2020 +0200

patch 8.2.1712: Vim9: leaking memory when calling a lambda
Problem: Vim9: leaking memory when calling a lambda.
Solution: Decrement function reference from ISN_DCALL.

Change Summary

差異

diff -r 543812d79fae -r fb69b43d73f3 src/proto/userfunc.pro
--- a/src/proto/userfunc.pro Sat Sep 19 15:30:04 2020 +0200
+++ b/src/proto/userfunc.pro Sat Sep 19 18:30:04 2020 +0200
@@ -12,6 +12,7 @@
1212 ufunc_T *find_func_even_dead(char_u *name, int is_global, cctx_T *cctx);
1313 ufunc_T *find_func(char_u *name, int is_global, cctx_T *cctx);
1414 int func_is_global(ufunc_T *ufunc);
15+int func_name_refcount(char_u *name);
1516 void copy_func(char_u *lambda, char_u *global);
1617 int call_user_func_check(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rettv, funcexe_T *funcexe, dict_T *selfdict);
1718 void save_funccal(funccal_entry_T *entry);
diff -r 543812d79fae -r fb69b43d73f3 src/userfunc.c
--- a/src/userfunc.c Sat Sep 19 15:30:04 2020 +0200
+++ b/src/userfunc.c Sat Sep 19 18:30:04 2020 +0200
@@ -1058,7 +1058,7 @@
10581058 * using function() does not count as a reference, because the function is
10591059 * looked up by name.
10601060 */
1061- static int
1061+ int
10621062 func_name_refcount(char_u *name)
10631063 {
10641064 return isdigit(*name) || *name == '<';
@@ -1176,8 +1176,9 @@
11761176 * Free a function and remove it from the list of functions. Does not free
11771177 * what a function contains, call func_clear() first.
11781178 * When "force" is TRUE we are exiting.
1179+ * Returns OK when the function was actually freed.
11791180 */
1180- static void
1181+ static int
11811182 func_free(ufunc_T *fp, int force)
11821183 {
11831184 // Only remove it when not done already, otherwise we would remove a newer
@@ -1191,7 +1192,9 @@
11911192 unlink_def_function(fp);
11921193 VIM_CLEAR(fp->uf_name_exp);
11931194 vim_free(fp);
1195+ return OK;
11941196 }
1197+ return FAIL;
11951198 }
11961199
11971200 /*
@@ -1890,9 +1893,13 @@
18901893 ++skipped;
18911894 else
18921895 {
1893- func_free(fp, FALSE);
1894- skipped = 0;
1895- break;
1896+ if (func_free(fp, FALSE) == OK)
1897+ {
1898+ skipped = 0;
1899+ break;
1900+ }
1901+ // did not actually free it
1902+ ++skipped;
18961903 }
18971904 }
18981905 }
diff -r 543812d79fae -r fb69b43d73f3 src/version.c
--- a/src/version.c Sat Sep 19 15:30:04 2020 +0200
+++ b/src/version.c Sat Sep 19 18:30:04 2020 +0200
@@ -751,6 +751,8 @@
751751 static int included_patches[] =
752752 { /* Add new patch number below this line */
753753 /**/
754+ 1712,
755+/**/
754756 1711,
755757 /**/
756758 1710,
diff -r 543812d79fae -r fb69b43d73f3 src/vim9compile.c
--- a/src/vim9compile.c Sat Sep 19 15:30:04 2020 +0200
+++ b/src/vim9compile.c Sat Sep 19 18:30:04 2020 +0200
@@ -1452,7 +1452,7 @@
14521452 ufunc->uf_def_status != UF_NOT_COMPILED ? ISN_DCALL
14531453 : ISN_UCALL)) == NULL)
14541454 return FAIL;
1455- if (ufunc->uf_def_status != UF_NOT_COMPILED)
1455+ if (isn->isn_type == ISN_DCALL)
14561456 {
14571457 isn->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
14581458 isn->isn_arg.dfunc.cdf_argcount = argcount;
@@ -2634,8 +2634,8 @@
26342634 clear_tv(&rettv);
26352635 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
26362636
2637- // The function will have one line: "return {expr}".
2638- // Compile it into instructions.
2637+ // The function will have one line: "return {expr}". Compile it into
2638+ // instructions so that we get any errors right now.
26392639 compile_def_function(ufunc, TRUE, cctx);
26402640
26412641 // compile the arguments
@@ -7285,7 +7285,19 @@
72857285 {
72867286 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
72877287 + isn->isn_arg.funcref.fr_func;
7288- func_ptr_unref(dfunc->df_ufunc);
7288+
7289+ if (func_name_refcount(dfunc->df_ufunc->uf_name))
7290+ func_ptr_unref(dfunc->df_ufunc);
7291+ }
7292+ break;
7293+
7294+ case ISN_DCALL:
7295+ {
7296+ dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
7297+ + isn->isn_arg.dfunc.cdf_idx;
7298+
7299+ if (func_name_refcount(dfunc->df_ufunc->uf_name))
7300+ func_ptr_unref(dfunc->df_ufunc);
72897301 }
72907302 break;
72917303
@@ -7333,7 +7345,6 @@
73337345 case ISN_COMPARESPECIAL:
73347346 case ISN_COMPARESTRING:
73357347 case ISN_CONCAT:
7336- case ISN_DCALL:
73377348 case ISN_DROP:
73387349 case ISN_ECHO:
73397350 case ISN_ECHOERR:
Show on old repository browser