X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/f14cf3632059d421de83cf901c7e849adc1fcd03..281cff281e54d71fbedd8c314fe56ae9b58bee67:/pp_ctl.c diff --git a/pp_ctl.c b/pp_ctl.c index 5f3cfdf..a38b9c1 100644 --- a/pp_ctl.c +++ b/pp_ctl.c @@ -213,9 +213,9 @@ PP(pp_substcont) SvGETMAGIC(TOPs); /* possibly clear taint on $1 etc: #67962 */ /* See "how taint works" above pp_subst() */ - if (SvTAINTED(TOPs)) - cx->sb_rxtainted |= SUBST_TAINT_REPL; sv_catsv_nomg(dstr, POPs); + if (UNLIKELY(TAINT_get)) + cx->sb_rxtainted |= SUBST_TAINT_REPL; if (CxONCE(cx) || s < orig || !CALLREGEXEC(rx, s, cx->sb_strend, orig, (s == m), cx->sb_targ, NULL, @@ -715,6 +715,7 @@ PP(pp_formline) SvSETMAGIC(sv); break; } + /* FALLTHROUGH */ case FF_LINESNGL: /* process ^* */ chopspace = 0; @@ -780,7 +781,8 @@ PP(pp_formline) * for safety */ grow = linemax; while (linemark--) - s += UTF8SKIP(s); + s += UTF8_SAFE_SKIP(s, + (U8 *) SvEND(PL_formtarget)); linemark = s - (U8*)SvPVX(PL_formtarget); } /* Easy. They agree. */ @@ -867,9 +869,9 @@ PP(pp_formline) } #else /* we generate fmt ourselves so it is safe */ - GCC_DIAG_IGNORE(-Wformat-nonliteral); + GCC_DIAG_IGNORE_STMT(-Wformat-nonliteral); len = my_snprintf(t, max, fmt, (int) fieldsize, (int) arg, value); - GCC_DIAG_RESTORE; + GCC_DIAG_RESTORE_STMT; #endif PERL_MY_SNPRINTF_POST_GUARD(len, max); RESTORE_LC_NUMERIC(); @@ -915,7 +917,7 @@ PP(pp_formline) *t++ = ' '; } s1 = t - 3; - if (strnEQ(s1," ",3)) { + if (strBEGINs(s1," ")) { while (s1 > SvPVX_const(PL_formtarget) && isSPACE(s1[-1])) s1--; } @@ -2006,16 +2008,7 @@ PP(pp_caller) mask = &PL_sv_undef ; else if (old_warnings == pWARN_ALL || (old_warnings == pWARN_STD && PL_dowarn & G_WARN_ON)) { - /* Get the bit mask for $warnings::Bits{all}, because - * it could have been extended by warnings::register */ - SV **bits_all; - HV * const bits = get_hv("warnings::Bits", 0); - if (bits && (bits_all=hv_fetchs(bits, "all", FALSE))) { - mask = newSVsv(*bits_all); - } - else { - mask = newSVpvn(WARN_ALLstring, WARNsize) ; - } + mask = newSVpvn(WARN_ALLstring, WARNsize) ; } else mask = newSVpvn((char *) (old_warnings + 1), old_warnings[0]); @@ -2652,6 +2645,9 @@ PP(pp_redo) return redo_op; } +#define UNENTERABLE (OP *)1 +#define GOTO_DEPTH 64 + STATIC OP * S_dofindlabel(pTHX_ OP *o, const char *label, STRLEN len, U32 flags, OP **opstack, OP **oplimit) { @@ -2666,15 +2662,34 @@ S_dofindlabel(pTHX_ OP *o, const char *label, STRLEN len, U32 flags, OP **opstac o->op_type == OP_SCOPE || o->op_type == OP_LEAVELOOP || o->op_type == OP_LEAVESUB || - o->op_type == OP_LEAVETRY) + o->op_type == OP_LEAVETRY || + o->op_type == OP_LEAVEGIVEN) { *ops++ = cUNOPo->op_first; - if (ops >= oplimit) - Perl_croak(aTHX_ "%s", too_deep); } + else if (oplimit - opstack < GOTO_DEPTH) { + if (o->op_flags & OPf_KIDS + && cUNOPo->op_first->op_type == OP_PUSHMARK) { + *ops++ = UNENTERABLE; + } + else if (o->op_flags & OPf_KIDS && PL_opargs[o->op_type] + && OP_CLASS(o) != OA_LOGOP + && o->op_type != OP_LINESEQ + && o->op_type != OP_SREFGEN + && o->op_type != OP_ENTEREVAL + && o->op_type != OP_GLOB + && o->op_type != OP_RV2CV) { + OP * const kid = cUNOPo->op_first; + if (OP_GIMME(kid, 0) != G_SCALAR || OpHAS_SIBLING(kid)) + *ops++ = UNENTERABLE; + } + } + if (ops >= oplimit) + Perl_croak(aTHX_ "%s", too_deep); *ops = 0; if (o->op_flags & OPf_KIDS) { OP *kid; + OP * const kid1 = cUNOPo->op_first; /* First try all the kids at this level, since that's likeliest. */ for (kid = cUNOPo->op_first; kid; kid = OpSIBLING(kid)) { if (kid->op_type == OP_NEXTSTATE || kid->op_type == OP_DBSTATE) { @@ -2697,19 +2712,27 @@ S_dofindlabel(pTHX_ OP *o, const char *label, STRLEN len, U32 flags, OP **opstac } } for (kid = cUNOPo->op_first; kid; kid = OpSIBLING(kid)) { + bool first_kid_of_binary = FALSE; if (kid == PL_lastgotoprobe) continue; if (kid->op_type == OP_NEXTSTATE || kid->op_type == OP_DBSTATE) { if (ops == opstack) *ops++ = kid; - else if (ops[-1]->op_type == OP_NEXTSTATE || - ops[-1]->op_type == OP_DBSTATE) + else if (ops[-1] != UNENTERABLE + && (ops[-1]->op_type == OP_NEXTSTATE || + ops[-1]->op_type == OP_DBSTATE)) ops[-1] = kid; else *ops++ = kid; } + if (kid == kid1 && ops != opstack && ops[-1] == UNENTERABLE) { + first_kid_of_binary = TRUE; + ops--; + } if ((o = dofindlabel(kid, label, len, flags, ops, oplimit))) return o; + if (first_kid_of_binary) + *ops++ = UNENTERABLE; } } *ops = 0; @@ -2717,6 +2740,23 @@ S_dofindlabel(pTHX_ OP *o, const char *label, STRLEN len, U32 flags, OP **opstac } +static void +S_check_op_type(pTHX_ OP * const o) +{ + /* Eventually we may want to stack the needed arguments + * for each op. For now, we punt on the hard ones. */ + /* XXX This comment seems to me like wishful thinking. --sprout */ + if (o == UNENTERABLE) + Perl_croak(aTHX_ + "Can't \"goto\" into a binary or list expression"); + if (o->op_type == OP_ENTERITER) + Perl_croak(aTHX_ + "Can't \"goto\" into the middle of a foreach loop"); + if (o->op_type == OP_ENTERGIVEN) + Perl_croak(aTHX_ + "Can't \"goto\" into a \"given\" block"); +} + /* also used for: pp_dump() */ PP(pp_goto) @@ -2725,7 +2765,6 @@ PP(pp_goto) OP *retop = NULL; I32 ix; PERL_CONTEXT *cx; -#define GOTO_DEPTH 64 OP *enterops[GOTO_DEPTH]; const char *label = NULL; STRLEN label_len = 0; @@ -3058,12 +3097,14 @@ PP(pp_goto) if (leaving_eval && *enterops && enterops[1]) { I32 i; for (i = 1; enterops[i]; i++) - if (enterops[i]->op_type == OP_ENTERITER) - DIE(aTHX_ "Can't \"goto\" into the middle of a foreach loop"); + S_check_op_type(aTHX_ enterops[i]); } if (*enterops && enterops[1]) { - I32 i = enterops[1]->op_type == OP_ENTER && in_block ? 2 : 1; + I32 i = enterops[1] != UNENTERABLE + && enterops[1]->op_type == OP_ENTER && in_block + ? 2 + : 1; if (enterops[i]) deprecate("\"goto\" to jump into a construct"); } @@ -3082,13 +3123,15 @@ PP(pp_goto) if (*enterops && enterops[1]) { OP * const oldop = PL_op; - ix = enterops[1]->op_type == OP_ENTER && in_block ? 2 : 1; + ix = enterops[1] != UNENTERABLE + && enterops[1]->op_type == OP_ENTER && in_block + ? 2 + : 1; for (; enterops[ix]; ix++) { PL_op = enterops[ix]; - /* Eventually we may want to stack the needed arguments - * for each op. For now, we punt on the hard ones. */ - if (PL_op->op_type == OP_ENTERITER) - DIE(aTHX_ "Can't \"goto\" into the middle of a foreach loop"); + S_check_op_type(aTHX_ PL_op); + DEBUG_l( Perl_deb(aTHX_ "pp_goto: Entering %s\n", + OP_NAME(PL_op))); PL_op->op_ppaddr(aTHX); } PL_op = oldop; @@ -3276,7 +3319,7 @@ Perl_find_runcv_where(pTHX_ U8 cond, IV arg, U32 *db_seqp) return cv; case FIND_RUNCV_level_eq: if (level++ != arg) continue; - /* GERONIMO! */ + /* FALLTHROUGH */ default: return cv; } @@ -3372,7 +3415,11 @@ S_doeval_compile(pTHX_ U8 gimme, CV* outside, U32 seq, HV *hh) SAVEGENERICSV(PL_curstash); PL_curstash = (HV *)CopSTASH(PL_curcop); if (SvTYPE(PL_curstash) != SVt_PVHV) PL_curstash = NULL; - else SvREFCNT_inc_simple_void(PL_curstash); + else { + SvREFCNT_inc_simple_void(PL_curstash); + save_item(PL_curstname); + sv_sethek(PL_curstname, HvNAME_HEK(PL_curstash)); + } } /* XXX:ajgo do we really need to alloc an AV for begin/checkunit */ SAVESPTR(PL_beginav); @@ -3557,15 +3604,22 @@ S_check_type_and_open(pTHX_ SV *name) errno EACCES, so only do a stat to separate a dir from a real EACCES caused by user perms */ #ifndef WIN32 - /* we use the value of errno later to see how stat() or open() failed. - * We don't want it set if the stat succeeded but we still failed, - * such as if the name exists, but is a directory */ - errno = 0; - st_rc = PerlLIO_stat(p, &st); - if (st_rc < 0 || S_ISDIR(st.st_mode) || S_ISBLK(st.st_mode)) { + if (st_rc < 0) return NULL; + else { + int eno; + if(S_ISBLK(st.st_mode)) { + eno = EINVAL; + goto not_file; + } + else if(S_ISDIR(st.st_mode)) { + eno = EISDIR; + not_file: + errno = eno; + return NULL; + } } #endif @@ -3577,8 +3631,10 @@ S_check_type_and_open(pTHX_ SV *name) int eno; st_rc = PerlLIO_stat(p, &st); if (st_rc >= 0) { - if(S_ISDIR(st.st_mode) || S_ISBLK(st.st_mode)) - eno = 0; + if(S_ISDIR(st.st_mode)) + eno = EISDIR; + else if(S_ISBLK(st.st_mode)) + eno = EINVAL; else eno = EACCES; errno = eno; @@ -3609,7 +3665,7 @@ S_doopen_pm(pTHX_ SV *name) if (!IS_SAFE_PATHNAME(p, namelen, "require")) return NULL; - if (namelen > 3 && memEQs(p + namelen - 3, 3, ".pm")) { + if (memENDPs(p, namelen, ".pm")) { SV *const pmcsv = sv_newmortal(); PerlIO * pmcio; @@ -3752,6 +3808,7 @@ S_require_file(pTHX_ SV *sv) I32 old_savestack_ix; const bool op_is_require = PL_op->op_type == OP_REQUIRE; const char *const op_name = op_is_require ? "require" : "do"; + SV ** svp_cached = NULL; assert(op_is_require || PL_op->op_type == OP_DOFILE); @@ -3761,6 +3818,15 @@ S_require_file(pTHX_ SV *sv) if (!(name && len > 0 && *name)) DIE(aTHX_ "Missing or undefined argument to %s", op_name); +#ifndef VMS + /* try to return earlier (save the SAFE_PATHNAME check) if INC already got the name */ + if (op_is_require) { + /* can optimize to only perform one single lookup */ + svp_cached = hv_fetch(GvHVn(PL_incgv), (char*) name, len, 0); + if ( svp_cached && *svp_cached != &PL_sv_undef ) RETPUSHYES; + } +#endif + if (!IS_SAFE_PATHNAME(name, len, op_name)) { if (!op_is_require) { CLEAR_ERRSV(); @@ -3799,8 +3865,8 @@ S_require_file(pTHX_ SV *sv) unixlen = len; } if (op_is_require) { - SV * const * const svp = hv_fetch(GvHVn(PL_incgv), - unixname, unixlen, 0); + /* reuse the previous hv_fetch result if possible */ + SV * const * const svp = svp_cached ? svp_cached : hv_fetch(GvHVn(PL_incgv), unixname, unixlen, 0); if ( svp ) { if (*svp != &PL_sv_undef) RETPUSHYES; @@ -3834,7 +3900,7 @@ S_require_file(pTHX_ SV *sv) directory, or (*nix) hidden filenames. Also sanity check that the generated filename ends .pm */ if (!path_searchable || len < 3 || name[0] == '.' - || !memEQ(name + package_len, ".pm", 3)) + || !memEQs(name + package_len, len - package_len, ".pm")) DIE(aTHX_ "Bareword in require maps to disallowed filename \"%" SVf "\"", sv); if (memchr(name, 0, package_len)) { /* diag_listed_as: Bareword in require contains "%s" */ @@ -4038,8 +4104,7 @@ S_require_file(pTHX_ SV *sv) continue; sv_setpv(namesv, unixdir); sv_catpv(namesv, unixname); -#else -# ifdef __SYMBIAN32__ +#elif defined(__SYMBIAN32__) if (PL_origfilename[0] && PL_origfilename[1] == ':' && !(dir[0] && dir[1] == ':')) @@ -4051,7 +4116,7 @@ S_require_file(pTHX_ SV *sv) Perl_sv_setpvf(aTHX_ namesv, "%s\\%s", dir, name); -# else +#else /* The equivalent of Perl_sv_setpvf(aTHX_ namesv, "%s/%s", dir, name); but without the need to parse the format string, or @@ -4078,7 +4143,6 @@ S_require_file(pTHX_ SV *sv) SvCUR_set(namesv, dirlen + len + 1); SvPOK_on(namesv); } -# endif #endif TAINT_PROPER(op_name); tryname = SvPVX_const(namesv); @@ -4120,12 +4184,12 @@ S_require_file(pTHX_ SV *sv) SSize_t i; SV *const msg = newSVpvs_flags("", SVs_TEMP); SV *const inc = newSVpvs_flags("", SVs_TEMP); - const char *e = name + len - 3; /* possible .pm */ for (i = 0; i <= AvFILL(ar); i++) { sv_catpvs(inc, " "); sv_catsv(inc, *av_fetch(ar, i, TRUE)); } - if (e > name && _memEQs(e, ".pm")) { + if (memENDPs(name, len, ".pm")) { + const char *e = name + len - (sizeof(".pm") - 1); const char *c; bool utf8 = cBOOL(SvUTF8(sv)); @@ -4155,7 +4219,7 @@ S_require_file(pTHX_ SV *sv) } if (c == e && isIDFIRST_lazy_if_safe(name, e, utf8)) { - sv_catpv(msg, " (you may need to install the "); + sv_catpvs(msg, " (you may need to install the "); for (c = name; c < e; c++) { if (*c == '/') { sv_catpvs(msg, "::"); @@ -4164,14 +4228,14 @@ S_require_file(pTHX_ SV *sv) sv_catpvn(msg, c, 1); } } - sv_catpv(msg, " module)"); + sv_catpvs(msg, " module)"); } } - else if (len >= 2 && memEQ(name + len - 2, ".h", 3)) { - sv_catpv(msg, " (change .h to .ph maybe?) (did you run h2ph?)"); + else if (memENDs(name, len, ".h")) { + sv_catpvs(msg, " (change .h to .ph maybe?) (did you run h2ph?)"); } - else if (len >= 3 && memEQ(name + len - 3, ".ph", 4)) { - sv_catpv(msg, " (did you run h2ph?)"); + else if (memENDs(name, len, ".ph")) { + sv_catpvs(msg, " (did you run h2ph?)"); } /* diag_listed_as: Can't locate %s */ @@ -5163,8 +5227,11 @@ PP(pp_enterwhen) to the op that follows the leavewhen. RETURNOP calls PUTBACK which restores the stack pointer after the POPs. */ - if (!(PL_op->op_flags & OPf_SPECIAL) && !SvTRUEx(POPs)) + if (!(PL_op->op_flags & OPf_SPECIAL) && !SvTRUEx(POPs)) { + if (gimme == G_SCALAR) + PUSHs(&PL_sv_undef); RETURNOP(cLOGOP->op_other->op_next); + } cx = cx_pushblock(CXt_WHEN, gimme, SP, PL_savestack_ix); cx_pushwhen(cx); @@ -5363,7 +5430,8 @@ S_doparseform(pTHX_ SV *sv) if (s < send) { skipspaces = 0; continue; - } /* else FALL THROUGH */ + } + /* FALLTHROUGH */ case '\n': arg = s - base; skipspaces++;