To: vim_dev@googlegroups.com Subject: Patch 8.2.0488 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.0488 Problem: Vim9: Compiling can break when using a lambda inside :def. Solution: Do not keep a pointer to the dfunc_T for longer time. Files: src/vim9compile.c, src/vim9.h *** ../vim-8.2.0487/src/vim9compile.c 2020-03-31 23:13:05.758568664 +0200 --- src/vim9compile.c 2020-03-31 23:28:43.711140249 +0200 *************** *** 5029,5039 **** * 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). */ void compile_def_function(ufunc_T *ufunc, int set_return_type) { - dfunc_T *dfunc; char_u *line = NULL; char_u *p; exarg_T ea; --- 5029,5040 ---- * 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) { char_u *line = NULL; char_u *p; exarg_T ea; *************** *** 5046,5070 **** sctx_T save_current_sctx = current_sctx; int emsg_before = called_emsg; - if (ufunc->uf_dfunc_idx >= 0) { ! // Redefining a function that was compiled before. ! dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx; ! // Free old instructions. ! delete_def_function_contents(dfunc); ! } ! else ! { ! // Add the function to "def_functions". ! if (ga_grow(&def_functions, 1) == FAIL) ! return; ! dfunc = ((dfunc_T *)def_functions.ga_data) + def_functions.ga_len; ! vim_memset(dfunc, 0, sizeof(dfunc_T)); ! dfunc->df_idx = def_functions.ga_len; ! ufunc->uf_dfunc_idx = dfunc->df_idx; ! dfunc->df_ufunc = ufunc; ! ++def_functions.ga_len; } vim_memset(&cctx, 0, sizeof(cctx)); --- 5047,5075 ---- 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. ! dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx; ! ! // Free old instructions. ! delete_def_function_contents(dfunc); ! } ! else ! { ! // Add the function to "def_functions". ! if (ga_grow(&def_functions, 1) == FAIL) ! return; ! dfunc = ((dfunc_T *)def_functions.ga_data) + def_functions.ga_len; ! vim_memset(dfunc, 0, sizeof(dfunc_T)); ! dfunc->df_idx = def_functions.ga_len; ! ufunc->uf_dfunc_idx = dfunc->df_idx; ! dfunc->df_ufunc = ufunc; ! ++def_functions.ga_len; ! } } vim_memset(&cctx, 0, sizeof(cctx)); *************** *** 5414,5423 **** generate_instr(&cctx, ISN_RETURN); } ! 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; --- 5419,5432 ---- 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,5430 **** --- 5434,5441 ---- 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); *** ../vim-8.2.0487/src/vim9.h 2020-03-31 23:13:05.758568664 +0200 --- src/vim9.h 2020-03-31 23:29:10.395041154 +0200 *************** *** 257,263 **** // 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}; #else extern garray_T def_functions; #endif --- 257,263 ---- // 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), 50, NULL}; #else extern garray_T def_functions; #endif *** ../vim-8.2.0487/src/version.c 2020-03-31 23:13:05.762568650 +0200 --- src/version.c 2020-03-31 23:30:53.690659160 +0200 *************** *** 740,741 **** --- 740,743 ---- { /* Add new patch number below this line */ + /**/ + 488, /**/ -- If "R" is Reverse, how come "D" is FORWARD? /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///