mirror of
https://github.com/vim/vim.git
synced 2025-09-25 03:54:15 -04:00
patch 8.2.2051: Vim9: crash when aborting a user function call
Problem: Vim9: crash when aborting a user function call. Solution: Do not use the return value when aboring. (closes #7372)
This commit is contained in:
@@ -1468,6 +1468,29 @@ def Test_nested_closure_fails()
|
|||||||
CheckScriptFailure(lines, 'E1012:')
|
CheckScriptFailure(lines, 'E1012:')
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
def Test_failure_in_called_function()
|
||||||
|
# this was using the frame index as the return value
|
||||||
|
var lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
au TerminalWinOpen * eval [][0]
|
||||||
|
def PopupTerm(a: any)
|
||||||
|
# make sure typvals on stack are string
|
||||||
|
['a', 'b', 'c', 'd', 'e', 'f', 'g']->join()
|
||||||
|
FireEvent()
|
||||||
|
enddef
|
||||||
|
def FireEvent()
|
||||||
|
do TerminalWinOpen
|
||||||
|
enddef
|
||||||
|
# use try/catch to make eval fail
|
||||||
|
try
|
||||||
|
call PopupTerm(0)
|
||||||
|
catch
|
||||||
|
endtry
|
||||||
|
au! TerminalWinOpen
|
||||||
|
END
|
||||||
|
CheckScriptSuccess(lines)
|
||||||
|
enddef
|
||||||
|
|
||||||
def Test_nested_lambda()
|
def Test_nested_lambda()
|
||||||
var lines =<< trim END
|
var lines =<< trim END
|
||||||
vim9script
|
vim9script
|
||||||
|
@@ -750,6 +750,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
2051,
|
||||||
/**/
|
/**/
|
||||||
2050,
|
2050,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -467,6 +467,7 @@ funcstack_check_refcount(funcstack_T *funcstack)
|
|||||||
func_return(ectx_T *ectx)
|
func_return(ectx_T *ectx)
|
||||||
{
|
{
|
||||||
int idx;
|
int idx;
|
||||||
|
int ret_idx;
|
||||||
dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
|
dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
|
||||||
+ ectx->ec_dfunc_idx;
|
+ ectx->ec_dfunc_idx;
|
||||||
int argcount = ufunc_argcount(dfunc->df_ufunc);
|
int argcount = ufunc_argcount(dfunc->df_ufunc);
|
||||||
@@ -490,6 +491,12 @@ func_return(ectx_T *ectx)
|
|||||||
idx < ectx->ec_stack.ga_len - 1; ++idx)
|
idx < ectx->ec_stack.ga_len - 1; ++idx)
|
||||||
clear_tv(STACK_TV(idx));
|
clear_tv(STACK_TV(idx));
|
||||||
|
|
||||||
|
// The return value should be on top of the stack. However, when aborting
|
||||||
|
// it may not be there and ec_frame_idx is the top of the stack.
|
||||||
|
ret_idx = ectx->ec_stack.ga_len - 1;
|
||||||
|
if (ret_idx == ectx->ec_frame_idx + 4)
|
||||||
|
ret_idx = 0;
|
||||||
|
|
||||||
// Restore the previous frame.
|
// Restore the previous frame.
|
||||||
ectx->ec_dfunc_idx = STACK_TV(ectx->ec_frame_idx)->vval.v_number;
|
ectx->ec_dfunc_idx = STACK_TV(ectx->ec_frame_idx)->vval.v_number;
|
||||||
ectx->ec_iidx = STACK_TV(ectx->ec_frame_idx + 1)->vval.v_number;
|
ectx->ec_iidx = STACK_TV(ectx->ec_frame_idx + 1)->vval.v_number;
|
||||||
@@ -501,11 +508,16 @@ func_return(ectx_T *ectx)
|
|||||||
dfunc = ((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx;
|
dfunc = ((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx;
|
||||||
ectx->ec_instr = dfunc->df_instr;
|
ectx->ec_instr = dfunc->df_instr;
|
||||||
|
|
||||||
// Reset the stack to the position before the call, move the return value
|
if (ret_idx > 0)
|
||||||
// to the top of the stack.
|
{
|
||||||
idx = ectx->ec_stack.ga_len - 1;
|
// Reset the stack to the position before the call, with a spot for the
|
||||||
ectx->ec_stack.ga_len = top + 1;
|
// return value, moved there from above the frame.
|
||||||
*STACK_TV_BOT(-1) = *STACK_TV(idx);
|
ectx->ec_stack.ga_len = top + 1;
|
||||||
|
*STACK_TV_BOT(-1) = *STACK_TV(ret_idx);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
// Reset the stack to the position before the call.
|
||||||
|
ectx->ec_stack.ga_len = top;
|
||||||
|
|
||||||
funcdepth_decrement();
|
funcdepth_decrement();
|
||||||
return OK;
|
return OK;
|
||||||
|
Reference in New Issue
Block a user