0
0
mirror of https://github.com/vim/vim.git synced 2025-09-27 04:14:06 -04:00

patch 9.0.0577: buffer underflow with unexpected :finally

Problem:    Buffer underflow with unexpected :finally.
Solution:   Check CSF_TRY can be found.
This commit is contained in:
Bram Moolenaar
2022-09-24 17:24:12 +01:00
parent b2209f213e
commit 96b9bf8f74
3 changed files with 291 additions and 270 deletions

View File

@@ -1935,23 +1935,23 @@ ex_finally(exarg_T *eap)
if (cmdmod_error(FALSE)) if (cmdmod_error(FALSE))
return; return;
if (cstack->cs_trylevel <= 0 || cstack->cs_idx < 0) for (idx = cstack->cs_idx; idx >= 0; --idx)
eap->errmsg = _(e_finally_without_try); if (cstack->cs_flags[idx] & CSF_TRY)
else break;
if (cstack->cs_trylevel <= 0 || idx < 0)
{ {
eap->errmsg = _(e_finally_without_try);
return;
}
if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRY)) if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRY))
{ {
eap->errmsg = get_end_emsg(cstack); eap->errmsg = get_end_emsg(cstack);
for (idx = cstack->cs_idx - 1; idx > 0; --idx)
if (cstack->cs_flags[idx] & CSF_TRY)
break;
// Make this error pending, so that the commands in the following // Make this error pending, so that the commands in the following
// finally clause can be executed. This overrules also a pending // finally clause can be executed. This overrules also a pending
// ":continue", ":break", ":return", or ":finish". // ":continue", ":break", ":return", or ":finish".
pending = CSTP_ERROR; pending = CSTP_ERROR;
} }
else
idx = cstack->cs_idx;
if (cstack->cs_flags[idx] & CSF_FINALLY) if (cstack->cs_flags[idx] & CSF_FINALLY)
{ {
@@ -2057,7 +2057,6 @@ ex_finally(exarg_T *eap)
*/ */
cstack->cs_lflags |= CSL_HAD_FINA; cstack->cs_lflags |= CSL_HAD_FINA;
} }
}
} }
/* /*
@@ -2076,10 +2075,15 @@ ex_endtry(exarg_T *eap)
if (cmdmod_error(FALSE)) if (cmdmod_error(FALSE))
return; return;
if (cstack->cs_trylevel <= 0 || cstack->cs_idx < 0) for (idx = cstack->cs_idx; idx >= 0; --idx)
eap->errmsg = _(e_endtry_without_try); if (cstack->cs_flags[idx] & CSF_TRY)
else break;
if (cstack->cs_trylevel <= 0 || idx < 0)
{ {
eap->errmsg = _(e_endtry_without_try);
return;
}
/* /*
* Don't do something after an error, interrupt or throw in the try * Don't do something after an error, interrupt or throw in the try
* block, catch clause, or finally clause preceding this ":endtry" or * block, catch clause, or finally clause preceding this ":endtry" or
@@ -2099,10 +2103,6 @@ ex_endtry(exarg_T *eap)
eap->errmsg = get_end_emsg(cstack); eap->errmsg = get_end_emsg(cstack);
// Find the matching ":try" and report what's missing. // Find the matching ":try" and report what's missing.
idx = cstack->cs_idx;
do
--idx;
while (idx > 0 && !(cstack->cs_flags[idx] & CSF_TRY));
rewind_conditionals(cstack, idx, CSF_WHILE | CSF_FOR, rewind_conditionals(cstack, idx, CSF_WHILE | CSF_FOR,
&cstack->cs_looplevel); &cstack->cs_looplevel);
skip = TRUE; skip = TRUE;
@@ -2151,8 +2151,7 @@ ex_endtry(exarg_T *eap)
// on an interrupt or error not converted to an exception or when // on an interrupt or error not converted to an exception or when
// a ":break", ":continue", ":return", or ":finish" is pending. These // a ":break", ":continue", ":return", or ":finish" is pending. These
// actions are carried out immediately. // actions are carried out immediately.
if ((rethrow || (!skip if ((rethrow || (!skip && !(cstack->cs_flags[idx] & CSF_FINALLY)
&& !(cstack->cs_flags[idx] & CSF_FINALLY)
&& !cstack->cs_pending[idx])) && !cstack->cs_pending[idx]))
&& dbg_check_skipped(eap)) && dbg_check_skipped(eap))
{ {
@@ -2199,8 +2198,7 @@ ex_endtry(exarg_T *eap)
*/ */
(void)cleanup_conditionals(cstack, CSF_TRY | CSF_SILENT, TRUE); (void)cleanup_conditionals(cstack, CSF_TRY | CSF_SILENT, TRUE);
if (cstack->cs_idx >= 0 if (cstack->cs_idx >= 0 && (cstack->cs_flags[cstack->cs_idx] & CSF_TRY))
&& (cstack->cs_flags[cstack->cs_idx] & CSF_TRY))
leave_block(cstack); leave_block(cstack);
--cstack->cs_trylevel; --cstack->cs_trylevel;
@@ -2254,7 +2252,6 @@ ex_endtry(exarg_T *eap)
if (rethrow) if (rethrow)
// Rethrow the current exception (within this cstack). // Rethrow the current exception (within this cstack).
do_throw(cstack); do_throw(cstack);
}
} }
/* /*

View File

@@ -3,6 +3,7 @@
source check.vim source check.vim
source shared.vim source shared.vim
import './vim9.vim' as v9
"------------------------------------------------------------------------------- "-------------------------------------------------------------------------------
" Test environment {{{1 " Test environment {{{1
@@ -2008,6 +2009,27 @@ func Test_try_catch_errors()
call assert_fails('try | for i in range(5) | endif | endtry', 'E580:') call assert_fails('try | for i in range(5) | endif | endtry', 'E580:')
call assert_fails('try | while v:true | endtry', 'E170:') call assert_fails('try | while v:true | endtry', 'E170:')
call assert_fails('try | if v:true | endtry', 'E171:') call assert_fails('try | if v:true | endtry', 'E171:')
" this was using a negative index in cstack[]
let lines =<< trim END
try
for
if
endwhile
if
finally
END
call v9.CheckScriptFailure(lines, 'E690:')
let lines =<< trim END
try
for
if
endwhile
if
endtry
END
call v9.CheckScriptFailure(lines, 'E690:')
endfunc endfunc
" Test for verbose messages with :try :catch, and :finally {{{1 " Test for verbose messages with :try :catch, and :finally {{{1

View File

@@ -699,6 +699,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 */
/**/
577,
/**/ /**/
576, 576,
/**/ /**/