0
0
mirror of https://github.com/vim/vim.git synced 2025-11-14 23:04:02 -05:00

patch 9.1.1879: Crash when using a lambda funcref with :defer

Problem:  Crash when using a lambda funcref with :defer
Solution: De-reference the partial correctly after invoking the deferred
          functions (Yegappan Lakshmanan).

closes: #18640

Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Yegappan Lakshmanan
2025-10-26 20:03:18 +00:00
committed by Christian Brabandt
parent 9fff99c3c2
commit bd9155ebb6
3 changed files with 39 additions and 7 deletions

View File

@@ -5232,6 +5232,23 @@ def Test_defer_invalid_func_arg()
v9.CheckScriptFailure(lines, 'E1001: Variable not found: a', 1)
enddef
" Test for using defer with a lambda funcref
def Test_defer_lambda_funcref()
var lines =<< trim END
vim9script
var lfr_result = ''
def Foo()
var Fn = () => {
lfr_result = 'called'
}
defer Fn()
enddef
Foo()
assert_equal('called', lfr_result)
END
v9.CheckSourceSuccess(lines)
enddef
" Test for using an non-existing type in a "for" statement.
def Test_invalid_type_in_for()
var lines =<< trim END

View File

@@ -729,6 +729,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1879,
/**/
1878,
/**/

View File

@@ -1176,20 +1176,30 @@ invoke_defer_funcs(ectx_T *ectx)
argvars[i] = arg_li->li_tv;
}
funcexe_T funcexe;
funcexe_T funcexe;
char_u *name = NULL;
partial_T *pt = NULL;
CLEAR_FIELD(funcexe);
funcexe.fe_evaluate = TRUE;
rettv.v_type = VAR_UNKNOWN;
if (functv->v_type == VAR_PARTIAL)
{
funcexe.fe_partial = functv->vval.v_partial;
funcexe.fe_object = functv->vval.v_partial->pt_obj;
pt = functv->vval.v_partial;
functv->vval.v_partial = NULL;
name = pt->pt_func->uf_name;
funcexe.fe_partial = pt;
funcexe.fe_object = pt->pt_obj;
if (funcexe.fe_object != NULL)
++funcexe.fe_object->obj_refcount;
}
char_u *name = functv->vval.v_string;
functv->vval.v_string = NULL;
else
{
name = functv->vval.v_string;
functv->vval.v_string = NULL;
}
// If the deferred function is called after an exception, then only the
// first statement in the function will be executed (because of the
@@ -1204,7 +1214,10 @@ invoke_defer_funcs(ectx_T *ectx)
exception_state_restore(&estate);
clear_tv(&rettv);
vim_free(name);
if (functv->v_type == VAR_PARTIAL)
partial_unref(pt);
else
vim_free(name);
}
}