0
0
mirror of https://github.com/vim/vim.git synced 2025-09-26 04:04:07 -04:00

patch 8.2.3216: Vim9: crash when using variable in a loop at script level

Problem:    Vim9: crash when using variable in a loop at script level.
Solution:   Do not clear the variable if a function was defined.
            Do not create a new entry in sn_var_vals every time.
            (closes #8628)
This commit is contained in:
Bram Moolenaar
2021-07-25 14:13:53 +02:00
parent 5bca906b30
commit 2eb6fc3b52
8 changed files with 136 additions and 77 deletions

View File

@@ -613,6 +613,35 @@ is_function_cmd(char_u **cmd)
return FALSE;
}
/*
* Called when defining a function: The context may be needed for script
* variables declared in a block that is visible now but not when the function
* is compiled or called later.
*/
static void
function_using_block_scopes(ufunc_T *fp, cstack_T *cstack)
{
if (cstack != NULL && cstack->cs_idx >= 0)
{
int count = cstack->cs_idx + 1;
int i;
fp->uf_block_ids = ALLOC_MULT(int, count);
if (fp->uf_block_ids != NULL)
{
mch_memmove(fp->uf_block_ids, cstack->cs_block_id,
sizeof(int) * count);
fp->uf_block_depth = count;
}
// Set flag in each block to indicate a function was defined. This
// is used to keep the variable when leaving the block, see
// hide_script_var().
for (i = 0; i <= cstack->cs_idx; ++i)
cstack->cs_flags[i] |= CSF_FUNC_DEF;
}
}
/*
* Read the body of a function, put every line in "newlines".
* This stops at "}", "endfunction" or "enddef".
@@ -1195,6 +1224,8 @@ lambda_function_body(
ufunc->uf_script_ctx.sc_lnum += sourcing_lnum_top;
set_function_type(ufunc);
function_using_block_scopes(ufunc, evalarg->eval_cstack);
rettv->vval.v_partial = pt;
rettv->v_type = VAR_PARTIAL;
ufunc = NULL;
@@ -1442,6 +1473,8 @@ get_lambda_tv(
fp->uf_script_ctx = current_sctx;
fp->uf_script_ctx.sc_lnum += SOURCING_LNUM - newlines.ga_len;
function_using_block_scopes(fp, evalarg->eval_cstack);
pt->pt_func = fp;
pt->pt_refcount = 1;
rettv->vval.v_partial = pt;
@@ -1459,6 +1492,7 @@ theend:
vim_free(tofree2);
if (types_optional)
ga_clear_strings(&argtypes);
return OK;
errret:
@@ -4313,28 +4347,8 @@ define_function(exarg_T *eap, char_u *name_arg)
// error messages are for the first function line
SOURCING_LNUM = sourcing_lnum_top;
if (cstack != NULL && cstack->cs_idx >= 0)
{
int count = cstack->cs_idx + 1;
int i;
// The block context may be needed for script variables declared in
// a block that is visible now but not when the function is called
// later.
fp->uf_block_ids = ALLOC_MULT(int, count);
if (fp->uf_block_ids != NULL)
{
mch_memmove(fp->uf_block_ids, cstack->cs_block_id,
sizeof(int) * count);
fp->uf_block_depth = count;
}
// Set flag in each block to indicate a function was defined. This
// is used to keep the variable when leaving the block, see
// hide_script_var().
for (i = 0; i <= cstack->cs_idx; ++i)
cstack->cs_flags[i] |= CSF_FUNC_DEF;
}
// The function may use script variables from the context.
function_using_block_scopes(fp, cstack);
if (parse_argument_types(fp, &argtypes, varargs) == FAIL)
{