mirror of
https://github.com/vim/vim.git
synced 2025-09-23 03:43:49 -04:00
patch 9.0.0487: using freed memory with combination of closures
Problem: Using freed memory with combination of closures. Solution: Do not use a partial after it has been freed through the funcstack.
This commit is contained in:
@@ -4876,6 +4876,8 @@ partial_unref(partial_T *pt)
|
||||
{
|
||||
if (pt != NULL)
|
||||
{
|
||||
int done = FALSE;
|
||||
|
||||
if (--pt->pt_refcount <= 0)
|
||||
partial_free(pt);
|
||||
|
||||
@@ -4883,9 +4885,12 @@ partial_unref(partial_T *pt)
|
||||
// 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)
|
||||
funcstack_check_refcount(pt->pt_funcstack);
|
||||
if (pt->pt_loopvars != NULL)
|
||||
done = funcstack_check_refcount(pt->pt_funcstack);
|
||||
|
||||
if (!done && pt->pt_loopvars != NULL)
|
||||
loopvars_check_refcount(pt->pt_loopvars);
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +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 funcstack_check_refcount(funcstack_T *funcstack);
|
||||
int set_ref_in_funcstacks(int copyID);
|
||||
int in_def_function(void);
|
||||
ectx_T *clear_currrent_ectx(void);
|
||||
|
@@ -703,6 +703,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
487,
|
||||
/**/
|
||||
486,
|
||||
/**/
|
||||
|
@@ -797,16 +797,19 @@ handle_closure_in_use(ectx_T *ectx, int free_arguments)
|
||||
* 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.
|
||||
*/
|
||||
void
|
||||
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;
|
||||
return FALSE;
|
||||
for (i = funcstack->fs_var_offset; i < gap->ga_len; ++i)
|
||||
{
|
||||
typval_T *tv = ((typval_T *)gap->ga_data) + i;
|
||||
@@ -816,9 +819,10 @@ funcstack_check_refcount(funcstack_T *funcstack)
|
||||
&& tv->vval.v_partial->pt_refcount == 1)
|
||||
++done;
|
||||
}
|
||||
if (done == funcstack->fs_min_refcount)
|
||||
{
|
||||
typval_T *stack = gap->ga_data;
|
||||
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.
|
||||
@@ -827,7 +831,8 @@ funcstack_check_refcount(funcstack_T *funcstack)
|
||||
vim_free(stack);
|
||||
remove_funcstack_from_list(funcstack);
|
||||
vim_free(funcstack);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user