From 69dc4b30f4725ad5f212d45d3c856ac1caaacf17 Mon Sep 17 00:00:00 2001 From: Father Chrysostomos Date: Mon, 14 Dec 2009 12:19:35 +0100 Subject: [perl #70764] $' fails to initialized for pre-compiled regular expression matches The match vars are associated with the regexp that last matched successfully. In the case of $str =~ $qr or /$qr/, since the $qr could be used in multiple scopes that need their own sets of match vars, the $qr is cloned by Perl_reg_temp_copy as of change 30677/28d8d7f. This happens in pp_regcomp before pp_match has stringified the LHS, hence the bug. In short, /$gror/ is not equivalent to ($which = !$which) ? /$gror/ : /$gror/, which is weird. Attached is a patch, which admittedly is a hack, but fixes this particular side effect of what is probably a bad design, by stringifying the LHS in pp_regcomp, and having pp_match skip get-magic in such cases. A real fix far exceeds my capabalities, and would also be very intrusive according to . --- pp_ctl.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'pp_ctl.c') diff --git a/pp_ctl.c b/pp_ctl.c index b196640c70..27d94bcc46 100644 --- a/pp_ctl.c +++ b/pp_ctl.c @@ -149,6 +149,26 @@ PP(pp_regcomp) re = (REGEXP*) tmpstr; if (re) { + /* The match's LHS's get-magic might need to access this op's reg- + exp (as is sometimes the case with $'; see bug 70764). So we + must call get-magic now before we replace the regexp. Hopeful- + ly this hack can be replaced with the approach described at + http://www.nntp.perl.org/group/perl.perl5.porters/2007/03 + /msg122415.html some day. */ + OP *matchop = pm->op_next; + SV *lhs; + const bool was_tainted = PL_tainted; + if (matchop->op_flags & OPf_STACKED) + lhs = TOPs; + else if (matchop->op_private & OPpTARGET_MY) + lhs = PAD_SV(matchop->op_targ); + else lhs = DEFSV; + SvGETMAGIC(lhs); + /* Restore the previous value of PL_tainted (which may have been + modified by get-magic), to avoid incorrectly setting the + RXf_TAINTED flag further down. */ + PL_tainted = was_tainted; + re = reg_temp_copy(NULL, re); ReREFCNT_dec(PM_GETRE(pm)); PM_SETRE(pm, re); -- cgit v1.2.1