Skip to content

Commit 78bb4e5

Browse files
committed
pp_ctl.c - try_run_unitcheck() guard against leaking PL_restartop
If we die while executing a UNITCHECK inside of an eval we shouldn't leave PL_restartop set, as we will execute PL_op->op_next anyway. I couldn't get anything to SEGV with code related to this, but I could get asserts() to trip to show the leaking PL_restartop. This maintains equivalence with try_yyparse() which does need it for sure.
1 parent 75345d9 commit 78bb4e5

File tree

1 file changed

+17
-3
lines changed

1 file changed

+17
-3
lines changed

pp_ctl.c

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3570,17 +3570,31 @@ S_try_yyparse(pTHX_ int gramtype, OP *caller_op)
35703570
* 3: a unitcheck block died
35713571
*/
35723572
STATIC int
3573-
S_try_run_unitcheck(pTHX)
3573+
S_try_run_unitcheck(pTHX, OP* caller_op)
35743574
{
3575-
int ret;
3575+
/* if we die during compilation PL_restartop and PL_restartjmpenv
3576+
* will be set. We need to restore their values if that happens. */
3577+
JMPENV *restartjmpenv = PL_restartjmpenv;
3578+
OP *restartop = PL_restartop;
35763579
dJMPENV;
3580+
int ret;
3581+
3582+
assert(CxTYPE(CX_CUR()) == CXt_EVAL);
35773583
JMPENV_PUSH(ret);
35783584
switch (ret) {
35793585
case 0:
35803586
call_list(PL_scopestack_ix, PL_unitcheckav);
35813587
break;
35823588
case 3:
35833589
/* call_list died */
3590+
/* call_list() died and we trapped the error. We should restore
3591+
* the old PL_restartjmpenv and PL_restartop values, as they are
3592+
* used only in the case where the code was actually run.
3593+
* The assert validates that we will still execute the PL_restartop.
3594+
*/
3595+
assert(PL_restartop == caller_op->op_next); /* we expect these to match */
3596+
PL_restartjmpenv = restartjmpenv;
3597+
PL_restartop = restartop;
35843598
break;
35853599
default:
35863600
JMPENV_POP;
@@ -3804,7 +3818,7 @@ S_doeval_compile(pTHX_ U8 gimme, CV* outside, U32 seq, HV *hh)
38043818
if (in_require) {
38053819
call_list(PL_scopestack_ix, PL_unitcheckav);
38063820
}
3807-
else if (S_try_run_unitcheck(aTHX)) {
3821+
else if (S_try_run_unitcheck(aTHX, saveop)) {
38083822
/* there was an error! */
38093823

38103824
/* Restore PL_OP */

0 commit comments

Comments
 (0)