Patch 8.2.1712

9 views
Skip to first unread message

Bram Moolenaar

unread,
Sep 19, 2020, 12:21:18 PM9/19/20
to vim...@googlegroups.com

Patch 8.2.1712
Problem: Vim9: leaking memory when calling a lambda.
Solution: Decrement function reference from ISN_DCALL.
Files: src/vim9compile.c, src/userfunc.c, src/proto/userfunc.pro


*** ../vim-8.2.1711/src/vim9compile.c 2020-09-19 15:16:46.395622457 +0200
--- src/vim9compile.c 2020-09-19 18:05:00.907313691 +0200
***************
*** 1452,1458 ****
ufunc->uf_def_status != UF_NOT_COMPILED ? ISN_DCALL
: ISN_UCALL)) == NULL)
return FAIL;
! if (ufunc->uf_def_status != UF_NOT_COMPILED)
{
isn->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
isn->isn_arg.dfunc.cdf_argcount = argcount;
--- 1452,1458 ----
ufunc->uf_def_status != UF_NOT_COMPILED ? ISN_DCALL
: ISN_UCALL)) == NULL)
return FAIL;
! if (isn->isn_type == ISN_DCALL)
{
isn->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
isn->isn_arg.dfunc.cdf_argcount = argcount;
***************
*** 2634,2641 ****
clear_tv(&rettv);
ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);

! // The function will have one line: "return {expr}".
! // Compile it into instructions.
compile_def_function(ufunc, TRUE, cctx);

// compile the arguments
--- 2634,2641 ----
clear_tv(&rettv);
ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);

! // The function will have one line: "return {expr}". Compile it into
! // instructions so that we get any errors right now.
compile_def_function(ufunc, TRUE, cctx);

// compile the arguments
***************
*** 7285,7291 ****
{
dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
+ isn->isn_arg.funcref.fr_func;
! func_ptr_unref(dfunc->df_ufunc);
}
break;

--- 7285,7303 ----
{
dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
+ isn->isn_arg.funcref.fr_func;
!
! if (func_name_refcount(dfunc->df_ufunc->uf_name))
! func_ptr_unref(dfunc->df_ufunc);
! }
! break;
!
! case ISN_DCALL:
! {
! dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
! + isn->isn_arg.dfunc.cdf_idx;
!
! if (func_name_refcount(dfunc->df_ufunc->uf_name))
! func_ptr_unref(dfunc->df_ufunc);
}
break;

***************
*** 7333,7339 ****
case ISN_COMPARESPECIAL:
case ISN_COMPARESTRING:
case ISN_CONCAT:
- case ISN_DCALL:
case ISN_DROP:
case ISN_ECHO:
case ISN_ECHOERR:
--- 7345,7350 ----
*** ../vim-8.2.1711/src/userfunc.c 2020-09-19 15:16:46.395622457 +0200
--- src/userfunc.c 2020-09-19 18:04:40.459403238 +0200
***************
*** 1058,1064 ****
* using function() does not count as a reference, because the function is
* looked up by name.
*/
! static int
func_name_refcount(char_u *name)
{
return isdigit(*name) || *name == '<';
--- 1058,1064 ----
* using function() does not count as a reference, because the function is
* looked up by name.
*/
! int
func_name_refcount(char_u *name)
{
return isdigit(*name) || *name == '<';
***************
*** 1176,1183 ****
* Free a function and remove it from the list of functions. Does not free
* what a function contains, call func_clear() first.
* When "force" is TRUE we are exiting.
*/
! static void
func_free(ufunc_T *fp, int force)
{
// Only remove it when not done already, otherwise we would remove a newer
--- 1176,1184 ----
* Free a function and remove it from the list of functions. Does not free
* what a function contains, call func_clear() first.
* When "force" is TRUE we are exiting.
+ * Returns OK when the function was actually freed.
*/
! static int
func_free(ufunc_T *fp, int force)
{
// Only remove it when not done already, otherwise we would remove a newer
***************
*** 1191,1197 ****
--- 1192,1200 ----
unlink_def_function(fp);
VIM_CLEAR(fp->uf_name_exp);
vim_free(fp);
+ return OK;
}
+ return FAIL;
}

/*
***************
*** 1890,1898 ****
++skipped;
else
{
! func_free(fp, FALSE);
! skipped = 0;
! break;
}
}
}
--- 1893,1905 ----
++skipped;
else
{
! if (func_free(fp, FALSE) == OK)
! {
! skipped = 0;
! break;
! }
! // did not actually free it
! ++skipped;
}
}
}
*** ../vim-8.2.1711/src/proto/userfunc.pro 2020-09-12 18:32:30.683427305 +0200
--- src/proto/userfunc.pro 2020-09-19 18:04:43.675389188 +0200
***************
*** 12,17 ****
--- 12,18 ----
ufunc_T *find_func_even_dead(char_u *name, int is_global, cctx_T *cctx);
ufunc_T *find_func(char_u *name, int is_global, cctx_T *cctx);
int func_is_global(ufunc_T *ufunc);
+ int func_name_refcount(char_u *name);
void copy_func(char_u *lambda, char_u *global);
int call_user_func_check(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rettv, funcexe_T *funcexe, dict_T *selfdict);
void save_funccal(funccal_entry_T *entry);
*** ../vim-8.2.1711/src/version.c 2020-09-19 15:16:46.399622447 +0200
--- src/version.c 2020-09-19 18:17:36.135766329 +0200
***************
*** 752,753 ****
--- 752,755 ----
{ /* Add new patch number below this line */
+ /**/
+ 1712,
/**/

--
If you don't get everything you want, think of
everything you didn't get and don't want.

/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
Reply all
Reply to author
Forward
0 new messages