patch 9.1.1879: Crash when using a lambda funcref with :defer
Commit:
https://github.com/vim/vim/commit/bd9155ebb64b3fbf3ff154c8b57c1b3a3783ebea
Author: Yegappan Lakshmanan <[email protected]>
Date: Sun Oct 26 20:03:18 2025 +0000
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 <[email protected]>
Signed-off-by: Christian Brabandt <[email protected]>
diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim
index 3c2c0cc07..40832a606 100644
--- a/src/testdir/test_vim9_script.vim
+++ b/src/testdir/test_vim9_script.vim
@@ -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
diff --git a/src/version.c b/src/version.c
index 78860b861..3f33a0e6f 100644
--- a/src/version.c
+++ b/src/version.c
@@ -729,6 +729,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 1879,
/**/
1878,
/**/
diff --git a/src/vim9execute.c b/src/vim9execute.c
index 85606840d..87a3e9d66 100644
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -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);
}
}
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion visit
https://groups.google.com/d/msgid/vim_dev/E1vD78r-004D4o-Ko%40256bit.org.