X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/c5aa2872379824e696683293ee3de5762325de1e..4e74b85bc530fa4d5182e4323be281b1cd335c7a:/pp_hot.c diff --git a/pp_hot.c b/pp_hot.c index 0e52921..852ff80 100644 --- a/pp_hot.c +++ b/pp_hot.c @@ -122,7 +122,7 @@ PP(pp_sassign) if (PL_op->op_private & OPpASSIGN_CV_TO_GV) { SV * const cv = SvRV(left); const U32 cv_type = SvTYPE(cv); - const U32 gv_type = SvTYPE(right); + const bool is_gv = isGV_with_GP(right); const bool got_coderef = cv_type == SVt_PVCV || cv_type == SVt_PVFM; if (!got_coderef) { @@ -132,7 +132,7 @@ PP(pp_sassign) /* Can do the optimisation if right (LVALUE) is not a typeglob, left (RVALUE) is a reference to something, and we're in void context. */ - if (!got_coderef && gv_type != SVt_PVGV && GIMME_V == G_VOID) { + if (!got_coderef && !is_gv && GIMME_V == G_VOID) { /* Is the target symbol table currently empty? */ GV * const gv = gv_fetchsv(right, GV_NOINIT, SVt_PVGV); if (SvTYPE(gv) != SVt_PVGV && !SvOK(gv)) { @@ -150,7 +150,7 @@ PP(pp_sassign) } /* Need to fix things up. */ - if (gv_type != SVt_PVGV) { + if (!is_gv) { /* Need to fix GV. */ right = MUTABLE_SV(gv_fetchsv(right, GV_ADD, SVt_PVGV)); } @@ -215,13 +215,14 @@ PP(pp_cond_expr) PP(pp_unstack) { dVAR; - I32 oldsave; PERL_ASYNC_CHECK(); TAINT_NOT; /* Each statement is presumed innocent */ PL_stack_sp = PL_stack_base + cxstack[cxstack_ix].blk_oldsp; FREETMPS; - oldsave = PL_scopestack[PL_scopestack_ix - 1]; - LEAVE_SCOPE(oldsave); + if (!(PL_op->op_flags & OPf_SPECIAL)) { + I32 oldsave = PL_scopestack[PL_scopestack_ix - 1]; + LEAVE_SCOPE(oldsave); + } return NORMAL; } @@ -244,7 +245,7 @@ PP(pp_concat) rcopied = TRUE; } - if (TARG != left) { + if (TARG != left) { /* not $l .= $r */ STRLEN llen; const char* const lpv = SvPV_nomg_const(left, llen); lbyte = !DO_UTF8(left); @@ -254,9 +255,9 @@ PP(pp_concat) else SvUTF8_off(TARG); } - else { /* TARG == left */ + else { /* $l .= $r */ if (!SvOK(TARG)) { - if (left == right && ckWARN(WARN_UNINITIALIZED)) + if (left == right && ckWARN(WARN_UNINITIALIZED)) /* $l .= $l */ report_uninit(right); sv_setpvs(left, ""); } @@ -268,12 +269,14 @@ PP(pp_concat) if (!rcopied) { if (left == right) - /* $a.$a: do magic twice: tied might return different 2nd time */ + /* $r.$r: do magic twice: tied might return different 2nd time */ SvGETMAGIC(right); rpv = SvPV_nomg_const(right, rlen); rbyte = !DO_UTF8(right); } if (lbyte != rbyte) { + /* sv_utf8_upgrade_nomg() may reallocate the stack */ + PUTBACK; if (lbyte) sv_utf8_upgrade_nomg(TARG); else { @@ -282,6 +285,7 @@ PP(pp_concat) sv_utf8_upgrade_nomg(right); rpv = SvPV_nomg_const(right, rlen); } + SPAGAIN; } sv_catpvn_nomg(TARG, rpv, rlen); @@ -310,7 +314,8 @@ PP(pp_padsv) PP(pp_readline) { dVAR; - tryAMAGICunTARGET(iter, 0); + dSP; SvGETMAGIC(TOPs); + tryAMAGICunTARGET(iter_amg, 0, 0); PL_last_in_gv = MUTABLE_GV(*PL_stack_sp--); if (!isGV_with_GP(PL_last_in_gv)) { if (SvROK(PL_last_in_gv) && isGV_with_GP(SvRV(PL_last_in_gv))) @@ -319,7 +324,7 @@ PP(pp_readline) dSP; XPUSHs(MUTABLE_SV(PL_last_in_gv)); PUTBACK; - pp_rv2gv(); + Perl_pp_rv2gv(aTHX); PL_last_in_gv = MUTABLE_GV(*PL_stack_sp--); } } @@ -329,7 +334,7 @@ PP(pp_readline) PP(pp_eq) { dVAR; dSP; - tryAMAGICbin_MG(eq_amg, AMGf_set); + tryAMAGICbin_MG(eq_amg, AMGf_set|AMGf_numeric); #ifndef NV_PRESERVES_UV if (SvROK(TOPs) && !SvAMAGIC(TOPs) && SvROK(TOPm1s) && !SvAMAGIC(TOPm1s)) { SP--; @@ -660,7 +665,7 @@ PP(pp_aelemfast) { dVAR; dSP; AV * const av = PL_op->op_flags & OPf_SPECIAL - ? MUTABLE_AV(PAD_SV(PL_op->op_targ)) : GvAV(cGVOP_gv); + ? MUTABLE_AV(PAD_SV(PL_op->op_targ)) : GvAVn(cGVOP_gv); const U32 lval = PL_op->op_flags & OPf_MOD; SV** const svp = av_fetch(av, PL_op->op_private, lval); SV *sv = (svp ? *svp : &PL_sv_undef); @@ -705,13 +710,13 @@ PP(pp_pushre) PP(pp_print) { dVAR; dSP; dMARK; dORIGMARK; - IO *io; register PerlIO *fp; MAGIC *mg; GV * const gv = (PL_op->op_flags & OPf_STACKED) ? MUTABLE_GV(*++MARK) : PL_defoutgv; + IO *io = GvIO(gv); - if (gv && (io = GvIO(gv)) + if (io && (mg = SvTIED_mg((const SV *)io, PERL_MAGIC_tiedscalar))) { had_magic: @@ -724,39 +729,25 @@ PP(pp_print) Move(MARK, MARK + 1, (SP - MARK) + 1, SV*); ++SP; } - PUSHMARK(MARK - 1); - *MARK = SvTIED_obj(MUTABLE_SV(io), mg); - PUTBACK; - ENTER_with_name("call_PRINT"); - if( PL_op->op_type == OP_SAY ) { - /* local $\ = "\n" */ - SAVEGENERICSV(PL_ors_sv); - PL_ors_sv = newSVpvs("\n"); - } - call_method("PRINT", G_SCALAR); - LEAVE_with_name("call_PRINT"); - SPAGAIN; - MARK = ORIGMARK + 1; - *MARK = *SP; - SP = MARK; - RETURN; + return Perl_tied_method(aTHX_ "PRINT", mark - 1, MUTABLE_SV(io), + mg, + (G_SCALAR | TIED_METHOD_ARGUMENTS_ON_STACK + | (PL_op->op_type == OP_SAY + ? TIED_METHOD_SAY : 0)), sp - mark); } - if (!(io = GvIO(gv))) { - if ((GvEGVx(gv)) && (io = GvIO(GvEGV(gv))) + if (!io) { + if ( gv && GvEGVx(gv) && (io = GvIO(GvEGV(gv))) && (mg = SvTIED_mg((const SV *)io, PERL_MAGIC_tiedscalar))) goto had_magic; - if (ckWARN2(WARN_UNOPENED,WARN_CLOSED)) - report_evil_fh(gv, io, PL_op->op_type); + report_evil_fh(gv); SETERRNO(EBADF,RMS_IFI); goto just_say_no; } else if (!(fp = IoOFP(io))) { - if (ckWARN2(WARN_CLOSED, WARN_IO)) { - if (IoIFP(io)) - report_evil_fh(gv, io, OP_phoney_INPUT_ONLY); - else if (ckWARN2(WARN_UNOPENED,WARN_CLOSED)) - report_evil_fh(gv, io, PL_op->op_type); - } + if (IoIFP(io)) + report_wrongway_fh(gv, '<'); + else + report_evil_fh(gv); SETERRNO(EBADF,IoIFP(io)?RMS_FAC:RMS_IFI); goto just_say_no; } @@ -822,8 +813,10 @@ PP(pp_rv2av) if (!(PL_op->op_private & OPpDEREFed)) SvGETMAGIC(sv); if (SvROK(sv)) { - tryAMAGICunDEREF_var(is_pp_rv2av ? to_av_amg : to_hv_amg); - + if (SvAMAGIC(sv)) { + sv = amagic_deref_call(sv, is_pp_rv2av ? to_av_amg : to_hv_amg); + SPAGAIN; + } sv = SvRV(sv); if (SvTYPE(sv) != type) DIE(aTHX_ "Not %s reference", is_pp_rv2av ? an_array : a_hash); @@ -884,45 +877,45 @@ PP(pp_rv2av) if (is_pp_rv2av) { AV *const av = MUTABLE_AV(sv); - /* The guts of pp_rv2av, with no intenting change to preserve history + /* The guts of pp_rv2av, with no intending change to preserve history (until such time as we get tools that can do blame annotation across whitespace changes. */ - if (gimme == G_ARRAY) { - const I32 maxarg = AvFILL(av) + 1; - (void)POPs; /* XXXX May be optimized away? */ - EXTEND(SP, maxarg); - if (SvRMAGICAL(av)) { - U32 i; - for (i=0; i < (U32)maxarg; i++) { - SV ** const svp = av_fetch(av, i, FALSE); - /* See note in pp_helem, and bug id #27839 */ - SP[i+1] = svp - ? SvGMAGICAL(*svp) ? (mg_get(*svp), *svp) : *svp - : &PL_sv_undef; + if (gimme == G_ARRAY) { + const I32 maxarg = AvFILL(av) + 1; + (void)POPs; /* XXXX May be optimized away? */ + EXTEND(SP, maxarg); + if (SvRMAGICAL(av)) { + U32 i; + for (i=0; i < (U32)maxarg; i++) { + SV ** const svp = av_fetch(av, i, FALSE); + /* See note in pp_helem, and bug id #27839 */ + SP[i+1] = svp + ? SvGMAGICAL(*svp) ? (mg_get(*svp), *svp) : *svp + : &PL_sv_undef; + } + } + else { + Copy(AvARRAY(av), SP+1, maxarg, SV*); } + SP += maxarg; } - else { - Copy(AvARRAY(av), SP+1, maxarg, SV*); + else if (gimme == G_SCALAR) { + dTARGET; + const I32 maxarg = AvFILL(av) + 1; + SETi(maxarg); } - SP += maxarg; - } - else if (gimme == G_SCALAR) { - dTARGET; - const I32 maxarg = AvFILL(av) + 1; - SETi(maxarg); - } } else { /* The guts of pp_rv2hv */ - if (gimme == G_ARRAY) { /* array wanted */ - *PL_stack_sp = sv; - return do_kv(); - } - else if (gimme == G_SCALAR) { - dTARGET; - TARG = Perl_hv_scalar(aTHX_ MUTABLE_HV(sv)); - SPAGAIN; - SETTARG; - } + if (gimme == G_ARRAY) { /* array wanted */ + *PL_stack_sp = sv; + return Perl_do_kv(aTHX); + } + else if (gimme == G_SCALAR) { + dTARGET; + TARG = Perl_hv_scalar(aTHX_ MUTABLE_HV(sv)); + SPAGAIN; + SETTARG; + } } RETURN; @@ -1052,6 +1045,7 @@ PP(pp_aassign) break; case SVt_PVHV: { /* normal hash */ SV *tmpstr; + SV** topelem = relem; hash = MUTABLE_HV(sv); magic = SvMAGICAL(hash) != 0; @@ -1065,10 +1059,19 @@ PP(pp_aassign) tmpstr = newSV(0); if (*relem) sv_setsv(tmpstr,*relem); /* value */ - *(relem++) = tmpstr; - if (gimme != G_VOID && hv_exists_ent(hash, sv, 0)) - /* key overwrites an existing entry */ - duplicates += 2; + relem++; + if (gimme != G_VOID) { + if (hv_exists_ent(hash, sv, 0)) + /* key overwrites an existing entry */ + duplicates += 2; + else + if (gimme == G_ARRAY) { + /* copy element back: possibly to an earlier + * stack location if we encountered dups earlier */ + *topelem++ = sv; + *topelem++ = tmpstr; + } + } didstore = hv_store_ent(hash,sv,tmpstr,0); if (magic) { if (SvSMAGICAL(tmpstr)) @@ -1181,11 +1184,20 @@ PP(pp_aassign) SP = lastrelem; else if (hash) { if (duplicates) { - /* Removes from the stack the entries which ended up as - * duplicated keys in the hash (fix for [perl #24380]) */ - Move(firsthashrelem + duplicates, - firsthashrelem, duplicates, SV**); + /* at this point we have removed the duplicate key/value + * pairs from the stack, but the remaining values may be + * wrong; i.e. with (a 1 a 2 b 3) on the stack we've removed + * the (a 2), but the stack now probably contains + * (a b 3), because { hv_save(a,1); hv_save(a,2) } + * obliterates the earlier key. So refresh all values. */ lastrelem -= duplicates; + relem = firsthashrelem; + while (relem < lastrelem) { + HE *he; + sv = *relem++; + he = hv_fetch_ent(hash, sv, 0, 0); + *relem++ = (he ? HeVAL(he) : &PL_sv_undef); + } } SP = lastrelem; } @@ -1218,13 +1230,15 @@ PP(pp_qr) SvROK_on(rv); if (pkg) { - HV* const stash = gv_stashpv(SvPV_nolen(pkg), GV_ADD); + HV *const stash = gv_stashsv(pkg, GV_ADD); SvREFCNT_dec(pkg); (void)sv_bless(rv, stash); } - if (RX_EXTFLAGS(rx) & RXf_TAINTED) + if (RX_EXTFLAGS(rx) & RXf_TAINTED) { SvTAINTED_on(rv); + SvTAINTED_on(SvRV(rv)); + } XPUSHs(rv); RETURN; } @@ -1326,14 +1340,14 @@ PP(pp_match) /g matches against large strings. So far a solution to this problem appears to be quite tricky. Test for the unsafe vars are TODO for now. */ - if (( !global && RX_NPARENS(rx)) - || SvTEMP(TARG) || PL_sawampersand || - (RX_EXTFLAGS(rx) & (RXf_EVAL_SEEN|RXf_PMf_KEEPCOPY))) + if ( (!global && RX_NPARENS(rx)) + || SvTEMP(TARG) || SvAMAGIC(TARG) || PL_sawampersand + || (RX_EXTFLAGS(rx) & (RXf_EVAL_SEEN|RXf_PMf_KEEPCOPY))) r_flags |= REXEC_COPY_STR; if (SvSCREAM(TARG)) r_flags |= REXEC_SCREAM; -play_it_again: + play_it_again: if (global && RX_OFFS(rx)[0].start != -1) { t = s = RX_OFFS(rx)[0].end + truebase - RX_GOFS(rx); if ((s + RX_MINLEN(rx)) > strend || s < truebase) @@ -1555,21 +1569,15 @@ Perl_do_readline(pTHX) const I32 gimme = GIMME_V; if (io) { - MAGIC * const mg = SvTIED_mg((const SV *)io, PERL_MAGIC_tiedscalar); + const MAGIC *const mg = SvTIED_mg((const SV *)io, PERL_MAGIC_tiedscalar); if (mg) { - PUSHMARK(SP); - XPUSHs(SvTIED_obj(MUTABLE_SV(io), mg)); - PUTBACK; - ENTER_with_name("call_READLINE"); - call_method("READLINE", gimme); - LEAVE_with_name("call_READLINE"); - SPAGAIN; + Perl_tied_method(aTHX_ "READLINE", SP, MUTABLE_SV(io), mg, gimme, 0); if (gimme == G_SCALAR) { - SV* const result = POPs; - SvSetSV_nosteal(TARG, result); - PUSHTARG; + SPAGAIN; + SvSetSV_nosteal(TARG, TOPs); + SETTARG; } - RETURN; + return NORMAL; } } fp = NULL; @@ -1598,8 +1606,8 @@ Perl_do_readline(pTHX) } else if (type == OP_GLOB) SP--; - else if (ckWARN(WARN_IO) && IoTYPE(io) == IoTYPE_WRONLY) { - report_evil_fh(PL_last_in_gv, io, OP_phoney_OUTPUT_ONLY); + else if (IoTYPE(io) == IoTYPE_WRONLY) { + report_wrongway_fh(PL_last_in_gv, '>'); } } if (!fp) { @@ -1611,7 +1619,7 @@ Perl_do_readline(pTHX) "glob failed (can't start child: %s)", Strerror(errno)); else - report_evil_fh(PL_last_in_gv, io, PL_op->op_type); + report_evil_fh(PL_last_in_gv); } if (gimme == G_SCALAR) { /* undef TARG, and push that undefined value */ @@ -1639,8 +1647,12 @@ Perl_do_readline(pTHX) } SvUPGRADE(sv, SVt_PV); tmplen = SvLEN(sv); /* remember if already alloced */ - if (!tmplen && !SvREADONLY(sv)) - Sv_Grow(sv, 80); /* try short-buffering it */ + if (!tmplen && !SvREADONLY(sv)) { + /* try short-buffering it. Please update t/op/readline.t + * if you change the growth length. + */ + Sv_Grow(sv, 80); + } offset = 0; if (type == OP_RCATLINE && SvOK(sv)) { if (!SvPOK(sv)) { @@ -2046,6 +2058,73 @@ PP(pp_iter) RETPUSHYES; } +/* +A description of how taint works in pattern matching and substitution. + +While the pattern is being assembled/concatenated and them compiled, +PL_tainted will get set if any component of the pattern is tainted, e.g. +/.*$tainted/. At the end of pattern compilation, the RXf_TAINTED flag +is set on the pattern if PL_tainted is set. + +When the pattern is copied, e.g. $r = qr/..../, the SV holding the ref to +the pattern is marked as tainted. This means that subsequent usage, such +as /x$r/, will set PL_tainted, and thus RXf_TAINTED, on the new pattern too. + +During execution of a pattern, locale-variant ops such as ALNUML set the +local flag RF_tainted. At the end of execution, the engine sets the +RXf_TAINTED_SEEN on the pattern if RF_tainted got set, or clears it +otherwise. + +In addition, RXf_TAINTED_SEEN is used post-execution by the get magic code +of $1 et al to indicate whether the returned value should be tainted. +It is the responsibility of the caller of the pattern (i.e. pp_match, +pp_subst etc) to set this flag for any other circumstances where $1 needs +to be tainted. + +The taint behaviour of pp_subst (and pp_substcont) is quite complex. + +There are three possible sources of taint + * the source string + * the pattern (both compile- and run-time, RXf_TAINTED / RXf_TAINTED_SEEN) + * the replacement string (or expression under /e) + +There are four destinations of taint and they are affected by the sources +according to the rules below: + + * the return value (not including /r): + tainted by the source string and pattern, but only for the + number-of-iterations case; boolean returns aren't tainted; + * the modified string (or modified copy under /r): + tainted by the source string, pattern, and replacement strings; + * $1 et al: + tainted by the pattern, and under 'use re "taint"', by the source + string too; + * PL_taint - i.e. whether subsequent code (e.g. in a /e block) is tainted: + should always be unset before executing subsequent code. + +The overall action of pp_subst is: + + * at the start, set bits in rxtainted indicating the taint status of + the various sources. + + * After each pattern execution, update the SUBST_TAINT_PAT bit in + rxtainted if RXf_TAINTED_SEEN has been set, to indicate that the + pattern has subsequently become tainted via locale ops. + + * If control is being passed to pp_substcont to execute a /e block, + save rxtainted in the CXt_SUBST block, for future use by + pp_substcont. + + * Whenever control is being returned to perl code (either by falling + off the "end" of pp_subst/pp_substcont, or by entering a /e block), + use the flag bits in rxtainted to make all the appropriate types of + destination taint visible; e.g. set RXf_TAINTED_SEEN so that $1 + et al will appear tainted. + +pp_match is just a simpler version of the above. + +*/ + PP(pp_subst) { dVAR; dSP; dTARG; @@ -2061,7 +2140,8 @@ PP(pp_subst) I32 maxiters; register I32 i; bool once; - U8 rxtainted; + U8 rxtainted = 0; /* holds various SUBST_TAINT_* flag bits. + See "how taint works" above */ char *orig; U8 r_flags; register REGEXP *rx = PM_GETRE(pm); @@ -2070,7 +2150,6 @@ PP(pp_subst) const I32 oldsave = PL_savestack_ix; STRLEN slen; bool doutf8 = FALSE; - I32 matched; #ifdef PERL_OLD_COPY_ON_WRITE bool is_cow; #endif @@ -2092,7 +2171,7 @@ PP(pp_subst) /* In non-destructive replacement mode, duplicate target scalar so it * remains unchanged. */ if (rpm->op_pmflags & PMf_NONDESTRUCT) - TARG = newSVsv(TARG); + TARG = sv_2mortal(newSVsv(TARG)); #ifdef PERL_OLD_COPY_ON_WRITE /* Awooga. Awooga. "bool" types that are actually char are dangerous, @@ -2117,11 +2196,20 @@ PP(pp_subst) s = SvPV_mutable(TARG, len); if (!SvPOKp(TARG) || SvTYPE(TARG) == SVt_PVGV) force_on_match = 1; - rxtainted = ((RX_EXTFLAGS(rx) & RXf_TAINTED) || - (PL_tainted && (pm->op_pmflags & PMf_RETAINT))); - if (PL_tainted) - rxtainted |= 2; - TAINT_NOT; + + /* only replace once? */ + once = !(rpm->op_pmflags & PMf_GLOBAL); + + /* See "how taint works" above */ + if (PL_tainting) { + rxtainted = ( + (SvTAINTED(TARG) ? SUBST_TAINT_STR : 0) + | ((RX_EXTFLAGS(rx) & RXf_TAINTED) ? SUBST_TAINT_PAT : 0) + | ((pm->op_pmflags & PMf_RETAINT) ? SUBST_TAINT_RETAINT : 0) + | ((once && !(rpm->op_pmflags & PMf_NONDESTRUCT)) + ? SUBST_TAINT_BOOLRET : 0)); + TAINT_NOT; + } RX_MATCH_UTF8_set(rx, DO_UTF8(TARG)); @@ -2151,7 +2239,7 @@ PP(pp_subst) s = CALLREG_INTUIT_START(rx, TARG, s, strend, r_flags, NULL); if (!s) - goto nope; + goto ret_no; /* How to do it in subst? */ /* if ( (RX_EXTFLAGS(rx) & RXf_CHECK_ALL) && !PL_sawampersand @@ -2163,24 +2251,33 @@ PP(pp_subst) */ } - /* only replace once? */ - once = !(rpm->op_pmflags & PMf_GLOBAL); - matched = CALLREGEXEC(rx, s, strend, orig, 0, TARG, NULL, - r_flags | REXEC_CHECKED); + if (!CALLREGEXEC(rx, s, strend, orig, 0, TARG, NULL, + r_flags | REXEC_CHECKED)) + { + ret_no: + SPAGAIN; + PUSHs(rpm->op_pmflags & PMf_NONDESTRUCT ? TARG : &PL_sv_no); + LEAVE_SCOPE(oldsave); + RETURN; + } + /* known replacement string? */ if (dstr) { + if (SvTAINTED(dstr)) + rxtainted |= SUBST_TAINT_REPL; /* Upgrade the source if the replacement is utf8 but the source is not, * but only if it matched; see * http://www.nntp.perl.org/group/perl.perl5.porters/2010/04/msg158809.html */ - if (matched && DO_UTF8(dstr) && ! DO_UTF8(TARG)) { - const STRLEN new_len = sv_utf8_upgrade(TARG); + if (DO_UTF8(dstr) && ! DO_UTF8(TARG)) { + char * const orig_pvx = SvPVX(TARG); + const STRLEN new_len = sv_utf8_upgrade_nomg(TARG); /* If the lengths are the same, the pattern contains only * invariants, can keep going; otherwise, various internal markers * could be off, so redo */ - if (new_len != len) { + if (new_len != len || orig_pvx != SvPVX(TARG)) { goto setup_match; } } @@ -2213,17 +2310,9 @@ PP(pp_subst) #endif && (I32)clen <= RX_MINLENRET(rx) && (once || !(r_flags & REXEC_COPY_STR)) && !(RX_EXTFLAGS(rx) & RXf_LOOKBEHIND_SEEN) - && (!doutf8 || SvUTF8(TARG))) { - if (!matched) - { - SPAGAIN; - if (rpm->op_pmflags & PMf_NONDESTRUCT) - PUSHs(TARG); - else - PUSHs(&PL_sv_no); - LEAVE_SCOPE(oldsave); - RETURN; - } + && (!doutf8 || SvUTF8(TARG))) + { + #ifdef PERL_OLD_COPY_ON_WRITE if (SvIsCOW(TARG)) { assert (!force_on_match); @@ -2239,7 +2328,8 @@ PP(pp_subst) PL_curpm = pm; SvSCREAM_off(TARG); /* disable possible screamer */ if (once) { - rxtainted |= RX_MATCH_TAINTED(rx); + if (RX_MATCH_TAINTED(rx)) /* run time pattern taint, eg locale */ + rxtainted |= SUBST_TAINT_PAT; m = orig + RX_OFFS(rx)[0].start; d = orig + RX_OFFS(rx)[0].end; s = orig; @@ -2272,18 +2362,15 @@ PP(pp_subst) else { sv_chop(TARG, d); } - TAINT_IF(rxtainted & 1); SPAGAIN; - if (rpm->op_pmflags & PMf_NONDESTRUCT) - PUSHs(TARG); - else - PUSHs(&PL_sv_yes); + PUSHs(rpm->op_pmflags & PMf_NONDESTRUCT ? TARG : &PL_sv_yes); } else { do { if (iters++ > maxiters) DIE(aTHX_ "Substitution loop"); - rxtainted |= RX_MATCH_TAINTED(rx); + if (RX_MATCH_TAINTED(rx)) /* run time pattern taint, eg locale */ + rxtainted |= SUBST_TAINT_PAT; m = RX_OFFS(rx)[0].start + orig; if ((i = m - s)) { if (s != d) @@ -2304,29 +2391,14 @@ PP(pp_subst) SvCUR_set(TARG, d - SvPVX_const(TARG) + i); Move(s, d, i+1, char); /* include the NUL */ } - TAINT_IF(rxtainted & 1); SPAGAIN; if (rpm->op_pmflags & PMf_NONDESTRUCT) PUSHs(TARG); else mPUSHi((I32)iters); } - (void)SvPOK_only_UTF8(TARG); - TAINT_IF(rxtainted); - if (SvSMAGICAL(TARG)) { - PUTBACK; - mg_set(TARG); - SPAGAIN; - } - SvTAINT(TARG); - if (doutf8) - SvUTF8_on(TARG); - LEAVE_SCOPE(oldsave); - RETURN; } - - if (matched) - { + else { if (force_on_match) { force_on_match = 0; s = SvPV_force(TARG, len); @@ -2335,13 +2407,19 @@ PP(pp_subst) #ifdef PERL_OLD_COPY_ON_WRITE have_a_cow: #endif - rxtainted |= RX_MATCH_TAINTED(rx); + if (RX_MATCH_TAINTED(rx)) /* run time pattern taint, eg locale */ + rxtainted |= SUBST_TAINT_PAT; dstr = newSVpvn_utf8(m, s-m, DO_UTF8(TARG)); SAVEFREESV(dstr); PL_curpm = pm; if (!c) { register PERL_CONTEXT *cx; SPAGAIN; + /* note that a whole bunch of local vars are saved here for + * use by pp_substcont: here's a list of them in case you're + * searching for places in this sub that uses a particular var: + * iters maxiters r_flags oldsave rxtainted orig dstr targ + * s m strend rx once */ PUSHSUBST(cx); RETURNOP(cPMOP->op_pmreplrootu.op_pmreplroot); } @@ -2349,7 +2427,8 @@ PP(pp_subst) do { if (iters++ > maxiters) DIE(aTHX_ "Substitution loop"); - rxtainted |= RX_MATCH_TAINTED(rx); + if (RX_MATCH_TAINTED(rx)) + rxtainted |= SUBST_TAINT_PAT; if (RX_MATCH_COPIED(rx) && RX_SUBBEG(rx) != orig) { m = s; s = orig; @@ -2393,31 +2472,38 @@ PP(pp_subst) doutf8 |= DO_UTF8(dstr); SvPV_set(dstr, NULL); - TAINT_IF(rxtainted & 1); SPAGAIN; if (rpm->op_pmflags & PMf_NONDESTRUCT) PUSHs(TARG); else mPUSHi((I32)iters); + } + (void)SvPOK_only_UTF8(TARG); + if (doutf8) + SvUTF8_on(TARG); + + /* See "how taint works" above */ + if (PL_tainting) { + if ((rxtainted & SUBST_TAINT_PAT) || + ((rxtainted & (SUBST_TAINT_STR|SUBST_TAINT_RETAINT)) == + (SUBST_TAINT_STR|SUBST_TAINT_RETAINT)) + ) + (RX_MATCH_TAINTED_on(rx)); /* taint $1 et al */ + + if (!(rxtainted & SUBST_TAINT_BOOLRET) + && (rxtainted & (SUBST_TAINT_STR|SUBST_TAINT_PAT)) + ) + SvTAINTED_on(TOPs); /* taint return value */ + else + SvTAINTED_off(TOPs); /* may have got tainted earlier */ - (void)SvPOK_only(TARG); - if (doutf8) - SvUTF8_on(TARG); - TAINT_IF(rxtainted); - SvSETMAGIC(TARG); + /* needed for mg_set below */ + PL_tainted = + cBOOL(rxtainted & (SUBST_TAINT_STR|SUBST_TAINT_PAT|SUBST_TAINT_REPL)); SvTAINT(TARG); - LEAVE_SCOPE(oldsave); - RETURN; } - goto ret_no; - -nope: -ret_no: - SPAGAIN; - if (rpm->op_pmflags & PMf_NONDESTRUCT) - PUSHs(TARG); - else - PUSHs(&PL_sv_no); + SvSETMAGIC(TARG); /* PL_tainted must be correctly set for this mg_set */ + TAINT_NOT; LEAVE_SCOPE(oldsave); RETURN; } @@ -2429,6 +2515,7 @@ PP(pp_grepwhile) if (SvTRUEx(POPs)) PL_stack_base[PL_markstack_ptr[-1]++] = PL_stack_base[*PL_markstack_ptr]; ++*PL_markstack_ptr; + FREETMPS; LEAVE_with_name("grep_item"); /* exit inner scope */ /* All done yet? */ @@ -2565,6 +2652,29 @@ PP(pp_leavesublv) if (gimme == G_SCALAR) goto temporise; if (gimme == G_ARRAY) { + mark = newsp + 1; + /* We want an array here, but padav will have left us an arrayref for an lvalue, + * so we need to expand it */ + if(SvTYPE(*mark) == SVt_PVAV) { + AV *const av = MUTABLE_AV(*mark); + const I32 maxarg = AvFILL(av) + 1; + (void)POPs; /* get rid of the array ref */ + EXTEND(SP, maxarg); + if (SvRMAGICAL(av)) { + U32 i; + for (i=0; i < (U32)maxarg; i++) { + SV ** const svp = av_fetch(av, i, FALSE); + SP[i+1] = svp + ? SvGMAGICAL(*svp) ? (mg_get(*svp), *svp) : *svp + : &PL_sv_undef; + } + } + else { + Copy(AvARRAY(av), SP+1, maxarg, SV*); + } + SP += maxarg; + PUTBACK; + } if (!CvLVALUE(cx->blk_sub.cv)) goto temporise_array; EXTEND_MORTAL(SP - newsp); @@ -2597,10 +2707,13 @@ PP(pp_leavesublv) MARK = newsp + 1; EXTEND_MORTAL(1); if (MARK == SP) { - /* Temporaries are bad unless they happen to be elements - * of a tied hash or array */ - if (SvFLAGS(TOPs) & (SVs_TEMP | SVs_PADTMP | SVf_READONLY) && - !(SvRMAGICAL(TOPs) && mg_find(TOPs, PERL_MAGIC_tiedelem))) { + /* Temporaries are bad unless they happen to have set magic + * attached, such as the elements of a tied hash or array */ + if ((SvFLAGS(TOPs) & (SVs_TEMP | SVs_PADTMP) || + (SvFLAGS(TOPs) & (SVf_READONLY | SVf_FAKE)) + == SVf_READONLY + ) && + !SvSMAGICAL(TOPs)) { LEAVE; cxstack_ix--; POPSUB(cx,sv); @@ -2714,6 +2827,7 @@ PP(pp_entersub) case SVt_PVGV: if (!isGV_with_GP(sv)) DIE(aTHX_ "Not a CODE reference"); + we_have_a_glob: if (!(cv = GvCVu((const GV *)sv))) { HV *stash; cv = sv_2cv(sv, &stash, &gv, 0); @@ -2724,16 +2838,23 @@ PP(pp_entersub) goto try_autoload; } break; + case SVt_PVLV: + if(isGV_with_GP(sv)) goto we_have_a_glob; + /*FALLTHROUGH*/ default: if (sv == &PL_sv_yes) { /* unfound import, ignore */ if (hasargs) SP = PL_stack_base + POPMARK; + else + (void)POPMARK; RETURN; } SvGETMAGIC(sv); if (SvROK(sv)) { - SV * const * sp = &sv; /* Used in tryAMAGICunDEREF macro. */ - tryAMAGICunDEREF(to_cv); + if (SvAMAGIC(sv)) { + sv = amagic_deref_call(sv, to_cv_amg); + /* Don't SPAGAIN here. */ + } } else { const char *sym; @@ -2763,6 +2884,8 @@ PP(pp_entersub) SAVETMPS; retry: + if (CvCLONE(cv) && ! CvCLONED(cv)) + DIE(aTHX_ "Closure prototype called"); if (!CvROOT(cv) && !CvXSUB(cv)) { GV* autogv; SV* sub_name; @@ -2909,7 +3032,7 @@ try_autoload: /* CvXSUB(cv) must not be NULL because newXS() refuses NULL xsub address */ assert(CvXSUB(cv)); - CALL_FPTR(CvXSUB(cv))(aTHX_ cv); + CvXSUB(cv)(aTHX_ cv); /* Enforce some sanity in scalar context. */ if (gimme == G_SCALAR && ++markix != PL_stack_sp - PL_stack_base ) {