To: vim_dev@googlegroups.com Subject: Patch 8.2.1154 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.1154 Problem: Vim9: crash when using imported function. Solution: Check for a function type. Set the script context when calling a function. (closes #6412) Files: src/evalvars.c, src/scriptfile.c, src/proto/scriptfile.pro, src/vim9execute.c, src/structs.h, src/testdir/test_vim9_script.vim *** ../vim-8.2.1153/src/evalvars.c 2020-07-04 17:39:07.506515715 +0200 --- src/evalvars.c 2020-07-07 23:02:08.282700284 +0200 *************** *** 2375,2380 **** --- 2375,2381 ---- { int ret = OK; typval_T *tv = NULL; + int foundFunc = FALSE; dictitem_T *v; int cc; *************** *** 2402,2422 **** // imported variable from another script if (import != NULL) { ! scriptitem_T *si = SCRIPT_ITEM(import->imp_sid); ! svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + import->imp_var_vals_idx; ! tv = sv->sv_tv; } } ! if (tv == NULL) { ! if (rettv != NULL && verbose) ! semsg(_(e_undefvar), name); ! ret = FAIL; } - else if (rettv != NULL) - copy_tv(tv, rettv); name[len] = cc; --- 2403,2438 ---- // imported variable from another script if (import != NULL) { ! if (import->imp_funcname != NULL) ! { ! foundFunc = TRUE; ! if (rettv != NULL) ! { ! rettv->v_type = VAR_FUNC; ! rettv->vval.v_string = vim_strsave(import->imp_funcname); ! } ! } ! else ! { ! scriptitem_T *si = SCRIPT_ITEM(import->imp_sid); ! svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + import->imp_var_vals_idx; ! tv = sv->sv_tv; ! } } } ! if (!foundFunc) { ! if (tv == NULL) ! { ! if (rettv != NULL && verbose) ! semsg(_(e_undefvar), name); ! ret = FAIL; ! } ! else if (rettv != NULL) ! copy_tv(tv, rettv); } name[len] = cc; *** ../vim-8.2.1153/src/scriptfile.c 2020-06-24 18:37:28.359249374 +0200 --- src/scriptfile.c 2020-07-07 23:20:05.637463929 +0200 *************** *** 68,74 **** /* * Add a user function to the execution stack. */ ! void estack_push_ufunc(ufunc_T *ufunc, long lnum) { estack_T *entry = estack_push(ETYPE_UFUNC, --- 68,74 ---- /* * Add a user function to the execution stack. */ ! estack_T * estack_push_ufunc(ufunc_T *ufunc, long lnum) { estack_T *entry = estack_push(ETYPE_UFUNC, *************** *** 76,81 **** --- 76,82 ---- ? ufunc->uf_name_exp : ufunc->uf_name, lnum); if (entry != NULL) entry->es_info.ufunc = ufunc; + return entry; } /* *************** *** 97,109 **** #endif /* ! * Take an item off of the execution stack. */ ! void estack_pop(void) { ! if (exestack.ga_len > 1) ! --exestack.ga_len; } /* --- 98,112 ---- #endif /* ! * Take an item off of the execution stack and return it. */ ! estack_T * estack_pop(void) { ! if (exestack.ga_len == 0) ! return NULL; ! --exestack.ga_len; ! return ((estack_T *)exestack.ga_data) + exestack.ga_len; } /* *** ../vim-8.2.1153/src/proto/scriptfile.pro 2020-06-24 18:37:28.359249374 +0200 --- src/proto/scriptfile.pro 2020-07-07 23:20:43.537290995 +0200 *************** *** 1,9 **** /* scriptfile.c */ void estack_init(void); estack_T *estack_push(etype_T type, char_u *name, long lnum); ! void estack_push_ufunc(ufunc_T *ufunc, long lnum); int estack_top_is_ufunc(ufunc_T *ufunc, long lnum); ! void estack_pop(void); char_u *estack_sfile(void); void ex_runtime(exarg_T *eap); int do_in_path(char_u *path, char_u *name, int flags, void (*callback)(char_u *fname, void *ck), void *cookie); --- 1,9 ---- /* scriptfile.c */ void estack_init(void); estack_T *estack_push(etype_T type, char_u *name, long lnum); ! estack_T *estack_push_ufunc(ufunc_T *ufunc, long lnum); int estack_top_is_ufunc(ufunc_T *ufunc, long lnum); ! estack_T *estack_pop(void); char_u *estack_sfile(void); void ex_runtime(exarg_T *eap); int do_in_path(char_u *path, char_u *name, int flags, void (*callback)(char_u *fname, void *ck), void *cookie); *** ../vim-8.2.1153/src/vim9execute.c 2020-07-05 16:51:23.610238546 +0200 --- src/vim9execute.c 2020-07-07 23:20:39.237310592 +0200 *************** *** 160,165 **** --- 160,166 ---- int arg_to_add; int vararg_count = 0; int idx; + estack_T *entry; if (dfunc->df_deleted) { *************** *** 230,236 **** // Set execution state to the start of the called function. ectx->ec_dfunc_idx = cdf_idx; ectx->ec_instr = dfunc->df_instr; ! estack_push_ufunc(dfunc->df_ufunc, 1); // Decide where to start execution, handles optional arguments. init_instr_idx(ufunc, argcount, ectx); --- 231,244 ---- // Set execution state to the start of the called function. ectx->ec_dfunc_idx = cdf_idx; ectx->ec_instr = dfunc->df_instr; ! entry = estack_push_ufunc(dfunc->df_ufunc, 1); ! if (entry != NULL) ! { ! // Set the script context to the script where the function was defined. ! // TODO: save more than the SID? ! entry->es_save_sid = current_sctx.sc_sid; ! current_sctx.sc_sid = ufunc->uf_script_ctx.sc_sid; ! } // Decide where to start execution, handles optional arguments. init_instr_idx(ufunc, argcount, ectx); *************** *** 386,394 **** + ectx->ec_dfunc_idx; int argcount = ufunc_argcount(dfunc->df_ufunc); int top = ectx->ec_frame_idx - argcount; // execution context goes one level up ! estack_pop(); if (handle_closure_in_use(ectx, TRUE) == FAIL) return FAIL; --- 394,405 ---- + ectx->ec_dfunc_idx; int argcount = ufunc_argcount(dfunc->df_ufunc); int top = ectx->ec_frame_idx - argcount; + estack_T *entry; // execution context goes one level up ! entry = estack_pop(); ! if (entry != NULL) ! current_sctx.sc_sid = entry->es_save_sid; if (handle_closure_in_use(ectx, TRUE) == FAIL) return FAIL; *** ../vim-8.2.1153/src/structs.h 2020-06-28 18:43:36.296992324 +0200 --- src/structs.h 2020-07-08 14:09:50.231790400 +0200 *************** *** 1905,1910 **** --- 1905,1913 ---- AutoPatCmd *aucmd; // autocommand info except_T *except; // exception info } es_info; + #if defined(FEAT_EVAL) + scid_T es_save_sid; // saved sc_sid when calling function + #endif } estack_T; // Information returned by get_tty_info(). *** ../vim-8.2.1153/src/testdir/test_vim9_script.vim 2020-07-07 23:31:31.814366067 +0200 --- src/testdir/test_vim9_script.vim 2020-07-08 14:47:38.266937211 +0200 *************** *** 911,920 **** CheckRunVimInTerminal " call indirectly to avoid compilation error for missing functions ! call Run_Test_import_fails_without_script() endfunc ! def Run_Test_import_fails_without_script() let export =<< trim END vim9script export def Foo(): number --- 911,920 ---- CheckRunVimInTerminal " call indirectly to avoid compilation error for missing functions ! call Run_Test_import_fails_on_command_line() endfunc ! def Run_Test_import_fails_on_command_line() let export =<< trim END vim9script export def Foo(): number *************** *** 1013,1018 **** --- 1013,1047 ---- delete('Xscript.vim') enddef + " Check that when searcing for "FilterFunc" it doesn't find the import in the + " script where FastFilter() is called from. + def Test_vim9script_funcref_other_script() + let filterLines =<< trim END + vim9script + export def FilterFunc(idx: number, val: number): bool + return idx % 2 == 1 + enddef + export def FastFilter(): list + return range(10)->filter('FilterFunc') + enddef + END + writefile(filterLines, 'Xfilter.vim') + + let lines =<< trim END + vim9script + import {FilterFunc, FastFilter} from './Xfilter.vim' + def Test() + let x: list = FastFilter() + enddef + Test() + END + writefile(lines, 'Ximport.vim') + assert_fails('source Ximport.vim', 'E121:') + + delete('Xfilter.vim') + delete('Ximport.vim') + enddef + def Test_vim9script_reload_delfunc() let first_lines =<< trim END vim9script *** ../vim-8.2.1153/src/version.c 2020-07-07 23:31:31.814366067 +0200 --- src/version.c 2020-07-08 15:14:26.962523895 +0200 *************** *** 756,757 **** --- 756,759 ---- { /* Add new patch number below this line */ + /**/ + 1154, /**/ -- Every engineer dreams about saving the universe and having sex with aliens. This is much more glamorous than the real life of an engineer, which consists of hiding from the universe and having sex without the participation of other life forms. (Scott Adams - The Dilbert principle) /// 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 ///