0
0
mirror of https://github.com/vim/vim.git synced 2025-09-23 03:43:49 -04:00

patch 8.2.2539: Vim9: return from finally block causes a hang

Problem:    Vim9: return from finally block causes a hang.
Solution:   Store both the finally and endtry indexes. (closes #7885)
This commit is contained in:
Bram Moolenaar
2021-02-21 21:32:45 +01:00
parent 21578271bb
commit 7e82c5f338
6 changed files with 89 additions and 38 deletions

View File

@@ -26,8 +26,9 @@
typedef struct {
int tcd_frame_idx; // ec_frame_idx at ISN_TRY
int tcd_stack_len; // size of ectx.ec_stack at ISN_TRY
int tcd_catch_idx; // instruction of the first catch
int tcd_finally_idx; // instruction of the finally block or :endtry
int tcd_catch_idx; // instruction of the first :catch or :finally
int tcd_finally_idx; // instruction of the :finally block or zero
int tcd_endtry_idx; // instruction of the :endtry
int tcd_caught; // catch block entered
int tcd_cont; // :continue encountered, jump here
int tcd_return; // when TRUE return from end of :finally
@@ -2517,10 +2518,9 @@ call_def_function(
+ trystack->ga_len - 1;
if (trycmd != NULL
&& trycmd->tcd_frame_idx == ectx.ec_frame_idx
&& ectx.ec_instr[trycmd->tcd_finally_idx]
.isn_type != ISN_ENDTRY)
&& trycmd->tcd_finally_idx != 0)
{
// jump to ":finally"
// jump to ":finally" once
ectx.ec_iidx = trycmd->tcd_finally_idx;
trycmd->tcd_return = TRUE;
}
@@ -2665,8 +2665,9 @@ call_def_function(
CLEAR_POINTER(trycmd);
trycmd->tcd_frame_idx = ectx.ec_frame_idx;
trycmd->tcd_stack_len = ectx.ec_stack.ga_len;
trycmd->tcd_catch_idx = iptr->isn_arg.try.try_catch;
trycmd->tcd_finally_idx = iptr->isn_arg.try.try_finally;
trycmd->tcd_catch_idx = iptr->isn_arg.try.try_ref->try_catch;
trycmd->tcd_finally_idx = iptr->isn_arg.try.try_ref->try_finally;
trycmd->tcd_endtry_idx = iptr->isn_arg.try.try_ref->try_endtry;
}
break;
@@ -2731,13 +2732,26 @@ call_def_function(
trycmd = ((trycmd_T *)trystack->ga_data)
+ trystack->ga_len - i;
trycmd->tcd_cont = iidx;
iidx = trycmd->tcd_finally_idx;
iidx = trycmd->tcd_finally_idx == 0
? trycmd->tcd_endtry_idx : trycmd->tcd_finally_idx;
}
// jump to :finally or :endtry of current try statement
ectx.ec_iidx = iidx;
}
break;
case ISN_FINALLY:
{
garray_T *trystack = &ectx.ec_trystack;
trycmd_T *trycmd = ((trycmd_T *)trystack->ga_data)
+ trystack->ga_len - 1;
// Reset the index to avoid a return statement jumps here
// again.
trycmd->tcd_finally_idx = 0;
break;
}
// end of ":try" block
case ISN_ENDTRY:
{
@@ -4348,11 +4362,17 @@ ex_disassemble(exarg_T *eap)
{
try_T *try = &iptr->isn_arg.try;
smsg("%4d TRY catch -> %d, %s -> %d", current,
try->try_catch,
instr[try->try_finally].isn_type == ISN_ENDTRY
? "end" : "finally",
try->try_finally);
if (try->try_ref->try_finally == 0)
smsg("%4d TRY catch -> %d, endtry -> %d",
current,
try->try_ref->try_catch,
try->try_ref->try_endtry);
else
smsg("%4d TRY catch -> %d, finally -> %d, endtry -> %d",
current,
try->try_ref->try_catch,
try->try_ref->try_finally,
try->try_ref->try_endtry);
}
break;
case ISN_CATCH:
@@ -4369,6 +4389,9 @@ ex_disassemble(exarg_T *eap)
trycont->tct_where);
}
break;
case ISN_FINALLY:
smsg("%4d FINALLY", current);
break;
case ISN_ENDTRY:
smsg("%4d ENDTRY", current);
break;