diff options
author | Yves Orton <demerphq@gmail.com> | 2022-09-03 15:26:52 +0200 |
---|---|---|
committer | Yves Orton <demerphq@gmail.com> | 2022-09-05 07:57:17 +0200 |
commit | d1a6746d8c2f7c8c63ed325c12310b651241c146 (patch) | |
tree | 097ca996499c2e7b6c539c7cc02c3568b493ecb4 /pp_ctl.c | |
parent | 0a2c3307765fa93b7e275a0cc3c1112cd0a116eb (diff) | |
download | perl-d1a6746d8c2f7c8c63ed325c12310b651241c146.tar.gz |
pp_ctl.c - handle UNITCHECK better
Make sure we actually return via pp_evalcomp() when UNITCHECK
inside of an eval dies.
Thanks to Bram for the work figuring this out.
Diffstat (limited to 'pp_ctl.c')
-rw-r--r-- | pp_ctl.c | 50 |
1 files changed, 49 insertions, 1 deletions
@@ -3752,7 +3752,55 @@ S_doeval_compile(pTHX_ U8 gimme, CV* outside, U32 seq, HV *hh) if (PL_unitcheckav) { OP *es = PL_eval_start; - call_list(PL_scopestack_ix, PL_unitcheckav); + if (in_require) { + call_list(PL_scopestack_ix, PL_unitcheckav); + } else { + /* TODO: are we sure we shouldn't do JMPENV_PUSH in + * when `in_require` is true? */ + int ret=0; + dJMPENV; + JMPENV_PUSH(ret); + switch (ret) { + case 0: + /* + * Doesn't seem like PUSHMARK(SP)/ENTER + * is needed here. */ + + call_list(PL_scopestack_ix, PL_unitcheckav); + /* Nor LEAVE here. */ + break; + case 3: { + /* call_list failed and threw an error */ + + /* Restore PL_OP */ + PL_op = saveop; + + SV *errsv = ERRSV; + if (!*(SvPV_nolen_const(errsv))) { + /* This happens when using: + * eval qq# UNITCHECK { die "\x00"; } #; + */ + sv_setpvs(errsv, "Unit check error"); + } + + /* We're returning so POP our JMPENV */ + /* NOTE: in `S_try_yyparse` the default for ret=3 is to + * break which falls back to the `JMPENV_POP` + * after the switch. In this code we're returning + * early so we must POP it outrself. */ + JMPENV_POP; + + if (gimme != G_LIST) PUSHs(&PL_sv_undef); + PUTBACK; + return FALSE; + } + default: + JMPENV_POP; + JMPENV_JUMP(ret); + NOT_REACHED; /* NOTREACHED */ + } + JMPENV_POP; + } PL_eval_start = es; } |