From 28aec66a5a651c22f482e7dcb513496606b439ec Mon Sep 17 00:00:00 2001 From: huangduirong Date: Thu, 29 Sep 2022 17:27:21 +0800 Subject: [PATCH] fix CVE-2022-3296 --- backport-CVE-2022-3296.patch | 634 +++++++++++++++++++++++++++++++++++ vim.spec | 9 +- 2 files changed, 642 insertions(+), 1 deletion(-) create mode 100644 backport-CVE-2022-3296.patch diff --git a/backport-CVE-2022-3296.patch b/backport-CVE-2022-3296.patch new file mode 100644 index 0000000..4d790bc --- /dev/null +++ b/backport-CVE-2022-3296.patch @@ -0,0 +1,634 @@ +From 96b9bf8f74af8abf1e30054f996708db7dc285be Mon Sep 17 00:00:00 2001 +From: Bram Moolenaar +Date: Sat, 24 Sep 2022 17:24:12 +0100 +Subject: patch 9.0.0577: buffer underflow with unexpected :finally + +Problem: Buffer underflow with unexpected :finally. +Solution: Check CSF_TRY can be found. +--- + src/ex_eval.c | 523 +++++++++++++++++----------------- + src/testdir/test_trycatch.vim | 22 ++ + 2 files changed, 282 insertions(+), 263 deletions(-) + +diff --git a/src/ex_eval.c b/src/ex_eval.c +index 5721b766e..77d6e8bb9 100644 +--- a/src/ex_eval.c ++++ b/src/ex_eval.c +@@ -1935,128 +1935,127 @@ ex_finally(exarg_T *eap) + if (cmdmod_error(FALSE)) + return; + +- if (cstack->cs_trylevel <= 0 || cstack->cs_idx < 0) ++ for (idx = cstack->cs_idx; idx >= 0; --idx) ++ if (cstack->cs_flags[idx] & CSF_TRY) ++ break; ++ if (cstack->cs_trylevel <= 0 || idx < 0) ++ { + eap->errmsg = _(e_finally_without_try); +- else ++ 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); +- 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 +- // finally clause can be executed. This overrules also a pending +- // ":continue", ":break", ":return", or ":finish". +- pending = CSTP_ERROR; +- } +- else +- idx = cstack->cs_idx; ++ eap->errmsg = get_end_emsg(cstack); ++ // Make this error pending, so that the commands in the following ++ // finally clause can be executed. This overrules also a pending ++ // ":continue", ":break", ":return", or ":finish". ++ pending = CSTP_ERROR; ++ } + +- if (cstack->cs_flags[idx] & CSF_FINALLY) ++ if (cstack->cs_flags[idx] & CSF_FINALLY) ++ { ++ // Give up for a multiple ":finally" and ignore it. ++ eap->errmsg = _(e_multiple_finally); ++ return; ++ } ++ rewind_conditionals(cstack, idx, CSF_WHILE | CSF_FOR, ++ &cstack->cs_looplevel); ++ ++ /* ++ * Don't do something when the corresponding try block never got active ++ * (because of an inactive surrounding conditional or after an error or ++ * interrupt or throw) or for a ":finally" without ":try" or a multiple ++ * ":finally". After every other error (did_emsg or the conditional ++ * errors detected above) or after an interrupt (got_int) or an ++ * exception (did_throw), the finally clause must be executed. ++ */ ++ skip = !(cstack->cs_flags[cstack->cs_idx] & CSF_TRUE); ++ ++ if (!skip) ++ { ++ // When debugging or a breakpoint was encountered, display the ++ // debug prompt (if not already done). The user then knows that the ++ // finally clause is executed. ++ if (dbg_check_skipped(eap)) + { +- // Give up for a multiple ":finally" and ignore it. +- eap->errmsg = _(e_multiple_finally); +- return; ++ // Handle a ">quit" debug command as if an interrupt had ++ // occurred before the ":finally". That is, discard the ++ // original exception and replace it by an interrupt ++ // exception. ++ (void)do_intthrow(cstack); + } +- rewind_conditionals(cstack, idx, CSF_WHILE | CSF_FOR, +- &cstack->cs_looplevel); + + /* +- * Don't do something when the corresponding try block never got active +- * (because of an inactive surrounding conditional or after an error or +- * interrupt or throw) or for a ":finally" without ":try" or a multiple +- * ":finally". After every other error (did_emsg or the conditional +- * errors detected above) or after an interrupt (got_int) or an +- * exception (did_throw), the finally clause must be executed. ++ * If there is a preceding catch clause and it caught the exception, ++ * finish the exception now. This happens also after errors except ++ * when this is a multiple ":finally" or one not within a ":try". ++ * After an error or interrupt, this also discards a pending ++ * ":continue", ":break", ":finish", or ":return" from the preceding ++ * try block or catch clause. + */ +- skip = !(cstack->cs_flags[cstack->cs_idx] & CSF_TRUE); ++ cleanup_conditionals(cstack, CSF_TRY, FALSE); + +- if (!skip) ++ if (cstack->cs_idx >= 0 ++ && (cstack->cs_flags[cstack->cs_idx] & CSF_TRY)) + { +- // When debugging or a breakpoint was encountered, display the +- // debug prompt (if not already done). The user then knows that the +- // finally clause is executed. +- if (dbg_check_skipped(eap)) +- { +- // Handle a ">quit" debug command as if an interrupt had +- // occurred before the ":finally". That is, discard the +- // original exception and replace it by an interrupt +- // exception. +- (void)do_intthrow(cstack); +- } +- +- /* +- * If there is a preceding catch clause and it caught the exception, +- * finish the exception now. This happens also after errors except +- * when this is a multiple ":finally" or one not within a ":try". +- * After an error or interrupt, this also discards a pending +- * ":continue", ":break", ":finish", or ":return" from the preceding +- * try block or catch clause. +- */ +- cleanup_conditionals(cstack, CSF_TRY, FALSE); ++ // Variables declared in the previous block can no longer be ++ // used. ++ leave_block(cstack); ++ enter_block(cstack); ++ } + +- if (cstack->cs_idx >= 0 +- && (cstack->cs_flags[cstack->cs_idx] & CSF_TRY)) ++ /* ++ * Make did_emsg, got_int, did_throw pending. If set, they overrule ++ * a pending ":continue", ":break", ":return", or ":finish". Then ++ * we have particularly to discard a pending return value (as done ++ * by the call to cleanup_conditionals() above when did_emsg or ++ * got_int is set). The pending values are restored by the ++ * ":endtry", except if there is a new error, interrupt, exception, ++ * ":continue", ":break", ":return", or ":finish" in the following ++ * finally clause. A missing ":endwhile", ":endfor" or ":endif" ++ * detected here is treated as if did_emsg and did_throw had ++ * already been set, respectively in case that the error is not ++ * converted to an exception, did_throw had already been unset. ++ * We must not set did_emsg here since that would suppress the ++ * error message. ++ */ ++ if (pending == CSTP_ERROR || did_emsg || got_int || did_throw) ++ { ++ if (cstack->cs_pending[cstack->cs_idx] == CSTP_RETURN) + { +- // Variables declared in the previous block can no longer be +- // used. +- leave_block(cstack); +- enter_block(cstack); ++ report_discard_pending(CSTP_RETURN, ++ cstack->cs_rettv[cstack->cs_idx]); ++ discard_pending_return(cstack->cs_rettv[cstack->cs_idx]); + } +- +- /* +- * Make did_emsg, got_int, did_throw pending. If set, they overrule +- * a pending ":continue", ":break", ":return", or ":finish". Then +- * we have particularly to discard a pending return value (as done +- * by the call to cleanup_conditionals() above when did_emsg or +- * got_int is set). The pending values are restored by the +- * ":endtry", except if there is a new error, interrupt, exception, +- * ":continue", ":break", ":return", or ":finish" in the following +- * finally clause. A missing ":endwhile", ":endfor" or ":endif" +- * detected here is treated as if did_emsg and did_throw had +- * already been set, respectively in case that the error is not +- * converted to an exception, did_throw had already been unset. +- * We must not set did_emsg here since that would suppress the +- * error message. +- */ +- if (pending == CSTP_ERROR || did_emsg || got_int || did_throw) +- { +- if (cstack->cs_pending[cstack->cs_idx] == CSTP_RETURN) +- { +- report_discard_pending(CSTP_RETURN, +- cstack->cs_rettv[cstack->cs_idx]); +- discard_pending_return(cstack->cs_rettv[cstack->cs_idx]); +- } +- if (pending == CSTP_ERROR && !did_emsg) +- pending |= (THROW_ON_ERROR) ? CSTP_THROW : 0; +- else +- pending |= did_throw ? CSTP_THROW : 0; +- pending |= did_emsg ? CSTP_ERROR : 0; +- pending |= got_int ? CSTP_INTERRUPT : 0; +- cstack->cs_pending[cstack->cs_idx] = pending; +- +- // It's mandatory that the current exception is stored in the +- // cstack so that it can be rethrown at the ":endtry" or be +- // discarded if the finally clause is left by a ":continue", +- // ":break", ":return", ":finish", error, interrupt, or another +- // exception. When emsg() is called for a missing ":endif" or +- // a missing ":endwhile"/":endfor" detected here, the +- // exception will be discarded. +- if (did_throw && cstack->cs_exception[cstack->cs_idx] +- != current_exception) +- internal_error("ex_finally()"); +- } +- +- /* +- * Set CSL_HAD_FINA, so do_cmdline() will reset did_emsg, +- * got_int, and did_throw and make the finally clause active. +- * This will happen after emsg() has been called for a missing +- * ":endif" or a missing ":endwhile"/":endfor" detected here, so +- * that the following finally clause will be executed even then. +- */ +- cstack->cs_lflags |= CSL_HAD_FINA; ++ if (pending == CSTP_ERROR && !did_emsg) ++ pending |= (THROW_ON_ERROR) ? CSTP_THROW : 0; ++ else ++ pending |= did_throw ? CSTP_THROW : 0; ++ pending |= did_emsg ? CSTP_ERROR : 0; ++ pending |= got_int ? CSTP_INTERRUPT : 0; ++ cstack->cs_pending[cstack->cs_idx] = pending; ++ ++ // It's mandatory that the current exception is stored in the ++ // cstack so that it can be rethrown at the ":endtry" or be ++ // discarded if the finally clause is left by a ":continue", ++ // ":break", ":return", ":finish", error, interrupt, or another ++ // exception. When emsg() is called for a missing ":endif" or ++ // a missing ":endwhile"/":endfor" detected here, the ++ // exception will be discarded. ++ if (did_throw && cstack->cs_exception[cstack->cs_idx] ++ != current_exception) ++ internal_error("ex_finally()"); + } ++ ++ /* ++ * Set CSL_HAD_FINA, so do_cmdline() will reset did_emsg, ++ * got_int, and did_throw and make the finally clause active. ++ * This will happen after emsg() has been called for a missing ++ * ":endif" or a missing ":endwhile"/":endfor" detected here, so ++ * that the following finally clause will be executed even then. ++ */ ++ cstack->cs_lflags |= CSL_HAD_FINA; + } + } + +@@ -2076,185 +2075,183 @@ ex_endtry(exarg_T *eap) + if (cmdmod_error(FALSE)) + return; + +- if (cstack->cs_trylevel <= 0 || cstack->cs_idx < 0) +- eap->errmsg = _(e_endtry_without_try); +- else ++ for (idx = cstack->cs_idx; idx >= 0; --idx) ++ if (cstack->cs_flags[idx] & CSF_TRY) ++ break; ++ if (cstack->cs_trylevel <= 0 || idx < 0) + { +- /* +- * Don't do something after an error, interrupt or throw in the try +- * block, catch clause, or finally clause preceding this ":endtry" or +- * when an error or interrupt occurred after a ":continue", ":break", +- * ":return", or ":finish" in a try block or catch clause preceding this +- * ":endtry" or when the try block never got active (because of an +- * inactive surrounding conditional or after an error or interrupt or +- * throw) or when there is a surrounding conditional and it has been +- * made inactive by a ":continue", ":break", ":return", or ":finish" in +- * the finally clause. The latter case need not be tested since then +- * anything pending has already been discarded. */ +- skip = did_emsg || got_int || did_throw ++ eap->errmsg = _(e_endtry_without_try); ++ return; ++ } ++ ++ /* ++ * Don't do something after an error, interrupt or throw in the try ++ * block, catch clause, or finally clause preceding this ":endtry" or ++ * when an error or interrupt occurred after a ":continue", ":break", ++ * ":return", or ":finish" in a try block or catch clause preceding this ++ * ":endtry" or when the try block never got active (because of an ++ * inactive surrounding conditional or after an error or interrupt or ++ * throw) or when there is a surrounding conditional and it has been ++ * made inactive by a ":continue", ":break", ":return", or ":finish" in ++ * the finally clause. The latter case need not be tested since then ++ * anything pending has already been discarded. */ ++ skip = did_emsg || got_int || did_throw + || !(cstack->cs_flags[cstack->cs_idx] & CSF_TRUE); + +- if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRY)) +- { +- eap->errmsg = get_end_emsg(cstack); ++ if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRY)) ++ { ++ eap->errmsg = get_end_emsg(cstack); + +- // 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, +- &cstack->cs_looplevel); +- skip = TRUE; ++ // Find the matching ":try" and report what's missing. ++ rewind_conditionals(cstack, idx, CSF_WHILE | CSF_FOR, ++ &cstack->cs_looplevel); ++ skip = TRUE; + +- /* +- * If an exception is being thrown, discard it to prevent it from +- * being rethrown at the end of this function. It would be +- * discarded by the error message, anyway. Resets did_throw. +- * This does not affect the script termination due to the error +- * since "trylevel" is decremented after emsg() has been called. +- */ +- if (did_throw) +- discard_current_exception(); ++ /* ++ * If an exception is being thrown, discard it to prevent it from ++ * being rethrown at the end of this function. It would be ++ * discarded by the error message, anyway. Resets did_throw. ++ * This does not affect the script termination due to the error ++ * since "trylevel" is decremented after emsg() has been called. ++ */ ++ if (did_throw) ++ discard_current_exception(); + +- // report eap->errmsg, also when there already was an error +- did_emsg = FALSE; +- } +- else +- { +- idx = cstack->cs_idx; ++ // report eap->errmsg, also when there already was an error ++ did_emsg = FALSE; ++ } ++ else ++ { ++ idx = cstack->cs_idx; + +- // Check the flags only when not in a skipped block. +- if (!skip && in_vim9script() ++ // Check the flags only when not in a skipped block. ++ if (!skip && in_vim9script() + && (cstack->cs_flags[idx] & (CSF_CATCH|CSF_FINALLY)) == 0) +- { +- // try/endtry without any catch or finally: give an error and +- // continue. +- eap->errmsg = _(e_missing_catch_or_finally); +- } +- +- /* +- * If we stopped with the exception currently being thrown at this +- * try conditional since we didn't know that it doesn't have +- * a finally clause, we need to rethrow it after closing the try +- * conditional. +- */ +- if (did_throw && (cstack->cs_flags[idx] & CSF_TRUE) +- && !(cstack->cs_flags[idx] & CSF_FINALLY)) +- rethrow = TRUE; +- } +- +- // If there was no finally clause, show the user when debugging or +- // a breakpoint was encountered that the end of the try conditional has +- // been reached: display the debug prompt (if not already done). Do +- // this on normal control flow or when an exception was thrown, but not +- // on an interrupt or error not converted to an exception or when +- // a ":break", ":continue", ":return", or ":finish" is pending. These +- // actions are carried out immediately. +- if ((rethrow || (!skip +- && !(cstack->cs_flags[idx] & CSF_FINALLY) +- && !cstack->cs_pending[idx])) +- && dbg_check_skipped(eap)) + { +- // Handle a ">quit" debug command as if an interrupt had occurred +- // before the ":endtry". That is, throw an interrupt exception and +- // set "skip" and "rethrow". +- if (got_int) +- { +- skip = TRUE; +- (void)do_intthrow(cstack); +- // The do_intthrow() call may have reset did_throw or +- // cstack->cs_pending[idx]. +- rethrow = FALSE; +- if (did_throw && !(cstack->cs_flags[idx] & CSF_FINALLY)) +- rethrow = TRUE; +- } ++ // try/endtry without any catch or finally: give an error and ++ // continue. ++ eap->errmsg = _(e_missing_catch_or_finally); + } + + /* +- * If a ":return" is pending, we need to resume it after closing the +- * try conditional; remember the return value. If there was a finally +- * clause making an exception pending, we need to rethrow it. Make it +- * the exception currently being thrown. ++ * If we stopped with the exception currently being thrown at this ++ * try conditional since we didn't know that it doesn't have ++ * a finally clause, we need to rethrow it after closing the try ++ * conditional. + */ +- if (!skip) ++ if (did_throw && (cstack->cs_flags[idx] & CSF_TRUE) ++ && !(cstack->cs_flags[idx] & CSF_FINALLY)) ++ rethrow = TRUE; ++ } ++ ++ // If there was no finally clause, show the user when debugging or ++ // a breakpoint was encountered that the end of the try conditional has ++ // been reached: display the debug prompt (if not already done). Do ++ // this on normal control flow or when an exception was thrown, but not ++ // on an interrupt or error not converted to an exception or when ++ // a ":break", ":continue", ":return", or ":finish" is pending. These ++ // actions are carried out immediately. ++ if ((rethrow || (!skip && !(cstack->cs_flags[idx] & CSF_FINALLY) ++ && !cstack->cs_pending[idx])) ++ && dbg_check_skipped(eap)) ++ { ++ // Handle a ">quit" debug command as if an interrupt had occurred ++ // before the ":endtry". That is, throw an interrupt exception and ++ // set "skip" and "rethrow". ++ if (got_int) + { +- pending = cstack->cs_pending[idx]; +- cstack->cs_pending[idx] = CSTP_NONE; +- if (pending == CSTP_RETURN) +- rettv = cstack->cs_rettv[idx]; +- else if (pending & CSTP_THROW) +- current_exception = cstack->cs_exception[idx]; ++ skip = TRUE; ++ (void)do_intthrow(cstack); ++ // The do_intthrow() call may have reset did_throw or ++ // cstack->cs_pending[idx]. ++ rethrow = FALSE; ++ if (did_throw && !(cstack->cs_flags[idx] & CSF_FINALLY)) ++ rethrow = TRUE; + } ++ } + +- /* +- * Discard anything pending on an error, interrupt, or throw in the +- * finally clause. If there was no ":finally", discard a pending +- * ":continue", ":break", ":return", or ":finish" if an error or +- * interrupt occurred afterwards, but before the ":endtry" was reached. +- * If an exception was caught by the last of the catch clauses and there +- * was no finally clause, finish the exception now. This happens also +- * after errors except when this ":endtry" is not within a ":try". +- * Restore "emsg_silent" if it has been reset by this try conditional. +- */ +- (void)cleanup_conditionals(cstack, CSF_TRY | CSF_SILENT, TRUE); ++ /* ++ * If a ":return" is pending, we need to resume it after closing the ++ * try conditional; remember the return value. If there was a finally ++ * clause making an exception pending, we need to rethrow it. Make it ++ * the exception currently being thrown. ++ */ ++ if (!skip) ++ { ++ pending = cstack->cs_pending[idx]; ++ cstack->cs_pending[idx] = CSTP_NONE; ++ if (pending == CSTP_RETURN) ++ rettv = cstack->cs_rettv[idx]; ++ else if (pending & CSTP_THROW) ++ current_exception = cstack->cs_exception[idx]; ++ } + +- if (cstack->cs_idx >= 0 +- && (cstack->cs_flags[cstack->cs_idx] & CSF_TRY)) +- leave_block(cstack); +- --cstack->cs_trylevel; ++ /* ++ * Discard anything pending on an error, interrupt, or throw in the ++ * finally clause. If there was no ":finally", discard a pending ++ * ":continue", ":break", ":return", or ":finish" if an error or ++ * interrupt occurred afterwards, but before the ":endtry" was reached. ++ * If an exception was caught by the last of the catch clauses and there ++ * was no finally clause, finish the exception now. This happens also ++ * after errors except when this ":endtry" is not within a ":try". ++ * Restore "emsg_silent" if it has been reset by this try conditional. ++ */ ++ (void)cleanup_conditionals(cstack, CSF_TRY | CSF_SILENT, TRUE); + +- if (!skip) +- { +- report_resume_pending(pending, ++ if (cstack->cs_idx >= 0 && (cstack->cs_flags[cstack->cs_idx] & CSF_TRY)) ++ leave_block(cstack); ++ --cstack->cs_trylevel; ++ ++ if (!skip) ++ { ++ report_resume_pending(pending, + (pending == CSTP_RETURN) ? rettv : + (pending & CSTP_THROW) ? (void *)current_exception : NULL); +- switch (pending) +- { +- case CSTP_NONE: +- break; ++ switch (pending) ++ { ++ case CSTP_NONE: ++ break; + +- // Reactivate a pending ":continue", ":break", ":return", +- // ":finish" from the try block or a catch clause of this try +- // conditional. This is skipped, if there was an error in an +- // (unskipped) conditional command or an interrupt afterwards +- // or if the finally clause is present and executed a new error, +- // interrupt, throw, ":continue", ":break", ":return", or +- // ":finish". +- case CSTP_CONTINUE: +- ex_continue(eap); +- break; +- case CSTP_BREAK: +- ex_break(eap); +- break; +- case CSTP_RETURN: +- do_return(eap, FALSE, FALSE, rettv); +- break; +- case CSTP_FINISH: +- do_finish(eap, FALSE); +- break; ++ // Reactivate a pending ":continue", ":break", ":return", ++ // ":finish" from the try block or a catch clause of this try ++ // conditional. This is skipped, if there was an error in an ++ // (unskipped) conditional command or an interrupt afterwards ++ // or if the finally clause is present and executed a new error, ++ // interrupt, throw, ":continue", ":break", ":return", or ++ // ":finish". ++ case CSTP_CONTINUE: ++ ex_continue(eap); ++ break; ++ case CSTP_BREAK: ++ ex_break(eap); ++ break; ++ case CSTP_RETURN: ++ do_return(eap, FALSE, FALSE, rettv); ++ break; ++ case CSTP_FINISH: ++ do_finish(eap, FALSE); ++ break; + +- // When the finally clause was entered due to an error, +- // interrupt or throw (as opposed to a ":continue", ":break", +- // ":return", or ":finish"), restore the pending values of +- // did_emsg, got_int, and did_throw. This is skipped, if there +- // was a new error, interrupt, throw, ":continue", ":break", +- // ":return", or ":finish". in the finally clause. +- default: +- if (pending & CSTP_ERROR) +- did_emsg = TRUE; +- if (pending & CSTP_INTERRUPT) +- got_int = TRUE; +- if (pending & CSTP_THROW) +- rethrow = TRUE; +- break; +- } ++ // When the finally clause was entered due to an error, ++ // interrupt or throw (as opposed to a ":continue", ":break", ++ // ":return", or ":finish"), restore the pending values of ++ // did_emsg, got_int, and did_throw. This is skipped, if there ++ // was a new error, interrupt, throw, ":continue", ":break", ++ // ":return", or ":finish". in the finally clause. ++ default: ++ if (pending & CSTP_ERROR) ++ did_emsg = TRUE; ++ if (pending & CSTP_INTERRUPT) ++ got_int = TRUE; ++ if (pending & CSTP_THROW) ++ rethrow = TRUE; ++ break; + } +- +- if (rethrow) +- // Rethrow the current exception (within this cstack). +- do_throw(cstack); + } ++ ++ if (rethrow) ++ // Rethrow the current exception (within this cstack). ++ do_throw(cstack); + } + + /* +diff --git a/src/testdir/test_trycatch.vim b/src/testdir/test_trycatch.vim +index aa42205a1..28cd39f04 100644 +--- a/src/testdir/test_trycatch.vim ++++ b/src/testdir/test_trycatch.vim +@@ -3,6 +3,7 @@ + + source check.vim + source shared.vim ++import './vim9.vim' as v9 + + "------------------------------------------------------------------------------- + " 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 | while v:true | endtry', 'E170:') + 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 + + " Test for verbose messages with :try :catch, and :finally {{{1 +-- +2.23.0 + diff --git a/vim.spec b/vim.spec index ff0b657..c0e2acc 100644 --- a/vim.spec +++ b/vim.spec @@ -12,7 +12,7 @@ Name: vim Epoch: 2 Version: 9.0 -Release: 16 +Release: 17 Summary: Vim is a highly configurable text editor for efficiently creating and changing any kind of text. License: Vim and MIT URL: http://www.vim.org @@ -66,6 +66,7 @@ Patch6035: backport-CVE-2022-3153.patch Patch6036: backport-CVE-2022-3234.patch Patch6037: backport-CVE-2022-3235.patch Patch6038: backport-CVE-2022-3256.patch +Patch6039: backport-CVE-2022-3296.patch Patch9000: bugfix-rm-modify-info-version.patch @@ -464,6 +465,12 @@ LC_ALL=en_US.UTF-8 make -j1 test %{_mandir}/man1/evim.* %changelog +* Thu Sep 29 2022 huangduirong - 2:9.0-17 +- Type:CVE +- ID:CVE-2022-3296 +- SUG:NA +- DESC:fix CVE-2022-3296 + * Fri Sep 23 2022 dongyuzhen - 2:9.0-16 - Type:CVE - ID:CVE-2022-3256 -- Gitee