diff options
author | David Mitchell <davem@iabyn.com> | 2012-06-04 13:24:23 +0100 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2012-06-13 13:32:55 +0100 |
commit | e4bfbed39bdcbc5cd76c9cdfdeb3314c3710ad62 (patch) | |
tree | 65692813c4e3da4c86143f350fd4828ca4173064 /regexec.c | |
parent | 9753d9401c87ce7ed5fdc20d64992a62f60942a7 (diff) | |
download | perl-e4bfbed39bdcbc5cd76c9cdfdeb3314c3710ad62.tar.gz |
handle weird/undef (?{}), (??{}) return value
All three code block variants: (?{}), (??{}), (?(?{}X|Y)),
make use of the return value of the block, either to set $^R, determine
truth, or to interpret as a pattern. Evaluating this value may trigger
magic calls, uninitialized var warnings etc. Make sure that this
processing happens in the right environment; specifically, before we've
restored vars and paren indices, and we set PL_op temporarily to NULL so
that uninit var warnings don't try to look in the wrong place: neither the
outer op (eg OP_MATCH) nor the inner op (the last op of the code block:
currently happens to be OP_NULL, but that's a bug; will eventually be last
*real* op, e.g. padsv) are suitable for identifying where the warning came
from.
For the (??{}) case, if we can't extract a pre-compiled regex from it,
we force it to a PV, making a temp copy if necessary.
Diffstat (limited to 'regexec.c')
-rw-r--r-- | regexec.c | 68 |
1 files changed, 39 insertions, 29 deletions
@@ -4404,6 +4404,40 @@ S_regmatch(pTHX_ regmatch_info *reginfo, regnode *prog) PUTBACK; } + /* before restoring everything, evaluate the returned + * value, so that 'uninit' warnings don't use the wrong + * PL_op or pad. Also need to process any magic vars (e.g. + * $1 *before* parentheses are restored */ + + PL_op = NULL; + + if (logical == 0) /* (?{})/ */ + sv_setsv(save_scalar(PL_replgv), ret); /* $^R */ + else if (logical == 1) { /* /(?(?{...})X|Y)/ */ + sw = cBOOL(SvTRUE(ret)); + logical = 0; + } + else { /* /(??{}) */ + SV *sv = ret; + re_sv = NULL; + if (SvROK(sv)) + sv = SvRV(sv); + if (SvTYPE(sv) == SVt_REGEXP) + re_sv = (REGEXP*) sv; + else if (SvSMAGICAL(sv)) { + MAGIC *mg = mg_find(sv, PERL_MAGIC_qr); + if (mg) + re_sv = (REGEXP *) mg->mg_obj; + } + + /* force any magic, undef warnings here */ + if (!re_sv && !SvAMAGIC(ret)) { + ret = sv_mortalcopy(ret); + (void) SvPV_force_nolen(ret); + } + + } + Copy(&saved_state, &PL_reg_state, 1, struct re_save_state); /* *** Note that at this point we don't restore @@ -4413,36 +4447,18 @@ S_regmatch(pTHX_ regmatch_info *reginfo, regnode *prog) PL_op = oop; PL_curcop = ocurcop; PL_regeol = saved_regeol; - if (!logical) { - /* /(?{...})/ */ - /* restore all paren positions. Note that where the - * return value is used, we must delay this as the - * returned string to be compiled may be $1 for - * example */ - S_regcp_restore(aTHX_ rex, runops_cp); - sv_setsv(save_scalar(PL_replgv), ret); + S_regcp_restore(aTHX_ rex, runops_cp); + + if (logical != 2) break; - } } - if (logical == 2) { /* Postponed subexpression: /(??{...})/ */ + + /* only /(??{})/ from now on */ logical = 0; { /* extract RE object from returned value; compiling if * necessary */ - re_sv = NULL; - { - SV *sv = ret; - if (SvROK(sv)) - sv = SvRV(sv); - if (SvTYPE(sv) == SVt_REGEXP) { - re_sv = (REGEXP*) sv; - } else if (SvSMAGICAL(sv)) { - MAGIC *mg = mg_find(sv, PERL_MAGIC_qr); - if (mg) - re_sv = (REGEXP *) mg->mg_obj; - } - } if (re_sv) { re_sv = reg_temp_copy(NULL, re_sv); } @@ -4527,12 +4543,6 @@ S_regmatch(pTHX_ regmatch_info *reginfo, regnode *prog) /* now continue from first node in postoned RE */ PUSH_YES_STATE_GOTO(EVAL_AB, startpoint); /* NOTREACHED */ - } - /* logical is 1, /(?(?{...})X|Y)/ */ - sw = cBOOL(SvTRUE(ret)); - S_regcp_restore(aTHX_ rex, runops_cp); - logical = 0; - break; } case EVAL_AB: /* cleanup after a successful (??{A})B */ |