mirror of
https://github.com/vim/vim.git
synced 2025-09-23 03:43:49 -04:00
patch 8.2.1154: Vim9: crash when using imported function
Problem: Vim9: crash when using imported function. Solution: Check for a function type. Set the script context when calling a function. (closes #6412)
This commit is contained in:
@@ -2375,6 +2375,7 @@ eval_variable(
|
||||
{
|
||||
int ret = OK;
|
||||
typval_T *tv = NULL;
|
||||
int foundFunc = FALSE;
|
||||
dictitem_T *v;
|
||||
int cc;
|
||||
|
||||
@@ -2402,21 +2403,36 @@ eval_variable(
|
||||
// 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)
|
||||
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;
|
||||
tv = sv->sv_tv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tv == NULL)
|
||||
if (!foundFunc)
|
||||
{
|
||||
if (rettv != NULL && verbose)
|
||||
semsg(_(e_undefvar), name);
|
||||
ret = FAIL;
|
||||
if (tv == NULL)
|
||||
{
|
||||
if (rettv != NULL && verbose)
|
||||
semsg(_(e_undefvar), name);
|
||||
ret = FAIL;
|
||||
}
|
||||
else if (rettv != NULL)
|
||||
copy_tv(tv, rettv);
|
||||
}
|
||||
else if (rettv != NULL)
|
||||
copy_tv(tv, rettv);
|
||||
|
||||
name[len] = cc;
|
||||
|
||||
|
@@ -1,9 +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);
|
||||
estack_T *estack_push_ufunc(ufunc_T *ufunc, long lnum);
|
||||
int estack_top_is_ufunc(ufunc_T *ufunc, long lnum);
|
||||
void estack_pop(void);
|
||||
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);
|
||||
|
@@ -68,7 +68,7 @@ estack_push(etype_T type, char_u *name, long lnum)
|
||||
/*
|
||||
* Add a user function to the execution stack.
|
||||
*/
|
||||
void
|
||||
estack_T *
|
||||
estack_push_ufunc(ufunc_T *ufunc, long lnum)
|
||||
{
|
||||
estack_T *entry = estack_push(ETYPE_UFUNC,
|
||||
@@ -76,6 +76,7 @@ estack_push_ufunc(ufunc_T *ufunc, long lnum)
|
||||
? ufunc->uf_name_exp : ufunc->uf_name, lnum);
|
||||
if (entry != NULL)
|
||||
entry->es_info.ufunc = ufunc;
|
||||
return entry;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -97,13 +98,15 @@ estack_top_is_ufunc(ufunc_T *ufunc, long lnum)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Take an item off of the execution stack.
|
||||
* Take an item off of the execution stack and return it.
|
||||
*/
|
||||
void
|
||||
estack_T *
|
||||
estack_pop(void)
|
||||
{
|
||||
if (exestack.ga_len > 1)
|
||||
--exestack.ga_len;
|
||||
if (exestack.ga_len == 0)
|
||||
return NULL;
|
||||
--exestack.ga_len;
|
||||
return ((estack_T *)exestack.ga_data) + exestack.ga_len;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -1905,6 +1905,9 @@ typedef struct {
|
||||
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().
|
||||
|
@@ -911,10 +911,10 @@ func Test_import_fails_without_script()
|
||||
CheckRunVimInTerminal
|
||||
|
||||
" call indirectly to avoid compilation error for missing functions
|
||||
call Run_Test_import_fails_without_script()
|
||||
call Run_Test_import_fails_on_command_line()
|
||||
endfunc
|
||||
|
||||
def Run_Test_import_fails_without_script()
|
||||
def Run_Test_import_fails_on_command_line()
|
||||
let export =<< trim END
|
||||
vim9script
|
||||
export def Foo(): number
|
||||
@@ -1013,6 +1013,35 @@ def Test_vim9script_funcref()
|
||||
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<number>
|
||||
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<number> = 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
|
||||
|
@@ -754,6 +754,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1154,
|
||||
/**/
|
||||
1153,
|
||||
/**/
|
||||
|
@@ -160,6 +160,7 @@ call_dfunc(int cdf_idx, int argcount_arg, ectx_T *ectx)
|
||||
int arg_to_add;
|
||||
int vararg_count = 0;
|
||||
int idx;
|
||||
estack_T *entry;
|
||||
|
||||
if (dfunc->df_deleted)
|
||||
{
|
||||
@@ -230,7 +231,14 @@ call_dfunc(int cdf_idx, int argcount_arg, ectx_T *ectx)
|
||||
// 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);
|
||||
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,9 +394,12 @@ func_return(ectx_T *ectx)
|
||||
+ 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
|
||||
estack_pop();
|
||||
entry = estack_pop();
|
||||
if (entry != NULL)
|
||||
current_sctx.sc_sid = entry->es_save_sid;
|
||||
|
||||
if (handle_closure_in_use(ectx, TRUE) == FAIL)
|
||||
return FAIL;
|
||||
|
Reference in New Issue
Block a user