Mercurial > vim
diff src/vim9execute.c @ 27591:d91be28bbdbb v8.2.4322
patch 8.2.4322: Vim9: crash when using funcref with closure
Commit: https://github.com/vim/vim/commit/7aca5ca6763e50d2c23953b20e30fca7457c9abf
Author: Bram Moolenaar <Bram@vim.org>
Date: Mon Feb 7 19:56:43 2022 +0000
patch 8.2.4322: Vim9: crash when using funcref with closure
Problem: Vim9: crash when using funcref with closure.
Solution: Keep a reference to the funcref that has the outer context.
(closes #9716)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Mon, 07 Feb 2022 21:00:02 +0100 |
parents | a31dd0a3cb39 |
children | a6ffe874a24b |
line wrap: on
line diff
--- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -235,6 +235,23 @@ dict_stack_clear(int len) } /* + * Get a pointer to useful "pt_outer" of "pt". + */ + static outer_T * +get_pt_outer(partial_T *pt) +{ + partial_T *ptref = pt->pt_outer_partial; + + if (ptref == NULL) + return &pt->pt_outer; + + // partial using partial (recursively) + while (ptref->pt_outer_partial != NULL) + ptref = ptref->pt_outer_partial; + return &ptref->pt_outer; +} + +/* * Call compiled function "cdf_idx" from compiled code. * This adds a stack frame and sets the instruction pointer to the start of the * called function. @@ -421,13 +438,13 @@ call_dfunc( return FAIL; if (pt != NULL) { - ref->or_outer = &pt->pt_outer; + ref->or_outer = get_pt_outer(pt); ++pt->pt_refcount; ref->or_partial = pt; } else if (ufunc->uf_partial != NULL) { - ref->or_outer = &ufunc->uf_partial->pt_outer; + ref->or_outer = get_pt_outer(ufunc->uf_partial); ++ufunc->uf_partial->pt_refcount; ref->or_partial = ufunc->uf_partial; } @@ -5086,7 +5103,9 @@ call_def_function( goto failed_early; if (partial != NULL) { - if (partial->pt_outer.out_stack == NULL) + outer_T *outer = get_pt_outer(partial); + + if (outer->out_stack == NULL) { if (current_ectx != NULL) { @@ -5099,7 +5118,7 @@ call_def_function( } else { - ectx.ec_outer_ref->or_outer = &partial->pt_outer; + ectx.ec_outer_ref->or_outer = outer; ++partial->pt_refcount; ectx.ec_outer_ref->or_partial = partial; }