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:
@@ -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)
|
||||
{
|
||||
|
Reference in New Issue
Block a user