Patch 9.0.0487 (after 9.0.0485)
Problem: Using freed memory with combination of closures.
Solution: Do not use a partial after it has been freed through the
funcstack.
Files: src/vim9execute.c, src/proto/
vim9execute.pro, src/eval.c
*** ../vim-9.0.0486/src/vim9execute.c 2022-09-17 15:44:48.365409503 +0100
--- src/vim9execute.c 2022-09-17 16:23:46.339316875 +0100
***************
*** 797,812 ****
* funcstack may be the only reference to the partials in the local variables.
* Go over all of them, the funcref and can be freed if all partials
* referencing the funcstack have a reference count of one.
*/
! void
funcstack_check_refcount(funcstack_T *funcstack)
{
! int i;
! garray_T *gap = &funcstack->fs_ga;
! int done = 0;
if (funcstack->fs_refcount > funcstack->fs_min_refcount)
! return;
for (i = funcstack->fs_var_offset; i < gap->ga_len; ++i)
{
typval_T *tv = ((typval_T *)gap->ga_data) + i;
--- 797,815 ----
* funcstack may be the only reference to the partials in the local variables.
* Go over all of them, the funcref and can be freed if all partials
* referencing the funcstack have a reference count of one.
+ * Returns TRUE if the funcstack is freed, the partial referencing it will then
+ * also have been freed.
*/
! int
funcstack_check_refcount(funcstack_T *funcstack)
{
! int i;
! garray_T *gap = &funcstack->fs_ga;
! int done = 0;
! typval_T *stack;
if (funcstack->fs_refcount > funcstack->fs_min_refcount)
! return FALSE;
for (i = funcstack->fs_var_offset; i < gap->ga_len; ++i)
{
typval_T *tv = ((typval_T *)gap->ga_data) + i;
***************
*** 816,833 ****
&& tv->vval.v_partial->pt_refcount == 1)
++done;
}
! if (done == funcstack->fs_min_refcount)
! {
! typval_T *stack = gap->ga_data;
! // All partials referencing the funcstack have a reference count of
! // one, thus the funcstack is no longer of use.
! for (i = 0; i < gap->ga_len; ++i)
! clear_tv(stack + i);
! vim_free(stack);
! remove_funcstack_from_list(funcstack);
! vim_free(funcstack);
! }
}
/*
--- 819,838 ----
&& tv->vval.v_partial->pt_refcount == 1)
++done;
}
! if (done != funcstack->fs_min_refcount)
! return FALSE;
! stack = gap->ga_data;
!
! // All partials referencing the funcstack have a reference count of
! // one, thus the funcstack is no longer of use.
! for (i = 0; i < gap->ga_len; ++i)
! clear_tv(stack + i);
! vim_free(stack);
! remove_funcstack_from_list(funcstack);
! vim_free(funcstack);
!
! return TRUE;
}
/*
*** ../vim-9.0.0486/src/proto/
vim9execute.pro 2022-09-17 15:44:48.365409503 +0100
--- src/proto/
vim9execute.pro 2022-09-17 16:23:50.291303723 +0100
***************
*** 1,7 ****
/* vim9execute.c */
void to_string_error(vartype_T vartype);
void update_has_breakpoint(ufunc_T *ufunc);
! void funcstack_check_refcount(funcstack_T *funcstack);
int set_ref_in_funcstacks(int copyID);
int in_def_function(void);
ectx_T *clear_currrent_ectx(void);
--- 1,7 ----
/* vim9execute.c */
void to_string_error(vartype_T vartype);
void update_has_breakpoint(ufunc_T *ufunc);
! int funcstack_check_refcount(funcstack_T *funcstack);
int set_ref_in_funcstacks(int copyID);
int in_def_function(void);
ectx_T *clear_currrent_ectx(void);
*** ../vim-9.0.0486/src/eval.c 2022-09-17 15:44:48.365409503 +0100
--- src/eval.c 2022-09-17 16:25:09.007048831 +0100
***************
*** 4876,4881 ****
--- 4876,4883 ----
{
if (pt != NULL)
{
+ int done = FALSE;
+
if (--pt->pt_refcount <= 0)
partial_free(pt);
***************
*** 4883,4891 ****
// only reference and can be freed if no other partials reference it.
else if (pt->pt_refcount == 1)
{
if (pt->pt_funcstack != NULL)
! funcstack_check_refcount(pt->pt_funcstack);
! if (pt->pt_loopvars != NULL)
loopvars_check_refcount(pt->pt_loopvars);
}
}
--- 4885,4896 ----
// only reference and can be freed if no other partials reference it.
else if (pt->pt_refcount == 1)
{
+ // careful: if the funcstack is freed it may contain this partial
+ // and it gets freed as well
if (pt->pt_funcstack != NULL)
! done = funcstack_check_refcount(pt->pt_funcstack);
!
! if (!done && pt->pt_loopvars != NULL)
loopvars_check_refcount(pt->pt_loopvars);
}
}
*** ../vim-9.0.0486/src/version.c 2022-09-17 16:16:31.925060698 +0100
--- src/version.c 2022-09-17 16:27:20.622649155 +0100
***************
*** 705,706 ****
--- 705,708 ----
{ /* Add new patch number below this line */
+ /**/
+ 487,
/**/
--
From "know your smileys":
8<}} Glasses, big nose, beard
/// Bram Moolenaar -- Br...@Moolenaar.net --
http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features --
http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims --
http://ICCF-Holland.org ///