*: 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.
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) {
.current_exception = current_exception,
.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 = FALSE;
/*
* "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.
* If force_abort is set, we cancel everything.
*/
did_emsg = FALSE;
did_throw = false;
current_exception = NULL;
// "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.
// If force_abort is set, we cancel everything.
did_emsg = false;
/*
* 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) {
cstack.cs_lflags &= ~CSL_HAD_FINA;
report_make_pending(cstack.cs_pending[cstack.cs_idx]
& (CSTP_ERROR | CSTP_INTERRUPT | CSTP_THROW),
did_throw ? (void *)current_exception : NULL);
did_emsg = got_int = did_throw = FALSE;
report_make_pending((cstack.cs_pending[cstack.cs_idx]
& (CSTP_ERROR | CSTP_INTERRUPT | CSTP_THROW)),
(did_throw ? (void *)current_exception : NULL));
did_emsg = got_int = did_throw = false;
current_exception = NULL;
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
&& ea.cmdidx != CMD_smagic && ea.cmdidx != CMD_snomagic) {
++p;
ea.forceit = TRUE;
} else
ea.forceit = FALSE;
p++;
ea.forceit = true;
} else {
ea.forceit = false;
}
/*
* 6. Parse arguments.

View File

@@ -1426,6 +1426,10 @@ void ex_catch(exarg_T *eap)
if (cstack->cs_exception[cstack->cs_idx] != current_exception) {
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 {
/*
* 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;
}
}
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_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
* 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()

View File

@@ -737,6 +737,22 @@ describe('Command-line coloring', function()
feed('<CR><CR>')
eq('', meths.get_var('out'))
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)
describe('Ex commands coloring support', function()
it('works', function()