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:
committed by
Christian Brabandt
parent
9fff99c3c2
commit
bd9155ebb6
@@ -5232,6 +5232,23 @@ def Test_defer_invalid_func_arg()
|
|||||||
v9.CheckScriptFailure(lines, 'E1001: Variable not found: a', 1)
|
v9.CheckScriptFailure(lines, 'E1001: Variable not found: a', 1)
|
||||||
enddef
|
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.
|
" Test for using an non-existing type in a "for" statement.
|
||||||
def Test_invalid_type_in_for()
|
def Test_invalid_type_in_for()
|
||||||
var lines =<< trim END
|
var lines =<< trim END
|
||||||
|
|||||||
@@ -729,6 +729,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1879,
|
||||||
/**/
|
/**/
|
||||||
1878,
|
1878,
|
||||||
/**/
|
/**/
|
||||||
|
|||||||
@@ -1177,19 +1177,29 @@ invoke_defer_funcs(ectx_T *ectx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
funcexe_T funcexe;
|
funcexe_T funcexe;
|
||||||
|
char_u *name = NULL;
|
||||||
|
partial_T *pt = NULL;
|
||||||
|
|
||||||
CLEAR_FIELD(funcexe);
|
CLEAR_FIELD(funcexe);
|
||||||
funcexe.fe_evaluate = TRUE;
|
funcexe.fe_evaluate = TRUE;
|
||||||
rettv.v_type = VAR_UNKNOWN;
|
rettv.v_type = VAR_UNKNOWN;
|
||||||
|
|
||||||
if (functv->v_type == VAR_PARTIAL)
|
if (functv->v_type == VAR_PARTIAL)
|
||||||
{
|
{
|
||||||
funcexe.fe_partial = functv->vval.v_partial;
|
pt = functv->vval.v_partial;
|
||||||
funcexe.fe_object = functv->vval.v_partial->pt_obj;
|
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)
|
if (funcexe.fe_object != NULL)
|
||||||
++funcexe.fe_object->obj_refcount;
|
++funcexe.fe_object->obj_refcount;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
char_u *name = functv->vval.v_string;
|
{
|
||||||
|
name = functv->vval.v_string;
|
||||||
functv->vval.v_string = NULL;
|
functv->vval.v_string = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// If the deferred function is called after an exception, then only the
|
// If the deferred function is called after an exception, then only the
|
||||||
// first statement in the function will be executed (because of the
|
// first statement in the function will be executed (because of the
|
||||||
@@ -1204,6 +1214,9 @@ invoke_defer_funcs(ectx_T *ectx)
|
|||||||
exception_state_restore(&estate);
|
exception_state_restore(&estate);
|
||||||
|
|
||||||
clear_tv(&rettv);
|
clear_tv(&rettv);
|
||||||
|
if (functv->v_type == VAR_PARTIAL)
|
||||||
|
partial_unref(pt);
|
||||||
|
else
|
||||||
vim_free(name);
|
vim_free(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user