*: Make sure that !did_throw implies !current_exception

Fixes #7876
This commit is contained in:
ZyX
2018-01-21 03:27:48 +03:00
parent f8d2aef4f2
commit 79b4b6fc86
5 changed files with 44 additions and 18 deletions

View File

@@ -47,6 +47,9 @@ typedef struct {
/// @param[out] tstate Location where try state should be saved. /// @param[out] tstate Location where try state should be saved.
void try_enter(TryState *const tstate) void try_enter(TryState *const tstate)
{ {
// TODO(ZyX-I): Check whether try_enter()/try_leave() may use
// enter_cleanup()/leave_cleanup(). Or
// save_dbg_stuff()/restore_dbg_stuff().
*tstate = (TryState) { *tstate = (TryState) {
.current_exception = current_exception, .current_exception = current_exception,
.msg_list = (const struct msglist *const *)msg_list, .msg_list = (const struct msglist *const *)msg_list,

View File

@@ -403,13 +403,12 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline,
/* /*
* "did_throw" will be set to TRUE when an exception is being thrown. * "did_throw" will be set to TRUE when an exception is being thrown.
*/ */
did_throw = FALSE; did_throw = false;
/* current_exception = NULL;
* "did_emsg" will be set to TRUE when emsg() is used, in which case we // "did_emsg" will be set to TRUE when emsg() is used, in which case we
* cancel the whole command line, and any if/endif or loop. // cancel the whole command line, and any if/endif or loop.
* If force_abort is set, we cancel everything. // If force_abort is set, we cancel everything.
*/ did_emsg = false;
did_emsg = FALSE;
/* /*
* KeyTyped is only set when calling vgetc(). Reset it here when not * KeyTyped is only set when calling vgetc(). Reset it here when not
@@ -715,10 +714,11 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline,
*/ */
if (cstack.cs_lflags & CSL_HAD_FINA) { if (cstack.cs_lflags & CSL_HAD_FINA) {
cstack.cs_lflags &= ~CSL_HAD_FINA; cstack.cs_lflags &= ~CSL_HAD_FINA;
report_make_pending(cstack.cs_pending[cstack.cs_idx] report_make_pending((cstack.cs_pending[cstack.cs_idx]
& (CSTP_ERROR | CSTP_INTERRUPT | CSTP_THROW), & (CSTP_ERROR | CSTP_INTERRUPT | CSTP_THROW)),
did_throw ? (void *)current_exception : NULL); (did_throw ? (void *)current_exception : NULL));
did_emsg = got_int = did_throw = FALSE; did_emsg = got_int = did_throw = false;
current_exception = NULL;
cstack.cs_flags[cstack.cs_idx] |= CSF_ACTIVE | CSF_FINALLY; cstack.cs_flags[cstack.cs_idx] |= CSF_ACTIVE | CSF_FINALLY;
} }
@@ -1782,13 +1782,14 @@ static char_u * do_one_cmd(char_u **cmdlinep,
)); ));
/* forced commands */ // Forced commands.
if (*p == '!' && ea.cmdidx != CMD_substitute if (*p == '!' && ea.cmdidx != CMD_substitute
&& ea.cmdidx != CMD_smagic && ea.cmdidx != CMD_snomagic) { && ea.cmdidx != CMD_smagic && ea.cmdidx != CMD_snomagic) {
++p; p++;
ea.forceit = TRUE; ea.forceit = true;
} else } else {
ea.forceit = FALSE; ea.forceit = false;
}
/* /*
* 6. Parse arguments. * 6. Parse arguments.

View File

@@ -1426,6 +1426,10 @@ void ex_catch(exarg_T *eap)
if (cstack->cs_exception[cstack->cs_idx] != current_exception) { if (cstack->cs_exception[cstack->cs_idx] != current_exception) {
internal_error("ex_catch()"); internal_error("ex_catch()");
} }
// Discarding current_exceptions happens based on what is stored in
// cstack->cs_exception, *all* calls to discard_current_exception() are
// (and must be) guarded by did_throw which was already unset above.
current_exception = NULL;
} else { } else {
/* /*
* If there is a preceding catch clause and it caught the exception, * If there is a preceding catch clause and it caught the exception,
@@ -1785,7 +1789,8 @@ void enter_cleanup(cleanup_T *csp)
cause_abort = FALSE; cause_abort = FALSE;
} }
} }
did_emsg = got_int = did_throw = need_rethrow = FALSE; did_emsg = got_int = did_throw = need_rethrow = false;
current_exception = NULL;
/* Report if required by the 'verbose' option or when debugging. */ /* Report if required by the 'verbose' option or when debugging. */
report_make_pending(pending, csp->exception); report_make_pending(pending, csp->exception);

View File

@@ -325,7 +325,8 @@ EXTERN except_T *current_exception;
* did_throw: An exception is being thrown. Reset when the exception is caught * did_throw: An exception is being thrown. Reset when the exception is caught
* or as long as it is pending in a finally clause. * or as long as it is pending in a finally clause.
*/ */
EXTERN int did_throw INIT(= FALSE); // FIXME: Replace did_throw checks with current_exception checks.
EXTERN int did_throw INIT(= false);
/* /*
* need_rethrow: set to TRUE when a throw that cannot be handled in do_cmdline() * need_rethrow: set to TRUE when a throw that cannot be handled in do_cmdline()

View File

@@ -737,6 +737,22 @@ describe('Command-line coloring', function()
feed('<CR><CR>') feed('<CR><CR>')
eq('', meths.get_var('out')) eq('', meths.get_var('out'))
end) end)
it('does not crash when callback has caught not-a-editor-command exception',
function()
source([[
function CaughtExc(cmdline) abort
try
gibberish
catch
" Do nothing
endtry
return []
endfunction
]])
set_color_cb('CaughtExc')
start_prompt('1')
eq(1, meths.eval('1'))
end)
end) end)
describe('Ex commands coloring support', function() describe('Ex commands coloring support', function()
it('works', function() it('works', function()