Skip to content

Commit 77e5dcc

Browse files
committed
patch 8.2.1704: Vim9: crash in for loop when autoload script has an error
Problem: Vim9: crash in for loop when autoload script has an error. Solution: Reset suppress_errthrow. Check for NULL list. (closes #6967)
1 parent 213da55 commit 77e5dcc

3 files changed

Lines changed: 50 additions & 1 deletion

File tree

src/testdir/test_vim9_script.vim

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3353,6 +3353,45 @@ def Test_vim9_autoload()
33533353
&rtp = save_rtp
33543354
enddef
33553355

3356+
" This was causing a crash because suppress_errthrow wasn't reset.
3357+
def Test_vim9_autoload_error()
3358+
let lines =<< trim END
3359+
vim9script
3360+
def crash#func()
3361+
try
3362+
for x in List()
3363+
endfor
3364+
catch
3365+
endtry
3366+
g:ok = true
3367+
enddef
3368+
fu List()
3369+
invalid
3370+
endfu
3371+
try
3372+
invalid
3373+
catch /wontmatch/
3374+
endtry
3375+
END
3376+
call mkdir('Xruntime/autoload', 'p')
3377+
call writefile(lines, 'Xruntime/autoload/crash.vim')
3378+
3379+
# run in a separate Vim to avoid the side effects of assert_fails()
3380+
lines =<< trim END
3381+
exe 'set rtp^=' .. getcwd() .. '/Xruntime'
3382+
call crash#func()
3383+
call writefile(['ok'], 'Xdidit')
3384+
qall
3385+
END
3386+
writefile(lines, 'Xscript')
3387+
RunVim([], [], '-S Xscript')
3388+
assert_equal(['ok'], readfile('Xdidit'))
3389+
3390+
delete('Xdidit')
3391+
delete('Xscript')
3392+
delete('Xruntime', 'rf')
3393+
enddef
3394+
33563395
def Test_script_var_in_autocmd()
33573396
# using a script variable from an autocommand, defined in a :def function in a
33583397
# legacy Vim script, cannot check the variable type.

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,8 @@ static char *(features[]) =
750750

751751
static int included_patches[] =
752752
{ /* Add new patch number below this line */
753+
/**/
754+
1704,
753755
/**/
754756
1703,
755757
/**/

src/vim9execute.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,7 @@ call_def_function(
761761
sctx_T save_current_sctx = current_sctx;
762762
int breakcheck_count = 0;
763763
int called_emsg_before = called_emsg;
764+
int save_suppress_errthrow = suppress_errthrow;
764765

765766
// Get pointer to item in the stack.
766767
#define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx)
@@ -907,6 +908,9 @@ call_def_function(
907908
current_sctx = ufunc->uf_script_ctx;
908909
current_sctx.sc_version = SCRIPT_VERSION_VIM9;
909910

911+
// Do turn errors into exceptions.
912+
suppress_errthrow = FALSE;
913+
910914
// Decide where to start execution, handles optional arguments.
911915
init_instr_idx(ufunc, argc, &ectx);
912916

@@ -1884,7 +1888,8 @@ call_def_function(
18841888
// push the next item from the list
18851889
if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
18861890
goto failed;
1887-
if (++idxtv->vval.v_number >= list->lv_len)
1891+
++idxtv->vval.v_number;
1892+
if (list == NULL || idxtv->vval.v_number >= list->lv_len)
18881893
// past the end of the list, jump to "endfor"
18891894
ectx.ec_iidx = iptr->isn_arg.forloop.for_end;
18901895
else if (list->lv_first == &range_list_item)
@@ -2713,6 +2718,9 @@ call_def_function(
27132718
vim_free(ectx.ec_stack.ga_data);
27142719
vim_free(ectx.ec_trystack.ga_data);
27152720

2721+
// Not sure if this is necessary.
2722+
suppress_errthrow = save_suppress_errthrow;
2723+
27162724
if (ret != OK && called_emsg == called_emsg_before)
27172725
semsg(_(e_unknown_error_while_executing_str),
27182726
printable_func_name(ufunc));

0 commit comments

Comments
 (0)