1
0
forked from aniani/vim

patch 8.2.0488: Vim9: compiling can break when using a lambda inside :def

Problem:    Vim9: Compiling can break when using a lambda inside :def.
Solution:   Do not keep a pointer to the dfunc_T for longer time.
This commit is contained in:
Bram Moolenaar 2020-03-31 23:32:31 +02:00
parent bd5da371aa
commit 05afceeddc
3 changed files with 36 additions and 23 deletions

View File

@ -738,6 +738,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
488,
/**/
487,
/**/

View File

@ -257,7 +257,7 @@ struct dfunc_S {
// Functions defined with :def are stored in this growarray.
// They are never removed, so that they can be found by index.
// Deleted functions have the df_deleted flag set.
garray_T def_functions = {0, 0, sizeof(dfunc_T), 200, NULL};
garray_T def_functions = {0, 0, sizeof(dfunc_T), 50, NULL};
#else
extern garray_T def_functions;
#endif

View File

@ -5029,11 +5029,12 @@ compile_execute(char_u *arg, cctx_T *cctx)
* Adds the function to "def_functions".
* When "set_return_type" is set then set ufunc->uf_ret_type to the type of the
* return statement (used for lambda).
* This can be used recursively through compile_lambda(), which may reallocate
* "def_functions".
*/
void
compile_def_function(ufunc_T *ufunc, int set_return_type)
{
dfunc_T *dfunc;
char_u *line = NULL;
char_u *p;
exarg_T ea;
@ -5046,6 +5047,9 @@ compile_def_function(ufunc_T *ufunc, int set_return_type)
sctx_T save_current_sctx = current_sctx;
int emsg_before = called_emsg;
{
dfunc_T *dfunc; // may be invalidated by compile_lambda()
if (ufunc->uf_dfunc_idx >= 0)
{
// Redefining a function that was compiled before.
@ -5066,6 +5070,7 @@ compile_def_function(ufunc_T *ufunc, int set_return_type)
dfunc->df_ufunc = ufunc;
++def_functions.ga_len;
}
}
vim_memset(&cctx, 0, sizeof(cctx));
cctx.ctx_ufunc = ufunc;
@ -5414,10 +5419,14 @@ compile_def_function(ufunc_T *ufunc, int set_return_type)
generate_instr(&cctx, ISN_RETURN);
}
{
dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
+ ufunc->uf_dfunc_idx;
dfunc->df_deleted = FALSE;
dfunc->df_instr = instr->ga_data;
dfunc->df_instr_count = instr->ga_len;
dfunc->df_varcount = cctx.ctx_max_local;
}
ret = OK;
@ -5425,6 +5434,8 @@ erret:
if (ret == FAIL)
{
int idx;
dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
+ ufunc->uf_dfunc_idx;
for (idx = 0; idx < instr->ga_len; ++idx)
delete_instr(((isn_T *)instr->ga_data) + idx);