X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/b68108d9b5245170bc0844ad4bded511ab7cca6a..801d32ac4fd337a99a83ad6098cda0f368bb8b03:/pp_ctl.c?ds=sidebyside diff --git a/pp_ctl.c b/pp_ctl.c index 1aaa261..7fd27f8 100644 --- a/pp_ctl.c +++ b/pp_ctl.c @@ -83,7 +83,7 @@ PP(pp_regcomp) REGEXP *re = NULL; REGEXP *new_re; const regexp_engine *eng; - bool is_bare_re; + bool is_bare_re= FALSE; if (PL_op->op_flags & OPf_STACKED) { dMARK; @@ -107,16 +107,29 @@ PP(pp_regcomp) assert (re != (REGEXP*) &PL_sv_undef); eng = re ? RX_ENGINE(re) : current_re_engine(); + /* + In the below logic: these are basically the same - check if this regcomp is part of a split. + + (PL_op->op_pmflags & PMf_split ) + (PL_op->op_next->op_type == OP_PUSHRE) + + We could add a new mask for this and copy the PMf_split, if we did + some bit definition fiddling first. + + For now we leave this + */ + new_re = (eng->op_comp ? eng->op_comp : &Perl_re_op_compile )(aTHX_ args, nargs, pm->op_code_list, eng, re, &is_bare_re, - (pm->op_pmflags & RXf_PMf_COMPILETIME), + (pm->op_pmflags & RXf_PMf_FLAGCOPYMASK), pm->op_pmflags | (PL_op->op_flags & OPf_SPECIAL ? PMf_USE_RE_EVAL : 0)); + if (pm->op_pmflags & PMf_HAS_CV) - ((struct regexp *)SvANY(new_re))->qr_anoncv + ReANY(new_re)->qr_anoncv = (CV*) SvREFCNT_inc(PAD_SV(PL_op->op_targ)); if (is_bare_re) { @@ -129,7 +142,7 @@ PP(pp_regcomp) some day. */ if (pm->op_type == OP_MATCH) { SV *lhs; - const bool was_tainted = PL_tainted; + const bool was_tainted = TAINT_get; if (pm->op_flags & OPf_STACKED) lhs = args[-1]; else if (pm->op_private & OPpTARGET_MY) @@ -138,22 +151,27 @@ PP(pp_regcomp) 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; + RXf_TAINTED flag with RX_TAINT_on further down. */ + TAINT_set(was_tainted); +#if NO_TAINT_SUPPORT + PERL_UNUSED_VAR(was_tainted); +#endif } tmp = reg_temp_copy(NULL, new_re); ReREFCNT_dec(new_re); new_re = tmp; } + if (re != new_re) { ReREFCNT_dec(re); PM_SETRE(pm, new_re); } + #ifndef INCOMPLETE_TAINTS - if (PL_tainting && PL_tainted) { + if (TAINTING_get && TAINT_get) { SvTAINTED_on((SV*)new_re); - RX_EXTFLAGS(new_re) |= RXf_TAINTED; + RX_TAINT_on(new_re); } #endif @@ -196,7 +214,6 @@ PP(pp_substcont) } rxres_restore(&cx->sb_rxres, rx); - RX_MATCH_UTF8_set(rx, DO_UTF8(cx->sb_targ)); if (cx->sb_iters++) { const I32 saviters = cx->sb_iters; @@ -209,14 +226,10 @@ PP(pp_substcont) if (SvTAINTED(TOPs)) cx->sb_rxtainted |= SUBST_TAINT_REPL; sv_catsv_nomg(dstr, POPs); - /* XXX: adjust for positive offsets of \G for instance s/(.)\G//g with positive pos() */ - s -= RX_GOFS(rx); - - /* Are we done */ if (CxONCE(cx) || s < orig || - !CALLREGEXEC(rx, s, cx->sb_strend, orig, - (s == m) + RX_GOFS(rx), cx->sb_targ, NULL, - (REXEC_IGNOREPOS|REXEC_NOT_FIRST))) + !CALLREGEXEC(rx, s, cx->sb_strend, orig, + (s == m), cx->sb_targ, NULL, + (REXEC_IGNOREPOS|REXEC_NOT_FIRST|REXEC_FAIL_ON_UNDERFLOW))) { SV *targ = cx->sb_targ; @@ -237,12 +250,9 @@ PP(pp_substcont) targ = dstr; } else { - if (SvIsCOW(targ)) { - sv_force_normal_flags(targ, SV_COW_DROP_PV); - } else - { - SvPV_free(targ); - } + SV_CHECK_THINKFIRST_COW_DROP(targ); + if (isGV(targ)) Perl_croak_no_modify(); + SvPV_free(targ); SvPV_set(targ, SvPVX(dstr)); SvCUR_set(targ, SvCUR(dstr)); SvLEN_set(targ, SvLEN(dstr)); @@ -259,7 +269,7 @@ PP(pp_substcont) /* update the taint state of various various variables in * preparation for final exit. * See "how taint works" above pp_subst() */ - if (PL_tainting) { + if (TAINTING_get) { if ((cx->sb_rxtainted & SUBST_TAINT_PAT) || ((cx->sb_rxtainted & (SUBST_TAINT_STR|SUBST_TAINT_RETAINT)) == (SUBST_TAINT_STR|SUBST_TAINT_RETAINT)) @@ -271,8 +281,10 @@ PP(pp_substcont) ) SvTAINTED_on(TOPs); /* taint return value */ /* needed for mg_set below */ - PL_tainted = cBOOL(cx->sb_rxtainted & - (SUBST_TAINT_STR|SUBST_TAINT_PAT|SUBST_TAINT_REPL)); + TAINT_set( + cBOOL(cx->sb_rxtainted & + (SUBST_TAINT_STR|SUBST_TAINT_PAT|SUBST_TAINT_REPL)) + ); SvTAINT(TARG); } /* PL_tainted must be correctly set for this mg_set */ @@ -280,6 +292,7 @@ PP(pp_substcont) TAINT_NOT; LEAVE_SCOPE(cx->sb_oldsave); POPSUBST(cx); + PERL_ASYNC_CHECK(); RETURNOP(pm->op_next); assert(0); /* NOTREACHED */ } @@ -305,23 +318,18 @@ PP(pp_substcont) SV * const sv = (pm->op_pmflags & PMf_NONDESTRUCT) ? cx->sb_dstr : cx->sb_targ; MAGIC *mg; - SvUPGRADE(sv, SVt_PVMG); - if (!(mg = mg_find(sv, PERL_MAGIC_regex_global))) { -#ifdef PERL_OLD_COPY_ON_WRITE - if (SvIsCOW(sv)) - sv_force_normal_flags(sv, 0); -#endif - mg = sv_magicext(sv, NULL, PERL_MAGIC_regex_global, &PL_vtbl_mglob, - NULL, 0); + if (!(mg = mg_find_mglob(sv))) { + mg = sv_magicext_mglob(sv); } - mg->mg_len = m - orig; + assert(SvPOK(dstr)); + MgBYTEPOS_set(mg, sv, SvPVX(dstr), m - orig); } if (old != rx) (void)ReREFCNT_inc(rx); /* update the taint state of various various variables in preparation * for calling the code block. * See "how taint works" above pp_subst() */ - if (PL_tainting) { + if (TAINTING_get) { if (RX_MATCH_TAINTED(rx)) /* run time pattern taint, eg locale */ cx->sb_rxtainted |= SUBST_TAINT_PAT; @@ -352,7 +360,7 @@ Perl_rxres_save(pTHX_ void **rsp, REGEXP *rx) PERL_UNUSED_CONTEXT; if (!p || p[1] < RX_NPARENS(rx)) { -#ifdef PERL_OLD_COPY_ON_WRITE +#ifdef PERL_ANY_COW i = 7 + (RX_NPARENS(rx)+1) * 2; #else i = 6 + (RX_NPARENS(rx)+1) * 2; @@ -369,7 +377,7 @@ Perl_rxres_save(pTHX_ void **rsp, REGEXP *rx) RX_MATCH_COPIED_off(rx); *p++ = RX_NPARENS(rx); -#ifdef PERL_OLD_COPY_ON_WRITE +#ifdef PERL_ANY_COW *p++ = PTR2UV(RX_SAVED_COPY(rx)); RX_SAVED_COPY(rx) = NULL; #endif @@ -398,7 +406,7 @@ S_rxres_restore(pTHX_ void **rsp, REGEXP *rx) *p++ = 0; RX_NPARENS(rx) = *p++; -#ifdef PERL_OLD_COPY_ON_WRITE +#ifdef PERL_ANY_COW if (RX_SAVED_COPY(rx)) SvREFCNT_dec (RX_SAVED_COPY(rx)); RX_SAVED_COPY(rx) = INT2PTR(SV*,*p); @@ -426,14 +434,14 @@ S_rxres_free(pTHX_ void **rsp) if (p) { void *tmp = INT2PTR(char*,*p); #ifdef PERL_POISON -#ifdef PERL_OLD_COPY_ON_WRITE +#ifdef PERL_ANY_COW U32 i = 9 + p[1] * 2; #else U32 i = 8 + p[1] * 2; #endif #endif -#ifdef PERL_OLD_COPY_ON_WRITE +#ifdef PERL_ANY_COW SvREFCNT_dec (INT2PTR(SV*,p[2])); #endif #ifdef PERL_POISON @@ -579,7 +587,7 @@ PP(pp_formline) itembytes = len; send = chophere = s + itembytes; while (s < send) { - if (*s & ~31) + if (! isCNTRL(*s)) gotsome = TRUE; else if (*s == '\n') break; @@ -596,7 +604,7 @@ PP(pp_formline) itemsize = fieldsize; send = chophere = s + itemsize; while (s < send) { - if (*s & ~31) + if (! isCNTRL(*s)) gotsome = TRUE; else if (*s == '\n') break; @@ -622,8 +630,9 @@ PP(pp_formline) chophere = s; break; } - if (*s++ & ~31) + if (! isCNTRL(*s)) gotsome = TRUE; + s++; } } else { @@ -640,7 +649,7 @@ PP(pp_formline) break; } else { - if (*s & ~31) + if (! isCNTRL(*s)) gotsome = TRUE; if (strchr(PL_chopset, *s)) chophere = s + 1; @@ -663,8 +672,9 @@ PP(pp_formline) chophere = s; break; } - if (*s++ & ~31) + if (! isCNTRL(*s)) gotsome = TRUE; + s++; } } else { @@ -679,7 +689,7 @@ PP(pp_formline) break; } else { - if (*s & ~31) + if (! isCNTRL(*s)) gotsome = TRUE; if (strchr(PL_chopset, *s)) chophere = s + 1; @@ -821,13 +831,7 @@ PP(pp_formline) U8 *send = s + to_copy; while (s < send) { const int ch = *s; - if (trans == '~' ? (ch == '~') : -#ifdef EBCDIC - iscntrl(ch) -#else - (!(ch & ~31)) -#endif - ) + if (trans == '~' ? (ch == '~') : isCNTRL(ch)) *s = ' '; s++; } @@ -979,6 +983,10 @@ PP(pp_grepstart) SAVEVPTR(PL_curpm); src = PL_stack_base[*PL_markstack_ptr]; + if (SvPADTMP(src) && !IS_PADGV(src)) { + src = PL_stack_base[*PL_markstack_ptr] = sv_mortalcopy(src); + PL_tmps_floor++; + } SvTEMP_off(src); if (PL_op->op_private & OPpGREP_LEX) PAD_SVl(PL_op->op_targ) = src; @@ -1127,6 +1135,7 @@ PP(pp_mapwhile) /* set $_ to the new source item */ src = PL_stack_base[PL_markstack_ptr[-1]]; + if (SvPADTMP(src) && !IS_PADGV(src)) src = sv_mortalcopy(src); SvTEMP_off(src); if (PL_op->op_private & OPpGREP_LEX) PAD_SVl(PL_op->op_targ) = src; @@ -1218,13 +1227,17 @@ PP(pp_flop) if (RANGE_IS_NUMERIC(left,right)) { IV i, j; IV max; - if ((SvOK(left) && SvNV_nomg(left) < IV_MIN) || - (SvOK(right) && SvNV_nomg(right) > IV_MAX)) + if ((SvOK(left) && !SvIOK(left) && SvNV_nomg(left) < IV_MIN) || + (SvOK(right) && (SvIOK(right) + ? SvIsUV(right) && SvUV(right) > IV_MAX + : SvNV_nomg(right) > IV_MAX))) DIE(aTHX_ "Range iterator outside integer range"); i = SvIV_nomg(left); max = SvIV_nomg(right); if (max >= i) { j = max - i + 1; + if (j > SSize_t_MAX) + Perl_croak(aTHX_ "Out of memory during list extend"); EXTEND_MORTAL(j); EXTEND(SP, j); } @@ -1421,8 +1434,14 @@ S_dopoptosub_at(pTHX_ const PERL_CONTEXT *cxstk, I32 startingblock) switch (CxTYPE(cx)) { default: continue; - case CXt_EVAL: case CXt_SUB: + /* in sub foo { /(?{...})/ }, foo ends up on the CX stack + * twice; the first for the normal foo() call, and the second + * for a faked up re-entry into the sub to execute the + * code block. Hide this faked entry from the world. */ + if (cx->cx_type & CXp_SUB_RE_FAKE) + continue; + case CXt_EVAL: case CXt_FORMAT: DEBUG_l( Perl_deb(aTHX_ "(dopoptosub_at(): found sub at cx=%ld)\n", (long)i)); return i; @@ -1636,6 +1655,11 @@ Perl_die_unwind(pTHX_ SV *msv) sv_setsv(ERRSV, exceptsv); } + if (in_eval & EVAL_KEEPERR) { + Perl_ck_warner(aTHX_ packWARN(WARN_MISC), "\t(in cleanup) %"SVf, + SVfARG(exceptsv)); + } + while ((cxix = dopoptoeval(cxstack_ix)) < 0 && PL_curstackinfo->si_prev) { @@ -1694,13 +1718,8 @@ Perl_die_unwind(pTHX_ SV *msv) SVfARG(exceptsv ? exceptsv : newSVpvs_flags("Unknown error\n", SVs_TEMP))); } - if (in_eval & EVAL_KEEPERR) { - Perl_ck_warner(aTHX_ packWARN(WARN_MISC), "\t(in cleanup) %"SVf, - SVfARG(exceptsv)); - } - else { + if (!(in_eval & EVAL_KEEPERR)) sv_setsv(ERRSV, exceptsv); - } PL_restartjmpenv = restartjmpenv; PL_restartop = restartop; JMPENV_JUMP(3); @@ -1792,6 +1811,7 @@ PP(pp_caller) const HEK *stash_hek; I32 count = 0; bool has_arg = MAXARG && TOPs; + const COP *lcop; if (MAXARG) { if (has_arg) @@ -1835,7 +1855,11 @@ PP(pp_caller) PUSHTARG; } mPUSHs(newSVpv(OutCopFILE(cx->blk_oldcop), 0)); - mPUSHi((I32)CopLINE(cx->blk_oldcop)); + lcop = closest_cop(cx->blk_oldcop, cx->blk_oldcop->op_sibling, + cx->blk_sub.retop, TRUE); + if (!lcop) + lcop = cx->blk_oldcop; + mPUSHi((I32)CopLINE(lcop)); if (!has_arg) RETURN; if (CxTYPE(cx) == CXt_SUB || CxTYPE(cx) == CXt_FORMAT) { @@ -1888,7 +1912,7 @@ PP(pp_caller) && CopSTASH_eq(PL_curcop, PL_debstash)) { AV * const ary = cx->blk_sub.argarray; - const int off = AvARRAY(ary) - AvALLOC(ary); + const SSize_t off = AvARRAY(ary) - AvALLOC(ary); Perl_init_dbargs(aTHX); @@ -1998,8 +2022,12 @@ PP(pp_dbstate) PUSHSUB_DB(cx); cx->blk_sub.retop = PL_op->op_next; CvDEPTH(cv)++; + if (CvDEPTH(cv) >= 2) { + PERL_STACK_OVERFLOW_CHECK(); + pad_push(CvPADLIST(cv), CvDEPTH(cv)); + } SAVECOMPPAD(); - PAD_SET_CUR_NOSAVE(CvPADLIST(cv), 1); + PAD_SET_CUR_NOSAVE(CvPADLIST(cv), CvDEPTH(cv)); RETURNOP(CvSTART(cv)); } } @@ -2433,8 +2461,8 @@ PP(pp_return) } break; case CXt_FORMAT: - POPFORMAT(cx); retop = cx->blk_sub.retop; + POPFORMAT(cx); break; default: DIE(aTHX_ "panic: return, type=%u", (unsigned) CxTYPE(cx)); @@ -2523,8 +2551,8 @@ PP(pp_leavesublv) S_return_lvalues(aTHX_ newsp, SP, newsp, gimme, cx, newpm); LEAVE; - cxstack_ix--; POPSUB(cx,sv); /* Stack values are safe: release CV and @_ ... */ + cxstack_ix--; PL_curpm = newpm; /* ... and pop $1 et al */ LEAVESUB(sv); @@ -2655,6 +2683,7 @@ PP(pp_next) if (PL_scopestack_ix < inner) leave_scope(PL_scopestack[PL_scopestack_ix]); PL_curcop = cx->blk_oldcop; + PERL_ASYNC_CHECK(); return (cx)->blk_loop.my_op->op_nextop; } @@ -2678,6 +2707,7 @@ PP(pp_redo) LEAVE_SCOPE(oldsave); FREETMPS; PL_curcop = cx->blk_oldcop; + PERL_ASYNC_CHECK(); return redo_op; } @@ -2686,12 +2716,12 @@ S_dofindlabel(pTHX_ OP *o, const char *label, STRLEN len, U32 flags, OP **opstac { dVAR; OP **ops = opstack; - static const char too_deep[] = "Target of goto is too deeply nested"; + static const char* const too_deep = "Target of goto is too deeply nested"; PERL_ARGS_ASSERT_DOFINDLABEL; if (ops >= oplimit) - Perl_croak(aTHX_ too_deep); + Perl_croak(aTHX_ "%s", too_deep); if (o->op_type == OP_LEAVE || o->op_type == OP_SCOPE || o->op_type == OP_LEAVELOOP || @@ -2700,7 +2730,7 @@ S_dofindlabel(pTHX_ OP *o, const char *label, STRLEN len, U32 flags, OP **opstac { *ops++ = cUNOPo->op_first; if (ops >= oplimit) - Perl_croak(aTHX_ too_deep); + Perl_croak(aTHX_ "%s", too_deep); } *ops = 0; if (o->op_flags & OPf_KIDS) { @@ -2746,7 +2776,7 @@ S_dofindlabel(pTHX_ OP *o, const char *label, STRLEN len, U32 flags, OP **opstac return 0; } -PP(pp_goto) +PP(pp_goto) /* also pp_dump */ { dVAR; dSP; OP *retop = NULL; @@ -2758,20 +2788,21 @@ PP(pp_goto) STRLEN label_len = 0; U32 label_flags = 0; const bool do_dump = (PL_op->op_type == OP_DUMP); - static const char must_have_label[] = "goto must have label"; + static const char* const must_have_label = "goto must have label"; if (PL_op->op_flags & OPf_STACKED) { + /* goto EXPR or goto &foo */ + SV * const sv = POPs; + SvGETMAGIC(sv); /* This egregious kludge implements goto &subroutine */ if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVCV) { I32 cxix; PERL_CONTEXT *cx; CV *cv = MUTABLE_CV(SvRV(sv)); - SV** mark; - I32 items = 0; + AV *arg = GvAV(PL_defgv); I32 oldsave; - bool reified = 0; retry: if (!CvROOT(cv) && !CvXSUB(cv)) { @@ -2798,14 +2829,18 @@ PP(pp_goto) SvREFCNT_inc_simple_void(cv); /* avoid premature free during unwind */ FREETMPS; cxix = dopoptosub(cxstack_ix); - if (cxix < 0) - DIE(aTHX_ "Can't goto subroutine outside a subroutine"); - if (cxix < cxstack_ix) + if (cxix < cxstack_ix) { + if (cxix < 0) { + SvREFCNT_dec(cv); + DIE(aTHX_ "Can't goto subroutine outside a subroutine"); + } dounwind(cxix); + } TOPBLOCK(cx); SPAGAIN; /* ban goto in eval: see <20050521150056.GC20213@iabyn.com> */ if (CxTYPE(cx) == CXt_EVAL) { + SvREFCNT_dec(cv); if (CxREALEVAL(cx)) /* diag_listed_as: Can't goto subroutine from an eval-%s */ DIE(aTHX_ "Can't goto subroutine from an eval-string"); @@ -2814,35 +2849,25 @@ PP(pp_goto) DIE(aTHX_ "Can't goto subroutine from an eval-block"); } else if (CxMULTICALL(cx)) + { + SvREFCNT_dec(cv); DIE(aTHX_ "Can't goto subroutine from a sort sub (or similar callback)"); + } if (CxTYPE(cx) == CXt_SUB && CxHASARGS(cx)) { - /* put @_ back onto stack */ AV* av = cx->blk_sub.argarray; - items = AvFILLp(av) + 1; - EXTEND(SP, items+1); /* @_ could have been extended. */ - Copy(AvARRAY(av), SP + 1, items, SV*); - SvREFCNT_dec(GvAV(PL_defgv)); - GvAV(PL_defgv) = cx->blk_sub.savearray; - CLEAR_ARGARRAY(av); - /* abandon @_ if it got reified */ - if (AvREAL(av)) { - reified = 1; + /* abandon the original @_ if it got reified or if it is + the same as the current @_ */ + if (AvREAL(av) || av == arg) { SvREFCNT_dec(av); av = newAV(); - av_extend(av, items-1); AvREIFY_only(av); PAD_SVl(0) = MUTABLE_SV(cx->blk_sub.argarray = av); } + else CLEAR_ARGARRAY(av); } - else if (CvISXSUB(cv)) { /* put GvAV(defgv) back onto stack */ - AV* const av = GvAV(PL_defgv); - items = AvFILLp(av) + 1; - EXTEND(SP, items+1); /* @_ could have been extended. */ - Copy(AvARRAY(av), SP + 1, items, SV*); - } - mark = SP; - SP += items; + /* We donate this refcount later to the callee’s pad. */ + SvREFCNT_inc_simple_void(arg); if (CxTYPE(cx) == CXt_SUB && !(CvDEPTH(cx->blk_sub.cv) = cx->blk_sub.olddepth)) SvREFCNT_dec(cx->blk_sub.cv); @@ -2853,6 +2878,7 @@ PP(pp_goto) * our precious cv. See bug #99850. */ if (!CvROOT(cv) && !CvXSUB(cv)) { const GV * const gv = CvGV(cv); + SvREFCNT_dec(arg); if (gv) { SV * const tmpstr = sv_newmortal(); gv_efullname3(tmpstr, gv, NULL); @@ -2867,12 +2893,37 @@ PP(pp_goto) SAVEFREESV(cv); /* later, undo the 'avoid premature free' hack */ if (CvISXSUB(cv)) { OP* const retop = cx->blk_sub.retop; - SV **newsp PERL_UNUSED_DECL; - I32 gimme PERL_UNUSED_DECL; - if (reified) { - I32 index; + SV **newsp; + I32 gimme; + const SSize_t items = arg ? AvFILLp(arg) + 1 : 0; + SV** mark; + + PERL_UNUSED_VAR(newsp); + PERL_UNUSED_VAR(gimme); + + /* put GvAV(defgv) back onto stack */ + if (items) { + EXTEND(SP, items+1); /* @_ could have been extended. */ + Copy(AvARRAY(arg), SP + 1, items, SV*); + } + mark = SP; + SP += items; + if (items && AvREAL(arg)) { + SSize_t index; for (index=0; indexblk_sub.savearray; + SvREFCNT_dec(arg); } /* XS subs don't have a CxSUB, so pop it */ @@ -2882,15 +2933,11 @@ PP(pp_goto) PUTBACK; (void)(*CvXSUB(cv))(aTHX_ cv); LEAVE; + PERL_ASYNC_CHECK(); return retop; } else { PADLIST * const padlist = CvPADLIST(cv); - if (CxTYPE(cx) == CXt_EVAL) { - PL_in_eval = CxOLD_IN_EVAL(cx); - PL_eval_root = cx->blk_eval.old_eval_root; - cx->cx_type = CXt_SUB; - } cx->blk_sub.cv = cv; cx->blk_sub.olddepth = CvDEPTH(cv); @@ -2907,41 +2954,26 @@ PP(pp_goto) PAD_SET_CUR_NOSAVE(padlist, CvDEPTH(cv)); if (CxHASARGS(cx)) { - AV *const av = MUTABLE_AV(PAD_SVl(0)); - - cx->blk_sub.savearray = GvAV(PL_defgv); - GvAV(PL_defgv) = MUTABLE_AV(SvREFCNT_inc_simple(av)); CX_CURPAD_SAVE(cx->blk_sub); - cx->blk_sub.argarray = av; - if (items >= AvMAX(av) + 1) { - SV **ary = AvALLOC(av); - if (AvARRAY(av) != ary) { - AvMAX(av) += AvARRAY(av) - AvALLOC(av); - AvARRAY(av) = ary; - } - if (items >= AvMAX(av) + 1) { - AvMAX(av) = items - 1; - Renew(ary,items+1,SV*); - AvALLOC(av) = ary; - AvARRAY(av) = ary; - } - } - ++mark; - Copy(mark,AvARRAY(av),items,SV*); - AvFILLp(av) = items - 1; - assert(!AvREAL(av)); - if (reified) { - /* transfer 'ownership' of refcnts to new @_ */ - AvREAL_on(av); - AvREIFY_off(av); - } - while (items--) { - if (*mark) - SvTEMP_off(*mark); - mark++; + /* cx->blk_sub.argarray has no reference count, so we + need something to hang on to our argument array so + that cx->blk_sub.argarray does not end up pointing + to freed memory as the result of undef *_. So put + it in the callee’s pad, donating our refer- + ence count. */ + SvREFCNT_dec(PAD_SVl(0)); + PAD_SVl(0) = (SV *)(cx->blk_sub.argarray = arg); + + /* GvAV(PL_defgv) might have been modified on scope + exit, so restore it. */ + if (arg != GvAV(PL_defgv)) { + AV * const av = GvAV(PL_defgv); + GvAV(PL_defgv) = (AV *)SvREFCNT_inc_simple(arg); + SvREFCNT_dec(av); } } + else SvREFCNT_dec(arg); if (PERLDB_SUB) { /* Checking curstash breaks DProf. */ Perl_get_db_sub(aTHX_ NULL, cv); if (PERLDB_GOTO) { @@ -2953,20 +2985,23 @@ PP(pp_goto) } } } + PERL_ASYNC_CHECK(); RETURNOP(CvSTART(cv)); } } else { - label = SvPV_const(sv, label_len); + /* goto EXPR */ + label = SvPV_nomg_const(sv, label_len); label_flags = SvUTF8(sv); } } else if (!(PL_op->op_flags & OPf_SPECIAL)) { + /* goto LABEL or dump LABEL */ label = cPVOP->op_pv; label_flags = (cPVOP->op_private & OPpPV_IS_UTF8) ? SVf_UTF8 : 0; label_len = strlen(label); } - if (!(do_dump || label_len)) DIE(aTHX_ must_have_label); + if (!(do_dump || label_len)) DIE(aTHX_ "%s", must_have_label); PERL_ASYNC_CHECK(); @@ -3044,9 +3079,8 @@ PP(pp_goto) PL_lastgotoprobe = gotoprobe; } if (!retop) - DIE(aTHX_ "Can't find label %"SVf, - SVfARG(newSVpvn_flags(label, label_len, - SVs_TEMP | label_flags))); + DIE(aTHX_ "Can't find label %"UTF8f, + UTF8fARG(label_flags, label_len, label)); /* if we're leaving an eval, check before we pop any frames that we're not going to punt, otherwise the error @@ -3108,6 +3142,7 @@ PP(pp_goto) PL_do_undump = FALSE; } + PERL_ASYNC_CHECK(); RETURNOP(retop); } @@ -3253,7 +3288,11 @@ Perl_find_runcv_where(pTHX_ U8 cond, IV arg, U32 *db_seqp) int level = 0; if (db_seqp) - *db_seqp = PL_curcop->cop_seq; + *db_seqp = + PL_curcop == &PL_compiling + ? PL_cop_seqmax + : PL_curcop->cop_seq; + for (si = PL_curstackinfo; si; si = si->si_prev) { I32 ix; for (ix = si->si_cxix; ix >= 0; ix--) { @@ -3266,6 +3305,8 @@ Perl_find_runcv_where(pTHX_ U8 cond, IV arg, U32 *db_seqp) *db_seqp = cx->blk_oldcop->cop_seq; continue; } + if (cx->cx_type & CXp_SUB_RE) + continue; } else if (CxTYPE(cx) == CXt_EVAL && !CxTRYBLOCK(cx)) cv = cx->blk_eval.cv; @@ -3273,7 +3314,8 @@ Perl_find_runcv_where(pTHX_ U8 cond, IV arg, U32 *db_seqp) switch (cond) { case FIND_RUNCV_padid_eq: if (!CvPADLIST(cv) - || CvPADLIST(cv)->xpadl_id != (U32)arg) continue; + || PadlistNAMES(CvPADLIST(cv)) != INT2PTR(PADNAMELIST *, arg)) + continue; return cv; case FIND_RUNCV_level_eq: if (level++ != arg) continue; @@ -3344,7 +3386,9 @@ S_doeval(pTHX_ int gimme, CV* outside, U32 seq, HV *hh) PL_in_eval = (in_require ? (EVAL_INREQUIRE | (PL_in_eval & EVAL_INEVAL)) - : EVAL_INEVAL); + : (EVAL_INEVAL | + ((PL_op->op_private & OPpEVAL_RE_REPARSING) + ? EVAL_RE_REPARSING : 0))); PUSHMARK(SP); @@ -3370,7 +3414,9 @@ S_doeval(pTHX_ int gimme, CV* outside, U32 seq, HV *hh) if (CopSTASH_ne(PL_curcop, PL_curstash)) { SAVEGENERICSV(PL_curstash); - PL_curstash = (HV *)SvREFCNT_inc_simple(CopSTASH(PL_curcop)); + PL_curstash = (HV *)CopSTASH(PL_curcop); + if (SvTYPE(PL_curstash) != SVt_PVHV) PL_curstash = NULL; + else SvREFCNT_inc_simple_void(PL_curstash); } /* XXX:ajgo do we really need to alloc an AV for begin/checkunit */ SAVESPTR(PL_beginav); @@ -3406,6 +3452,15 @@ S_doeval(pTHX_ int gimme, CV* outside, U32 seq, HV *hh) else { PL_hints = saveop->op_private & OPpEVAL_COPHH ? oldcurcop->cop_hints : saveop->op_targ; + + /* making 'use re eval' not be in scope when compiling the + * qr/mabye_has_runtime_code_block/ ensures that we don't get + * infinite recursion when S_has_runtime_code() gives a false + * positive: the second time round, HINT_RE_EVAL isn't set so we + * don't bother calling S_has_runtime_code() */ + if (PL_in_eval & EVAL_RE_REPARSING) + PL_hints &= ~HINT_RE_EVAL; + if (hh) { /* SAVEHINTS created a new HV in PL_hintgv, which we need to GC */ SvREFCNT_dec(GvHV(PL_hintgv)); @@ -3450,6 +3505,7 @@ S_doeval(pTHX_ int gimme, CV* outside, U32 seq, HV *hh) PERL_CONTEXT *cx; I32 optype; /* Used by POPEVAL. */ SV *namesv; + SV *errsv = NULL; cx = NULL; namesv = NULL; @@ -3461,7 +3517,6 @@ S_doeval(pTHX_ int gimme, CV* outside, U32 seq, HV *hh) PL_op = saveop; if (yystatus != 3) { if (PL_eval_root) { - cv_forget_slab(evalcv); op_free(PL_eval_root); PL_eval_root = NULL; } @@ -3473,6 +3528,7 @@ S_doeval(pTHX_ int gimme, CV* outside, U32 seq, HV *hh) LEAVE_with_name("eval"); /* pp_entereval knows about this LEAVE. */ } + errsv = ERRSV; if (in_require) { if (!cx) { /* If cx is still NULL, it means that we didn't go in the @@ -3486,13 +3542,13 @@ S_doeval(pTHX_ int gimme, CV* outside, U32 seq, HV *hh) SvUTF8(namesv) ? -(I32)SvCUR(namesv) : (I32)SvCUR(namesv), &PL_sv_undef, 0); Perl_croak(aTHX_ "%"SVf"Compilation failed in require", - SVfARG(ERRSV - ? ERRSV + SVfARG(errsv + ? errsv : newSVpvs_flags("Unknown error\n", SVs_TEMP))); } else { - if (!*(SvPVx_nolen_const(ERRSV))) { - sv_setpvs(ERRSV, "Compilation error"); + if (!*(SvPV_nolen_const(errsv))) { + sv_setpvs(errsv, "Compilation error"); } } if (gimme != G_ARRAY) PUSHs(&PL_sv_undef); @@ -3542,10 +3598,21 @@ S_check_type_and_open(pTHX_ SV *name) { Stat_t st; const char *p = SvPV_nolen_const(name); - const int st_rc = PerlLIO_stat(p, &st); + int st_rc; PERL_ARGS_ASSERT_CHECK_TYPE_AND_OPEN; + /* checking here captures a reasonable error message when + * PERL_DISABLE_PMC is true, but when PMC checks are enabled, the + * user gets a confusing message about looking for the .pmc file + * rather than for the .pm file. + * This check prevents a \0 in @INC causing problems. + */ + if (!IS_SAFE_PATHNAME(name, "require")) + return NULL; + + st_rc = PerlLIO_stat(p, &st); + if (st_rc < 0 || S_ISDIR(st.st_mode) || S_ISBLK(st.st_mode)) { return NULL; } @@ -3566,6 +3633,13 @@ S_doopen_pm(pTHX_ SV *name) PERL_ARGS_ASSERT_DOOPEN_PM; + /* check the name before trying for the .pmc name to avoid the + * warning referring to the .pmc which the user probably doesn't + * know or care about + */ + if (!IS_SAFE_PATHNAME(name, "require")) + return NULL; + if (namelen > 3 && memEQs(p + namelen - 3, 3, ".pm")) { SV *const pmcsv = sv_newmortal(); Stat_t pmcstat; @@ -3582,6 +3656,32 @@ S_doopen_pm(pTHX_ SV *name) # define doopen_pm(name) check_type_and_open(name) #endif /* !PERL_DISABLE_PMC */ +/* require doesn't search for absolute names, or when the name is + explicity relative the current directory */ +PERL_STATIC_INLINE bool +S_path_is_searchable(const char *name) +{ + PERL_ARGS_ASSERT_PATH_IS_SEARCHABLE; + + if (PERL_FILE_IS_ABSOLUTE(name) +#ifdef WIN32 + || (*name == '.' && ((name[1] == '/' || + (name[1] == '.' && name[2] == '/')) + || (name[1] == '\\' || + ( name[1] == '.' && name[2] == '\\'))) + ) +#else + || (*name == '.' && (name[1] == '/' || + (name[1] == '.' && name[2] == '/'))) +#endif + ) + { + return FALSE; + } + else + return TRUE; +} + PP(pp_require) { dVAR; dSP; @@ -3609,11 +3709,12 @@ PP(pp_require) SV *encoding; OP *op; int saved_errno; + bool path_searchable; sv = POPs; if ( (SvNIOKp(sv) || SvVOK(sv)) && PL_op->op_type != OP_DOFILE) { sv = sv_2mortal(new_version(sv)); - if (!sv_derived_from(PL_patchlevel, "version")) + if (!Perl_sv_derived_from_pvn(aTHX_ PL_patchlevel, STR_WITH_LEN("version"), 0)) upg_version(PL_patchlevel, TRUE); if (cUNOP->op_first->op_type == OP_CONST && cUNOP->op_first->op_private & OPpCONST_NOVER) { if ( vcmp(sv,PL_patchlevel) <= 0 ) @@ -3671,8 +3772,15 @@ PP(pp_require) name = SvPV_const(sv, len); if (!(name && len > 0 && *name)) DIE(aTHX_ "Null filename used"); + if (!IS_SAFE_PATHNAME(sv, "require")) { + DIE(aTHX_ "Can't locate %s: %s", + pv_escape(newSVpvs_flags("",SVs_TEMP),SvPVX(sv),SvCUR(sv), + SvCUR(sv)*2,NULL, SvUTF8(sv)?PERL_PV_ESCAPE_UNI:0), + Strerror(ENOENT)); + } TAINT_PROPER("require"); + path_searchable = path_is_searchable(name); #ifdef VMS /* The key in the %ENV hash is in the syntax of file passed as the argument @@ -3712,14 +3820,14 @@ PP(pp_require) /* prepare to compile file */ - if (path_is_absolute(name)) { + if (!path_searchable) { /* At this point, name is SvPVX(sv) */ tryname = name; tryrsfp = doopen_pm(sv); } - if (!tryrsfp && !(errno == EACCES && path_is_absolute(name))) { + if (!tryrsfp && !(errno == EACCES && !path_searchable)) { AV * const ar = GvAVn(PL_incgv); - I32 i; + SSize_t i; #ifdef VMS if (vms_unixname) #endif @@ -3770,7 +3878,6 @@ PP(pp_require) if (SvROK(arg) && (SvTYPE(SvRV(arg)) <= SVt_PVLV) && !isGV_with_GP(SvRV(arg))) { filter_cache = SvRV(arg); - SvREFCNT_inc_simple_void_NN(filter_cache); if (i < count) { arg = SP[i++]; @@ -3833,10 +3940,7 @@ PP(pp_require) } filter_has_file = 0; - if (filter_cache) { - SvREFCNT_dec(filter_cache); - filter_cache = NULL; - } + filter_cache = NULL; if (filter_state) { SvREFCNT_dec(filter_state); filter_state = NULL; @@ -3847,8 +3951,7 @@ PP(pp_require) } } else { - if (!path_is_absolute(name) - ) { + if (path_searchable) { const char *dir; STRLEN dirlen; @@ -3889,7 +3992,12 @@ PP(pp_require) memcpy(tmp, dir, dirlen); tmp +=dirlen; - *tmp++ = '/'; + + /* Avoid '//' */ + if (!dirlen || *(tmp-1) != '/') { + *tmp++ = '/'; + } + /* name came from an SV, so it will have a '\0' at the end that we can copy as part of this memcpy(). */ memcpy(tmp, name, len + 1); @@ -3905,7 +4013,7 @@ PP(pp_require) if (tryrsfp) { if (tryname[0] == '.' && tryname[1] == '/') { ++tryname; - while (*++tryname == '/'); + while (*++tryname == '/') {} } break; } @@ -3932,8 +4040,8 @@ PP(pp_require) } else { if (namesv) { /* did we lookup @INC? */ AV * const ar = GvAVn(PL_incgv); - I32 i; - SV *const msg = newSVpv("", 0); + SSize_t i; + SV *const msg = newSVpvs_flags("", SVs_TEMP); SV *const inc = newSVpvs_flags("", SVs_TEMP); for (i = 0; i <= AvFILL(ar); i++) { sv_catpvs(inc, " "); @@ -3998,7 +4106,10 @@ PP(pp_require) than hanging another SV from it. In turn, filter_add() optionally takes the SV to use as the filter (or creates a new SV if passed NULL), so simply pass in whatever value filter_cache has. */ - SV * const datasv = filter_add(S_run_user_filter, filter_cache); + SV * const fc = filter_cache ? newSV(0) : NULL; + SV *datasv; + if (fc) sv_copypv(fc, filter_cache); + datasv = filter_add(S_run_user_filter, fc); IoLINES(datasv) = filter_has_file; IoTOP_GV(datasv) = MUTABLE_GV(filter_state); IoBOTTOM_GV(datasv) = MUTABLE_GV(filter_sub); @@ -4496,7 +4607,7 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other, const bool copied) } else if (SvROK(d) && SvTYPE(SvRV(d)) == SVt_PVAV) { /* Test sub truth for each element */ - I32 i; + SSize_t i; bool andedresults = TRUE; AV *av = (AV*) SvRV(d); const I32 len = av_len(av); @@ -4611,8 +4722,8 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other, const bool copied) } else if (SvROK(d) && SvTYPE(SvRV(d)) == SVt_PVAV) { AV * const other_av = MUTABLE_AV(SvRV(d)); - const I32 other_len = av_len(other_av) + 1; - I32 i; + const SSize_t other_len = av_len(other_av) + 1; + SSize_t i; HV *hv = MUTABLE_HV(SvRV(e)); DEBUG_M(Perl_deb(aTHX_ " applying rule Array-Hash\n")); @@ -4663,8 +4774,8 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other, const bool copied) } else if (SvROK(d) && SvTYPE(SvRV(d)) == SVt_PVHV) { AV * const other_av = MUTABLE_AV(SvRV(e)); - const I32 other_len = av_len(other_av) + 1; - I32 i; + const SSize_t other_len = av_len(other_av) + 1; + SSize_t i; DEBUG_M(Perl_deb(aTHX_ " applying rule Hash-Array\n")); for (i = 0; i < other_len; ++i) { @@ -4684,8 +4795,8 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other, const bool copied) if (av_len(MUTABLE_AV(SvRV(e))) != av_len(other_av)) RETPUSHNO; else { - I32 i; - const I32 other_len = av_len(other_av); + SSize_t i; + const SSize_t other_len = av_len(other_av); if (NULL == seen_this) { seen_this = newHV(); @@ -4740,8 +4851,8 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other, const bool copied) sm_regex_array: { PMOP * const matcher = make_matcher((REGEXP*) SvRV(d)); - const I32 this_len = av_len(MUTABLE_AV(SvRV(e))); - I32 i; + const SSize_t this_len = av_len(MUTABLE_AV(SvRV(e))); + SSize_t i; for(i = 0; i <= this_len; ++i) { SV * const * const svp = av_fetch(MUTABLE_AV(SvRV(e)), i, FALSE); @@ -4757,8 +4868,8 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other, const bool copied) } else if (!SvOK(d)) { /* undef ~~ array */ - const I32 this_len = av_len(MUTABLE_AV(SvRV(e))); - I32 i; + const SSize_t this_len = av_len(MUTABLE_AV(SvRV(e))); + SSize_t i; DEBUG_M(Perl_deb(aTHX_ " applying rule Undef-Array\n")); for (i = 0; i <= this_len; ++i) { @@ -4772,8 +4883,8 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other, const bool copied) else { sm_any_array: { - I32 i; - const I32 this_len = av_len(MUTABLE_AV(SvRV(e))); + SSize_t i; + const SSize_t this_len = av_len(MUTABLE_AV(SvRV(e))); DEBUG_M(Perl_deb(aTHX_ " applying rule Any-Array\n")); for (i = 0; i <= this_len; ++i) { @@ -4935,10 +5046,13 @@ PP(pp_leavewhen) leave_scope(PL_scopestack[PL_scopestack_ix]); PL_curcop = cx->blk_oldcop; + PERL_ASYNC_CHECK(); return cx->blk_loop.my_op->op_nextop; } - else + else { + PERL_ASYNC_CHECK(); RETURNOP(cx->blk_givwhen.leave_op); + } } PP(pp_continue) @@ -5370,11 +5484,14 @@ S_run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen) if (count > 0) { SV *out = POPs; + SvGETMAGIC(out); if (SvOK(out)) { status = SvIV(out); } - else if (SvTRUE(ERRSV)) { - err = newSVsv(ERRSV); + else { + SV * const errsv = ERRSV; + if (SvTRUE_NN(errsv)) + err = newSVsv(errsv); } } @@ -5383,9 +5500,13 @@ S_run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen) LEAVE_with_name("call_filter_sub"); } + if (SvGMAGICAL(upstream)) { + mg_get(upstream); + if (upstream == buf_sv) mg_free(buf_sv); + } if (SvIsCOW(upstream)) sv_force_normal(upstream); if(!err && SvOK(upstream)) { - got_p = SvPV(upstream, got_len); + got_p = SvPV_nomg(upstream, got_len); if (umaxlen) { if (got_len > umaxlen) { prune_from = got_p + umaxlen; @@ -5416,7 +5537,12 @@ S_run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen) if (SvUTF8(upstream)) { SvUTF8_on(cache); } - SvCUR_set(upstream, got_len - cached_len); + if (SvPOK(upstream)) SvCUR_set(upstream, got_len - cached_len); + else + /* Cannot just use sv_setpvn, as that could free the buffer + before we have a chance to assign it. */ + sv_usepvn(upstream, savepvn(got_p, got_len - cached_len), + got_len - cached_len); *prune_from = 0; /* Can't yet be EOF */ if (status == 0) @@ -5428,9 +5554,10 @@ S_run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen) concatenate it then we get a warning about use of uninitialised value. */ if (!err && upstream != buf_sv && - (SvOK(upstream) || SvGMAGICAL(upstream))) { - sv_catsv(buf_sv, upstream); + SvOK(upstream)) { + sv_catsv_nomg(buf_sv, upstream); } + else if (SvOK(upstream)) (void)SvPV_force_nolen(buf_sv); if (status <= 0) { IoLINES(datasv) = 0; @@ -5457,32 +5584,6 @@ S_run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen) return status; } -/* perhaps someone can come up with a better name for - this? it is not really "absolute", per se ... */ -static bool -S_path_is_absolute(const char *name) -{ - PERL_ARGS_ASSERT_PATH_IS_ABSOLUTE; - - if (PERL_FILE_IS_ABSOLUTE(name) -#ifdef WIN32 - || (*name == '.' && ((name[1] == '/' || - (name[1] == '.' && name[2] == '/')) - || (name[1] == '\\' || - ( name[1] == '.' && name[2] == '\\'))) - ) -#else - || (*name == '.' && (name[1] == '/' || - (name[1] == '.' && name[2] == '/'))) -#endif - ) - { - return TRUE; - } - else - return FALSE; -} - /* * Local variables: * c-indentation-style: bsd