X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/b2b95e4c717e3e7005a2a533840bce801ccf74bb..3805b5fb04f8819edfb6bd5256d5eefd7b23e730:/mg.c diff --git a/mg.c b/mg.c index bdded26..d22f620 100644 --- a/mg.c +++ b/mg.c @@ -76,6 +76,7 @@ void setegid(uid_t id); #endif /* + * Pre-magic setup and post-magic takedown. * Use the "DESTRUCTOR" scope cleanup to reinstate magic. */ @@ -89,13 +90,15 @@ struct magic_state { /* MGS is typedef'ed to struct magic_state in perl.h */ STATIC void -S_save_magic(pTHX_ I32 mgs_ix, SV *sv) +S_save_magic_flags(pTHX_ I32 mgs_ix, SV *sv, U32 flags) { dVAR; MGS* mgs; bool bumped = FALSE; - PERL_ARGS_ASSERT_SAVE_MAGIC; + PERL_ARGS_ASSERT_SAVE_MAGIC_FLAGS; + + assert(SvMAGICAL(sv)); /* we shouldn't really be called here with RC==0, but it can sometimes * happen via mg_clear() (which also shouldn't be called when RC==0, @@ -108,29 +111,21 @@ S_save_magic(pTHX_ I32 mgs_ix, SV *sv) bumped = TRUE; } - assert(SvMAGICAL(sv)); - /* Turning READONLY off for a copy-on-write scalar (including shared - hash keys) is a bad idea. */ - if (SvIsCOW(sv)) - sv_force_normal_flags(sv, 0); - SAVEDESTRUCTOR_X(S_restore_magic, INT2PTR(void*, (IV)mgs_ix)); mgs = SSPTR(mgs_ix, MGS*); mgs->mgs_sv = sv; mgs->mgs_magical = SvMAGICAL(sv); - mgs->mgs_readonly = SvREADONLY(sv) != 0; + mgs->mgs_readonly = SvREADONLY(sv); mgs->mgs_ss_ix = PL_savestack_ix; /* points after the saved destructor */ mgs->mgs_bumped = bumped; - SvMAGICAL_off(sv); + SvFLAGS(sv) &= ~flags; SvREADONLY_off(sv); - if (!(SvFLAGS(sv) & (SVf_IOK|SVf_NOK|SVf_POK))) { - /* No public flags are set, so promote any private flags to public. */ - SvFLAGS(sv) |= (SvFLAGS(sv) & (SVp_IOK|SVp_NOK|SVp_POK)) >> PRIVSHIFT; - } } +#define save_magic(a,b) save_magic_flags(a,b,SVs_GMG|SVs_SMG|SVs_RMG) + /* =for apidoc mg_magical @@ -164,46 +159,11 @@ Perl_mg_magical(pTHX_ SV *sv) } } - -/* is this container magic (%ENV, $1 etc), or value magic (pos, taint etc)? */ - -STATIC bool -S_is_container_magic(const MAGIC *mg) -{ - assert(mg); - switch (mg->mg_type) { - case PERL_MAGIC_bm: - case PERL_MAGIC_fm: - case PERL_MAGIC_regex_global: - case PERL_MAGIC_nkeys: -#ifdef USE_LOCALE_COLLATE - case PERL_MAGIC_collxfrm: -#endif - case PERL_MAGIC_qr: - case PERL_MAGIC_taint: - case PERL_MAGIC_vec: - case PERL_MAGIC_vstring: - case PERL_MAGIC_utf8: - case PERL_MAGIC_substr: - case PERL_MAGIC_defelem: - case PERL_MAGIC_arylen: - case PERL_MAGIC_pos: - case PERL_MAGIC_backref: - case PERL_MAGIC_arylen_p: - case PERL_MAGIC_rhash: - case PERL_MAGIC_symtab: - case PERL_MAGIC_tied: /* treat as value, so 'local @tied' isn't tied */ - case PERL_MAGIC_checkcall: - return 0; - default: - return 1; - } -} - /* =for apidoc mg_get -Do magic after a value is retrieved from the SV. See C. +Do magic before a value is retrieved from the SV. The type of SV must +be >= SVt_PVMG. See C. =cut */ @@ -213,12 +173,13 @@ Perl_mg_get(pTHX_ SV *sv) { dVAR; const I32 mgs_ix = SSNEW(sizeof(MGS)); + bool saved = FALSE; bool have_new = 0; MAGIC *newmg, *head, *cur, *mg; PERL_ARGS_ASSERT_MG_GET; - save_magic(mgs_ix, sv); + if (PL_localizing == 1 && sv == DEFSV) return 0; /* We must call svt_get(sv, mg) for each valid entry in the linked list of magic. svt_get() may delete the current entry, add new @@ -230,6 +191,13 @@ Perl_mg_get(pTHX_ SV *sv) MAGIC * const nextmg = mg->mg_moremagic; /* it may delete itself */ if (!(mg->mg_flags & MGf_GSKIP) && vtbl && vtbl->svt_get) { + + /* taint's mg get is so dumb it doesn't need flag saving */ + if (!saved && mg->mg_type != PERL_MAGIC_taint) { + save_magic(mgs_ix, sv); + saved = TRUE; + } + vtbl->svt_get(aTHX_ sv, mg); /* guard against magic having been deleted - eg FETCH calling @@ -243,6 +211,10 @@ Perl_mg_get(pTHX_ SV *sv) if (mg->mg_flags & MGf_GSKIP) (SSPTR(mgs_ix, MGS *))->mgs_magical = 0; } + else if (vtbl == &PL_vtbl_utf8) { + /* get-magic can reallocate the PV */ + magic_setutf8(sv, mg); + } mg = nextmg; @@ -265,7 +237,9 @@ Perl_mg_get(pTHX_ SV *sv) } } - restore_magic(INT2PTR(void *, (IV)mgs_ix)); + if (saved) + restore_magic(INT2PTR(void *, (IV)mgs_ix)); + return 0; } @@ -287,7 +261,9 @@ Perl_mg_set(pTHX_ SV *sv) PERL_ARGS_ASSERT_MG_SET; - save_magic(mgs_ix, sv); + if (PL_localizing == 2 && sv == DEFSV) return 0; + + save_magic_flags(mgs_ix, sv, SVs_GMG|SVs_SMG); /* leave SVs_RMG on */ for (mg = SvMAGIC(sv); mg; mg = nextmg) { const MGVTBL* vtbl = mg->mg_virtual; @@ -296,7 +272,8 @@ Perl_mg_set(pTHX_ SV *sv) mg->mg_flags &= ~MGf_GSKIP; /* setting requires another read */ (SSPTR(mgs_ix, MGS*))->mgs_magical = 0; } - if (PL_localizing == 2 && (!S_is_container_magic(mg) || sv == DEFSV)) + if (PL_localizing == 2 + && PERL_MAGIC_TYPE_IS_VALUE_MAGIC(mg->mg_type)) continue; if (vtbl && vtbl->svt_set) vtbl->svt_set(aTHX_ sv, mg); @@ -309,7 +286,11 @@ Perl_mg_set(pTHX_ SV *sv) /* =for apidoc mg_length -Report on the SV's length. See C. +Reports on the SV's length in bytes, calling length magic if available, +but does not set the UTF8 flag on the sv. It will fall back to 'get' +magic if there is no 'length' magic, but with no indication as to +whether it called 'get' magic. It assumes the sv is a PVMG or +higher. Use sv_len() instead. =cut */ @@ -335,15 +316,7 @@ Perl_mg_length(pTHX_ SV *sv) } } - { - /* You can't know whether it's UTF-8 until you get the string again... - */ - const U8 *s = (U8*)SvPV_const(sv, len); - - if (DO_UTF8(sv)) { - len = utf8_length(s, s + len); - } - } + (void)SvPV_const(sv, len); return len; } @@ -422,6 +395,8 @@ S_mg_findext_flags(pTHX_ const SV *sv, int type, const MGVTBL *vtbl, U32 flags) if (sv) { MAGIC *mg; + assert(!(SvTYPE(sv) == SVt_PVAV && AvPAD_NAMELIST(sv))); + for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) { if (mg->mg_type == type && (!flags || mg->mg_virtual == vtbl)) { return mg; @@ -461,6 +436,21 @@ Perl_mg_findext(pTHX_ const SV *sv, int type, const MGVTBL *vtbl) return S_mg_findext_flags(aTHX_ sv, type, vtbl, 1); } +MAGIC * +Perl_mg_find_mglob(pTHX_ SV *sv) +{ + PERL_ARGS_ASSERT_MG_FIND_MGLOB; + if (SvTYPE(sv) == SVt_PVLV && LvTYPE(sv) == 'y') { + /* This sv is only a delegate. //g magic must be attached to + its target. */ + vivify_defelem(sv); + sv = LvTARG(sv); + } + if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv)) + return S_mg_findext_flags(aTHX_ sv, PERL_MAGIC_regex_global, 0, 0); + return NULL; +} + /* =for apidoc mg_copy @@ -526,7 +516,7 @@ Perl_mg_localize(pTHX_ SV *sv, SV *nsv, bool setmagic) for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) { const MGVTBL* const vtbl = mg->mg_virtual; - if (!S_is_container_magic(mg)) + if (PERL_MAGIC_TYPE_IS_VALUE_MAGIC(mg->mg_type)) continue; if ((mg->mg_flags & MGf_LOCAL) && vtbl->svt_local) @@ -637,7 +627,7 @@ Perl_magic_regdata_cnt(pTHX_ SV *sv, MAGIC *mg) PERL_ARGS_ASSERT_MAGIC_REGDATA_CNT; if (PL_curpm) { - register const REGEXP * const rx = PM_GETRE(PL_curpm); + const REGEXP * const rx = PM_GETRE(PL_curpm); if (rx) { if (mg->mg_obj) { /* @+ */ /* return the number possible */ @@ -658,6 +648,8 @@ Perl_magic_regdata_cnt(pTHX_ SV *sv, MAGIC *mg) return (U32)-1; } +/* @-, @+ */ + int Perl_magic_regdatum_get(pTHX_ SV *sv, MAGIC *mg) { @@ -666,18 +658,18 @@ Perl_magic_regdatum_get(pTHX_ SV *sv, MAGIC *mg) PERL_ARGS_ASSERT_MAGIC_REGDATUM_GET; if (PL_curpm) { - register const REGEXP * const rx = PM_GETRE(PL_curpm); + const REGEXP * const rx = PM_GETRE(PL_curpm); if (rx) { - register const I32 paren = mg->mg_len; - register I32 s; - register I32 t; + const I32 paren = mg->mg_len; + I32 s; + I32 t; if (paren < 0) return 0; if (paren <= (I32)RX_NPARENS(rx) && (s = RX_OFFS(rx)[paren].start) != -1 && (t = RX_OFFS(rx)[paren].end) != -1) { - register I32 i; + I32 i; if (mg->mg_obj) /* @+ */ i = t; else /* @- */ @@ -686,7 +678,9 @@ Perl_magic_regdatum_get(pTHX_ SV *sv, MAGIC *mg) if (i > 0 && RX_MATCH_UTF8(rx)) { const char * const b = RX_SUBBEG(rx); if (b) - i = utf8_length((U8*)b, (U8*)(b+i)); + i = RX_SUBCOFFSET(rx) + + utf8_length((U8*)b, + (U8*)(b-RX_SUBOFFSET(rx)+i)); } sv_setiv(sv, i); @@ -696,95 +690,18 @@ Perl_magic_regdatum_get(pTHX_ SV *sv, MAGIC *mg) return 0; } +/* @-, @+ */ + int Perl_magic_regdatum_set(pTHX_ SV *sv, MAGIC *mg) { PERL_ARGS_ASSERT_MAGIC_REGDATUM_SET; PERL_UNUSED_ARG(sv); PERL_UNUSED_ARG(mg); - Perl_croak_no_modify(aTHX); + Perl_croak_no_modify(); NORETURN_FUNCTION_END; } -U32 -Perl_magic_len(pTHX_ SV *sv, MAGIC *mg) -{ - dVAR; - register I32 paren; - register I32 i; - register const REGEXP * rx; - const char * const remaining = mg->mg_ptr + 1; - - PERL_ARGS_ASSERT_MAGIC_LEN; - - switch (*mg->mg_ptr) { - case '\020': - if (*remaining == '\0') { /* ^P */ - break; - } else if (strEQ(remaining, "REMATCH")) { /* $^PREMATCH */ - goto do_prematch; - } else if (strEQ(remaining, "OSTMATCH")) { /* $^POSTMATCH */ - goto do_postmatch; - } - break; - case '\015': /* $^MATCH */ - if (strEQ(remaining, "ATCH")) { - goto do_match; - } else { - break; - } - case '`': - do_prematch: - paren = RX_BUFF_IDX_PREMATCH; - goto maybegetparen; - case '\'': - do_postmatch: - paren = RX_BUFF_IDX_POSTMATCH; - goto maybegetparen; - case '&': - do_match: - paren = RX_BUFF_IDX_FULLMATCH; - goto maybegetparen; - case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - paren = atoi(mg->mg_ptr); - maybegetparen: - if (PL_curpm && (rx = PM_GETRE(PL_curpm))) { - getparen: - i = CALLREG_NUMBUF_LENGTH((REGEXP * const)rx, sv, paren); - - if (i < 0) - Perl_croak(aTHX_ "panic: magic_len: %"IVdf, (IV)i); - return i; - } else { - if (ckWARN(WARN_UNINITIALIZED)) - report_uninit(sv); - return 0; - } - case '+': - if (PL_curpm && (rx = PM_GETRE(PL_curpm))) { - paren = RX_LASTPAREN(rx); - if (paren) - goto getparen; - } - return 0; - case '\016': /* ^N */ - if (PL_curpm && (rx = PM_GETRE(PL_curpm))) { - paren = RX_LASTCLOSEPAREN(rx); - if (paren) - goto getparen; - } - return 0; - } - magic_get(sv,mg); - if (!SvPOK(sv) && SvNIOK(sv)) { - sv_2pv(sv, 0); - } - if (SvPOK(sv)) - return SvCUR(sv); - return 0; -} - #define SvRTRIM(sv) STMT_START { \ if (SvPOK(sv)) { \ STRLEN len = SvCUR(sv); \ @@ -820,13 +737,18 @@ Perl_emulate_cop_io(pTHX_ const COP *const c, SV *const sv) } } +#ifdef VMS +#include +#include +#endif + int Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) { dVAR; - register I32 paren; - register const char *s = NULL; - register REGEXP *rx; + I32 paren; + const char *s = NULL; + REGEXP *rx; const char * const remaining = mg->mg_ptr + 1; const char nextchar = *remaining; @@ -834,7 +756,8 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) switch (*mg->mg_ptr) { case '\001': /* ^A */ - sv_setsv(sv, PL_bodytarget); + if (SvOK(PL_bodytarget)) sv_copypv(sv, PL_bodytarget); + else sv_setsv(sv, &PL_sv_undef); if (SvTAINTED(PL_bodytarget)) SvTAINTED_on(sv); break; @@ -854,8 +777,6 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) if (nextchar == '\0') { #if defined(VMS) { -# include -# include char msg[255]; $DESCRIPTOR(msgdsc,msg); sv_setnv(sv,(NV) vaxc$errno); @@ -917,6 +838,20 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) case '\011': /* ^I */ /* NOT \t in EBCDIC */ sv_setpv(sv, PL_inplace); /* Will undefine sv if PL_inplace is NULL */ break; + case '\014': /* ^LAST_FH */ + if (strEQ(remaining, "AST_FH")) { + if (PL_last_in_gv) { + assert(isGV_with_GP(PL_last_in_gv)); + SV_CHECK_THINKFIRST_COW_DROP(sv); + prepare_SV_for_RV(sv); + SvOK_off(sv); + SvRV_set(sv, SvREFCNT_inc_simple_NN(PL_last_in_gv)); + SvROK_on(sv); + sv_rvweaken(sv); + } + else sv_setsv_nomg(sv, NULL); + } + break; case '\017': /* ^O & ^OPEN */ if (nextchar == '\0') { sv_setpv(sv, PL_osname); @@ -930,9 +865,12 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) if (nextchar == '\0') { /* ^P */ sv_setiv(sv, (IV)PL_perldb); } else if (strEQ(remaining, "REMATCH")) { /* $^PREMATCH */ - goto do_prematch_fetch; + + paren = RX_BUFF_IDX_CARET_PREMATCH; + goto do_numbuf_fetch; } else if (strEQ(remaining, "OSTMATCH")) { /* $^POSTMATCH */ - goto do_postmatch_fetch; + paren = RX_BUFF_IDX_CARET_POSTMATCH; + goto do_numbuf_fetch; } break; case '\023': /* ^S */ @@ -954,8 +892,8 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) #endif } else if (strEQ(remaining, "AINT")) - sv_setiv(sv, PL_tainting - ? (PL_taint_warn || PL_unsafe ? -1 : 1) + sv_setiv(sv, TAINTING_get + ? (TAINT_WARN_get || PL_unsafe ? -1 : 1) : 0); break; case '\025': /* $^UNICODE, $^UTF8LOCALE, $^UTF8CACHE */ @@ -974,83 +912,67 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) sv_setpvn(sv, WARN_NONEstring, WARNsize) ; } else if (PL_compiling.cop_warnings == pWARN_STD) { - sv_setpvn( - sv, - (PL_dowarn & G_WARN_ON) ? WARN_ALLstring : WARN_NONEstring, - WARNsize - ); + sv_setsv(sv, &PL_sv_undef); + break; } else if (PL_compiling.cop_warnings == pWARN_ALL) { /* Get the bit mask for $warnings::Bits{all}, because * it could have been extended by warnings::register */ - HV * const bits=get_hv("warnings::Bits", 0); - if (bits) { - SV ** const bits_all = hv_fetchs(bits, "all", FALSE); - if (bits_all) - sv_setsv(sv, *bits_all); - } - else { - sv_setpvn(sv, WARN_ALLstring, WARNsize) ; - } + HV * const bits = get_hv("warnings::Bits", 0); + SV ** const bits_all = bits ? hv_fetchs(bits, "all", FALSE) : NULL; + if (bits_all) + sv_copypv(sv, *bits_all); + else + sv_setpvn(sv, WARN_ALLstring, WARNsize); } else { sv_setpvn(sv, (char *) (PL_compiling.cop_warnings + 1), *PL_compiling.cop_warnings); } - SvPOK_only(sv); } break; case '\015': /* $^MATCH */ if (strEQ(remaining, "ATCH")) { + paren = RX_BUFF_IDX_CARET_FULLMATCH; + goto do_numbuf_fetch; + } + case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '&': - if (PL_curpm && (rx = PM_GETRE(PL_curpm))) { - /* - * Pre-threads, this was paren = atoi(GvENAME((const GV *)mg->mg_obj)); - * XXX Does the new way break anything? - */ - paren = atoi(mg->mg_ptr); /* $& is in [0] */ - CALLREG_NUMBUF_FETCH(rx,paren,sv); - break; - } - sv_setsv(sv,&PL_sv_undef); - } + /* + * Pre-threads, this was paren = atoi(GvENAME((const GV *)mg->mg_obj)); + * XXX Does the new way break anything? + */ + paren = atoi(mg->mg_ptr); /* $& is in [0] */ + do_numbuf_fetch: + if (PL_curpm && (rx = PM_GETRE(PL_curpm))) { + CALLREG_NUMBUF_FETCH(rx,paren,sv); + break; + } + sv_setsv(sv,&PL_sv_undef); break; case '+': if (PL_curpm && (rx = PM_GETRE(PL_curpm))) { - if (RX_LASTPAREN(rx)) { - CALLREG_NUMBUF_FETCH(rx,RX_LASTPAREN(rx),sv); - break; - } + paren = RX_LASTPAREN(rx); + if (paren) + goto do_numbuf_fetch; } sv_setsv(sv,&PL_sv_undef); break; case '\016': /* ^N */ if (PL_curpm && (rx = PM_GETRE(PL_curpm))) { - if (RX_LASTCLOSEPAREN(rx)) { - CALLREG_NUMBUF_FETCH(rx,RX_LASTCLOSEPAREN(rx),sv); - break; - } - + paren = RX_LASTCLOSEPAREN(rx); + if (paren) + goto do_numbuf_fetch; } sv_setsv(sv,&PL_sv_undef); break; case '`': - do_prematch_fetch: - if (PL_curpm && (rx = PM_GETRE(PL_curpm))) { - CALLREG_NUMBUF_FETCH(rx,-2,sv); - break; - } - sv_setsv(sv,&PL_sv_undef); - break; + paren = RX_BUFF_IDX_PREMATCH; + goto do_numbuf_fetch; case '\'': - do_postmatch_fetch: - if (PL_curpm && (rx = PM_GETRE(PL_curpm))) { - CALLREG_NUMBUF_FETCH(rx,-1,sv); - break; - } - sv_setsv(sv,&PL_sv_undef); - break; + paren = RX_BUFF_IDX_POSTMATCH; + goto do_numbuf_fetch; case '.': if (GvIO(PL_last_in_gv)) { sv_setiv(sv, (IV)IoLINES(GvIOp(PL_last_in_gv))); @@ -1067,9 +989,7 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) } break; case '^': - if (!isGV_with_GP(PL_defoutgv)) - s = ""; - else if (GvIOp(PL_defoutgv)) + if (GvIOp(PL_defoutgv)) s = IoTOP_NAME(GvIOp(PL_defoutgv)); if (s) sv_setpv(sv,s); @@ -1079,9 +999,7 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) } break; case '~': - if (!isGV_with_GP(PL_defoutgv)) - s = ""; - else if (GvIOp(PL_defoutgv)) + if (GvIOp(PL_defoutgv)) s = IoFMT_NAME(GvIOp(PL_defoutgv)); if (!s) s = GvENAME(PL_defoutgv); @@ -1104,7 +1022,7 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) case '/': break; case '[': - sv_setiv(sv, (IV)CopARYBASE_get(PL_curcop)); + sv_setiv(sv, 0); break; case '|': if (GvIO(PL_defoutgv)) @@ -1113,9 +1031,20 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) case '\\': if (PL_ors_sv) sv_copypv(sv, PL_ors_sv); + else + sv_setsv(sv, &PL_sv_undef); break; case '$': /* $$ */ - sv_setiv(sv, (IV)PerlProc_getpid()); + { + IV const pid = (IV)PerlProc_getpid(); + if (isGV(mg->mg_obj) || SvIV(mg->mg_obj) != pid) { + /* never set manually, or at least not since last fork */ + sv_setiv(sv, pid); + /* never unsafe, even if reading in a tainted expression */ + SvTAINTED_off(sv); + } + /* else a value has been assigned manually, so do nothing */ + } break; case '!': @@ -1131,9 +1060,35 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) sv_setpv(sv, os2error(Perl_rc)); else #endif - sv_setpv(sv, errno ? Strerror(errno) : ""); - if (SvPOKp(sv)) - SvPOK_on(sv); /* may have got removed during taint processing */ + if (! errno) { + sv_setpvs(sv, ""); + } + else { + + /* Strerror can return NULL on some platforms, which will result in + * 'sv' not being considered SvOK. The SvNOK_on() below will cause + * just the number part to be valid */ + sv_setpv(sv, Strerror(errno)); + + /* In some locales the error string may come back as UTF-8, in + * which case we should turn on that flag. This didn't use to + * happen, and to avoid any possible backward compatibility issues, + * we don't turn on the flag unless we have to. So the flag stays + * off for an entirely ASCII string. We assume that if the string + * looks like UTF-8, it really is UTF-8: "text in any other + * encoding that uses bytes with the high bit set is extremely + * unlikely to pass a UTF-8 validity test" + * (http://en.wikipedia.org/wiki/Charset_detection). There is a + * potential that we will get it wrong however, especially on short + * error message text. (If it turns out to be necessary, we could + * also keep track if the current LC_MESSAGES locale is UTF-8) */ + if (SvOK(sv) /* It could be that Strerror returned invalid */ + && ! is_ascii_string((U8*) SvPVX_const(sv), SvCUR(sv)) + && is_utf8_string((U8*) SvPVX_const(sv), SvCUR(sv))) + { + SvUTF8_on(sv); + } + } RESTORE_ERRNO; } @@ -1141,16 +1096,16 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) SvNOK_on(sv); /* what a wonderful hack! */ break; case '<': - sv_setiv(sv, (IV)PL_uid); + sv_setuid(sv, PerlProc_getuid()); break; case '>': - sv_setiv(sv, (IV)PL_euid); + sv_setuid(sv, PerlProc_geteuid()); break; case '(': - sv_setiv(sv, (IV)PL_gid); + sv_setgid(sv, PerlProc_getgid()); goto add_groups; case ')': - sv_setiv(sv, (IV)PL_egid); + sv_setgid(sv, PerlProc_getegid()); add_groups: #ifdef HAS_GETGROUPS { @@ -1188,17 +1143,31 @@ Perl_magic_setenv(pTHX_ SV *sv, MAGIC *mg) { dVAR; STRLEN len = 0, klen; - const char *s = SvOK(sv) ? SvPV_const(sv,len) : ""; - const char * const ptr = MgPV_const(mg,klen); - my_setenv(ptr, s); + const char * const key = MgPV_const(mg,klen); + const char *s = ""; PERL_ARGS_ASSERT_MAGIC_SETENV; + SvGETMAGIC(sv); + if (SvOK(sv)) { + /* defined environment variables are byte strings; unfortunately + there is no SvPVbyte_force_nomg(), so we must do this piecewise */ + (void)SvPV_force_nomg_nolen(sv); + sv_utf8_downgrade(sv, /* fail_ok */ TRUE); + if (SvUTF8(sv)) { + Perl_ck_warner_d(aTHX_ packWARN(WARN_UTF8), "Wide character in %s", "setenv"); + SvUTF8_off(sv); + } + s = SvPVX(sv); + len = SvCUR(sv); + } + my_setenv(key, s); /* does the deed */ + #ifdef DYNAMIC_ENV_FETCH /* We just undefd an environment var. Is a replacement */ /* waiting in the wings? */ if (!len) { - SV ** const valp = hv_fetch(GvHVn(PL_envgv), ptr, klen, FALSE); + SV ** const valp = hv_fetch(GvHVn(PL_envgv), key, klen, FALSE); if (valp) s = SvOK(*valp) ? SvPV_const(*valp, len) : ""; } @@ -1207,10 +1176,10 @@ Perl_magic_setenv(pTHX_ SV *sv, MAGIC *mg) #if !defined(OS2) && !defined(AMIGAOS) && !defined(WIN32) && !defined(MSDOS) /* And you'll never guess what the dog had */ /* in its mouth... */ - if (PL_tainting) { + if (TAINTING_get) { MgTAINTEDDIR_off(mg); #ifdef VMS - if (s && klen == 8 && strEQ(ptr, "DCL$PATH")) { + if (s && klen == 8 && strEQ(key, "DCL$PATH")) { char pathbuf[256], eltbuf[256], *cp, *elt; int i = 0, j = 0; @@ -1236,7 +1205,7 @@ Perl_magic_setenv(pTHX_ SV *sv, MAGIC *mg) } while (my_trnlnm(s, pathbuf, i++) && (elt = pathbuf)); } #endif /* VMS */ - if (s && klen == 4 && strEQ(ptr,"PATH")) { + if (s && klen == 4 && strEQ(key,"PATH")) { const char * const strend = s + len; while (s < strend) { @@ -1335,7 +1304,9 @@ Perl_magic_getsig(pTHX_ SV *sv, MAGIC *mg) PERL_ARGS_ASSERT_MAGIC_GETSIG; if (!i) { - mg->mg_private = i = whichsig(MgPV_nolen_const(mg)); + STRLEN siglen; + const char * sig = MgPV_const(mg, siglen); + mg->mg_private = i = whichsig_pvn(sig, siglen); } if (i > 0) { @@ -1521,14 +1492,14 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg) sigset_t set, save; SV* save_sv; #endif - register const char *s = MgPV_const(mg,len); + const char *s = MgPV_const(mg,len); PERL_ARGS_ASSERT_MAGIC_SETSIG; if (*s == '_') { - if (strEQ(s,"__DIE__")) + if (memEQs(s, len, "__DIE__")) svp = &PL_diehook; - else if (strEQ(s,"__WARN__") + else if (memEQs(s, len, "__WARN__") && (sv ? 1 : PL_warnhook != PERL_WARNHOOK_FATAL)) { /* Merge the existing behaviours, which are as follows: magic_setsig, we always set svp to &PL_warnhook @@ -1536,8 +1507,11 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg) For magic_clearsig, we don't change the warnings handler if it's set to the &PL_warnhook. */ svp = &PL_warnhook; - } else if (sv) - Perl_croak(aTHX_ "No such hook: %s", s); + } else if (sv) { + SV *tmp = sv_newmortal(); + Perl_croak(aTHX_ "No such hook: %s", + pv_pretty(tmp, s, len, 0, NULL, NULL, 0)); + } i = 0; if (svp && *svp) { if (*svp != PERL_WARNHOOK_FATAL) @@ -1548,12 +1522,15 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg) else { i = (I16)mg->mg_private; if (!i) { - i = whichsig(s); /* ...no, a brick */ + i = whichsig_pvn(s, len); /* ...no, a brick */ mg->mg_private = (U16)i; } if (i <= 0) { - if (sv) - Perl_ck_warner(aTHX_ packWARN(WARN_SIGNAL), "No such signal: SIG%s", s); + if (sv) { + SV *tmp = sv_newmortal(); + Perl_ck_warner(aTHX_ packWARN(WARN_SIGNAL), "No such signal: SIG%s", + pv_pretty(tmp, s, len, 0, NULL, NULL, 0)); + } return 0; } #ifdef HAS_SIGPROCMASK @@ -1609,7 +1586,7 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg) } else { sv = NULL; } - if (sv && strEQ(s,"IGNORE")) { + if (sv && memEQs(s, len,"IGNORE")) { if (i) { #ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS PL_sig_ignoring[i] = 1; @@ -1619,7 +1596,7 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg) #endif } } - else if (!sv || strEQ(s,"DEFAULT") || !len) { + else if (!sv || memEQs(s, len,"DEFAULT") || !len) { if (i) { #ifdef FAKE_DEFAULT_SIGNAL_HANDLERS PL_sig_defaulting[i] = 1; @@ -1712,18 +1689,6 @@ Perl_magic_clearisa(pTHX_ SV *sv, MAGIC *mg) } int -Perl_magic_setamagic(pTHX_ SV *sv, MAGIC *mg) -{ - dVAR; - PERL_ARGS_ASSERT_MAGIC_SETAMAGIC; - PERL_UNUSED_ARG(sv); - PERL_UNUSED_ARG(mg); - PL_amagic_generation++; - - return 0; -} - -int Perl_magic_getnkeys(pTHX_ SV *sv, MAGIC *mg) { HV * const hv = MUTABLE_HV(LvTARG(sv)); @@ -1762,13 +1727,20 @@ Perl_magic_setnkeys(pTHX_ SV *sv, MAGIC *mg) Invoke a magic method (like FETCH). -* sv and mg are the tied thingy and the tie magic; -* meth is the name of the method to call; -* argc is the number of args (in addition to $self) to pass to the method; - the args themselves are any values following the argc argument. -* flags: - G_DISCARD: invoke method with G_DISCARD flag and don't return a value - G_UNDEF_FILL: fill the stack with argc pointers to PL_sv_undef. +C and C are the tied thingy and the tie magic. + +C is the name of the method to call. + +C is the number of args (in addition to $self) to pass to the method. + +The C can be: + + G_DISCARD invoke method with G_DISCARD flag and don't + return a value + G_UNDEF_FILL fill the stack with argc pointers to + PL_sv_undef + +The arguments themselves are any values following the C argument. Returns the SV (if any) returned by the method, or NULL on failure. @@ -1777,7 +1749,7 @@ Returns the SV (if any) returned by the method, or NULL on failure. */ SV* -Perl_magic_methcall(pTHX_ SV *sv, const MAGIC *mg, const char *meth, U32 flags, +Perl_magic_methcall(pTHX_ SV *sv, const MAGIC *mg, SV *meth, U32 flags, U32 argc, ...) { dVAR; @@ -1818,10 +1790,10 @@ Perl_magic_methcall(pTHX_ SV *sv, const MAGIC *mg, const char *meth, U32 flags, } PUTBACK; if (flags & G_DISCARD) { - call_method(meth, G_SCALAR|G_DISCARD); + call_sv(meth, G_SCALAR|G_DISCARD|G_METHOD_NAMED); } else { - if (call_method(meth, G_SCALAR)) + if (call_sv(meth, G_SCALAR|G_METHOD_NAMED)) ret = *PL_stack_sp--; } POPSTACK; @@ -1831,11 +1803,10 @@ Perl_magic_methcall(pTHX_ SV *sv, const MAGIC *mg, const char *meth, U32 flags, return ret; } - /* wrapper for magic_methcall that creates the first arg */ STATIC SV* -S_magic_methcall1(pTHX_ SV *sv, const MAGIC *mg, const char *meth, U32 flags, +S_magic_methcall1(pTHX_ SV *sv, const MAGIC *mg, SV *meth, U32 flags, int n, SV *val) { dVAR; @@ -1861,7 +1832,7 @@ S_magic_methcall1(pTHX_ SV *sv, const MAGIC *mg, const char *meth, U32 flags, } STATIC int -S_magic_methpack(pTHX_ SV *sv, const MAGIC *mg, const char *meth) +S_magic_methpack(pTHX_ SV *sv, const MAGIC *mg, SV *meth) { dVAR; SV* ret; @@ -1881,7 +1852,7 @@ Perl_magic_getpack(pTHX_ SV *sv, MAGIC *mg) if (mg->mg_type == PERL_MAGIC_tiedelem) mg->mg_flags |= MGf_GSKIP; - magic_methpack(sv,mg,"FETCH"); + magic_methpack(sv,mg,SV_CONST(FETCH)); return 0; } @@ -1904,7 +1875,7 @@ Perl_magic_setpack(pTHX_ SV *sv, MAGIC *mg) * fake up a temporary tainted value (this is easier than temporarily * re-enabling magic on sv). */ - if (PL_tainting && (tmg = mg_find(sv, PERL_MAGIC_taint)) + if (TAINTING_get && (tmg = mg_find(sv, PERL_MAGIC_taint)) && (tmg->mg_len & 1)) { val = sv_mortalcopy(sv); @@ -1913,7 +1884,7 @@ Perl_magic_setpack(pTHX_ SV *sv, MAGIC *mg) else val = sv; - magic_methcall1(sv, mg, "STORE", G_DISCARD, 2, val); + magic_methcall1(sv, mg, SV_CONST(STORE), G_DISCARD, 2, val); return 0; } @@ -1922,7 +1893,8 @@ Perl_magic_clearpack(pTHX_ SV *sv, MAGIC *mg) { PERL_ARGS_ASSERT_MAGIC_CLEARPACK; - return magic_methpack(sv,mg,"DELETE"); + if (mg->mg_type == PERL_MAGIC_tiedscalar) return 0; + return magic_methpack(sv,mg,SV_CONST(DELETE)); } @@ -1935,7 +1907,7 @@ Perl_magic_sizepack(pTHX_ SV *sv, MAGIC *mg) PERL_ARGS_ASSERT_MAGIC_SIZEPACK; - retsv = magic_methcall1(sv, mg, "FETCHSIZE", 0, 1, NULL); + retsv = magic_methcall1(sv, mg, SV_CONST(FETCHSIZE), 0, 1, NULL); if (retsv) { retval = SvIV(retsv)-1; if (retval < -1) @@ -1951,7 +1923,7 @@ Perl_magic_wipepack(pTHX_ SV *sv, MAGIC *mg) PERL_ARGS_ASSERT_MAGIC_WIPEPACK; - Perl_magic_methcall(aTHX_ sv, mg, "CLEAR", G_DISCARD, 0); + Perl_magic_methcall(aTHX_ sv, mg, SV_CONST(CLEAR), G_DISCARD, 0); return 0; } @@ -1963,8 +1935,8 @@ Perl_magic_nextpack(pTHX_ SV *sv, MAGIC *mg, SV *key) PERL_ARGS_ASSERT_MAGIC_NEXTPACK; - ret = SvOK(key) ? Perl_magic_methcall(aTHX_ sv, mg, "NEXTKEY", 0, 1, key) - : Perl_magic_methcall(aTHX_ sv, mg, "FIRSTKEY", 0, 0); + ret = SvOK(key) ? Perl_magic_methcall(aTHX_ sv, mg, SV_CONST(NEXTKEY), 0, 1, key) + : Perl_magic_methcall(aTHX_ sv, mg, SV_CONST(FIRSTKEY), 0, 0); if (ret) sv_setsv(key,ret); return 0; @@ -1975,7 +1947,7 @@ Perl_magic_existspack(pTHX_ SV *sv, const MAGIC *mg) { PERL_ARGS_ASSERT_MAGIC_EXISTSPACK; - return magic_methpack(sv,mg,"EXISTS"); + return magic_methpack(sv,mg,SV_CONST(EXISTS)); } SV * @@ -2001,7 +1973,7 @@ Perl_magic_scalarpack(pTHX_ HV *hv, MAGIC *mg) } /* there is a SCALAR method that we can call */ - retval = Perl_magic_methcall(aTHX_ MUTABLE_SV(hv), mg, "SCALAR", 0, 0); + retval = Perl_magic_methcall(aTHX_ MUTABLE_SV(hv), mg, SV_CONST(SCALAR), 0, 0); if (!retval) retval = &PL_sv_undef; return retval; @@ -2021,11 +1993,17 @@ Perl_magic_setdbline(pTHX_ SV *sv, MAGIC *mg) if (svp && SvIOKp(*svp)) { OP * const o = INT2PTR(OP*,SvIVX(*svp)); if (o) { +#ifdef PERL_DEBUG_READONLY_OPS + Slab_to_rw(OpSLAB(o)); +#endif /* set or clear breakpoint in the relevant control op */ if (i) o->op_flags |= OPf_SPECIAL; else o->op_flags &= ~OPf_SPECIAL; +#ifdef PERL_DEBUG_READONLY_OPS + Slab_to_ro(OpSLAB(o)); +#endif } } return 0; @@ -2040,7 +2018,7 @@ Perl_magic_getarylen(pTHX_ SV *sv, const MAGIC *mg) PERL_ARGS_ASSERT_MAGIC_GETARYLEN; if (obj) { - sv_setiv(sv, AvFILL(obj) + CopARYBASE_get(PL_curcop)); + sv_setiv(sv, AvFILL(obj)); } else { SvOK_off(sv); } @@ -2056,7 +2034,7 @@ Perl_magic_setarylen(pTHX_ SV *sv, MAGIC *mg) PERL_ARGS_ASSERT_MAGIC_SETARYLEN; if (obj) { - av_fill(obj, SvIV(sv) - CopARYBASE_get(PL_curcop)); + av_fill(obj, SvIV(sv)); } else { Perl_ck_warner(aTHX_ packWARN(WARN_MISC), "Attempt to set length of freed array"); @@ -2065,6 +2043,25 @@ Perl_magic_setarylen(pTHX_ SV *sv, MAGIC *mg) } int +Perl_magic_cleararylen_p(pTHX_ SV *sv, MAGIC *mg) +{ + dVAR; + + PERL_ARGS_ASSERT_MAGIC_CLEARARYLEN_P; + PERL_UNUSED_ARG(sv); + + /* Reset the iterator when the array is cleared */ +#if IVSIZE == I32SIZE + *((IV *) &(mg->mg_len)) = 0; +#else + if (mg->mg_ptr) + *((IV *) mg->mg_ptr) = 0; +#endif + + return 0; +} + +int Perl_magic_freearylen_p(pTHX_ SV *sv, MAGIC *mg) { dVAR; @@ -2094,19 +2091,17 @@ Perl_magic_getpos(pTHX_ SV *sv, MAGIC *mg) { dVAR; SV* const lsv = LvTARG(sv); + MAGIC * const found = mg_find_mglob(lsv); PERL_ARGS_ASSERT_MAGIC_GETPOS; PERL_UNUSED_ARG(mg); - if (SvTYPE(lsv) >= SVt_PVMG && SvMAGIC(lsv)) { - MAGIC * const found = mg_find(lsv, PERL_MAGIC_regex_global); - if (found && found->mg_len >= 0) { - I32 i = found->mg_len; + if (found && found->mg_len != -1) { + STRLEN i = found->mg_len; if (DO_UTF8(lsv)) - sv_pos_b2u(lsv, &i); - sv_setiv(sv, i + CopARYBASE_get(PL_curcop)); + i = sv_pos_b2u_flags(lsv, i, SV_GMAGIC|SV_CONST_RETURN); + sv_setuv(sv, i); return 0; - } } SvOK_off(sv); return 0; @@ -2121,34 +2116,27 @@ Perl_magic_setpos(pTHX_ SV *sv, MAGIC *mg) STRLEN len; STRLEN ulen = 0; MAGIC* found; + const char *s; PERL_ARGS_ASSERT_MAGIC_SETPOS; PERL_UNUSED_ARG(mg); - if (SvTYPE(lsv) >= SVt_PVMG && SvMAGIC(lsv)) - found = mg_find(lsv, PERL_MAGIC_regex_global); - else - found = NULL; + found = mg_find_mglob(lsv); if (!found) { if (!SvOK(sv)) return 0; -#ifdef PERL_OLD_COPY_ON_WRITE - if (SvIsCOW(lsv)) - sv_force_normal_flags(lsv, 0); -#endif - found = sv_magicext(lsv, NULL, PERL_MAGIC_regex_global, &PL_vtbl_mglob, - NULL, 0); + found = sv_magicext_mglob(lsv); } else if (!SvOK(sv)) { found->mg_len = -1; return 0; } - len = SvPOK(lsv) ? SvCUR(lsv) : sv_len(lsv); + s = SvPV_const(lsv, len); - pos = SvIV(sv) - CopARYBASE_get(PL_curcop); + pos = SvIV(sv); if (DO_UTF8(lsv)) { - ulen = sv_len_utf8(lsv); + ulen = sv_or_pv_len_utf8(lsv, s, len); if (ulen) len = ulen; } @@ -2162,9 +2150,7 @@ Perl_magic_setpos(pTHX_ SV *sv, MAGIC *mg) pos = len; if (ulen) { - I32 p = pos; - sv_pos_u2b(lsv, &p, 0); - pos = p; + pos = sv_or_pv_pos_u2b(lsv, s, pos, 0); } found->mg_len = pos; @@ -2181,16 +2167,24 @@ Perl_magic_getsubstr(pTHX_ SV *sv, MAGIC *mg) const char * const tmps = SvPV_const(lsv,len); STRLEN offs = LvTARGOFF(sv); STRLEN rem = LvTARGLEN(sv); + const bool negoff = LvFLAGS(sv) & 1; + const bool negrem = LvFLAGS(sv) & 2; PERL_ARGS_ASSERT_MAGIC_GETSUBSTR; PERL_UNUSED_ARG(mg); + if (!translate_substr_offsets( + SvUTF8(lsv) ? sv_or_pv_len_utf8(lsv, tmps, len) : len, + negoff ? -(IV)offs : (IV)offs, !negoff, + negrem ? -(IV)rem : (IV)rem, !negrem, &offs, &rem + )) { + Perl_ck_warner(aTHX_ packWARN(WARN_SUBSTR), "substr outside of string"); + sv_setsv_nomg(sv, &PL_sv_undef); + return 0; + } + if (SvUTF8(lsv)) - offs = sv_pos_u2b_flags(lsv, offs, &rem, SV_CONST_RETURN); - if (offs > len) - offs = len; - if (rem > len - offs) - rem = len - offs; + offs = sv_or_pv_pos_u2b(lsv, tmps, offs, &rem); sv_setpvn(sv, tmps + offs, rem); if (SvUTF8(lsv)) SvUTF8_on(sv); @@ -2201,34 +2195,52 @@ int Perl_magic_setsubstr(pTHX_ SV *sv, MAGIC *mg) { dVAR; - STRLEN len; + STRLEN len, lsv_len, oldtarglen, newtarglen; const char * const tmps = SvPV_const(sv, len); SV * const lsv = LvTARG(sv); STRLEN lvoff = LvTARGOFF(sv); STRLEN lvlen = LvTARGLEN(sv); + const bool negoff = LvFLAGS(sv) & 1; + const bool neglen = LvFLAGS(sv) & 2; PERL_ARGS_ASSERT_MAGIC_SETSUBSTR; PERL_UNUSED_ARG(mg); + SvGETMAGIC(lsv); + if (SvROK(lsv)) + Perl_ck_warner(aTHX_ packWARN(WARN_SUBSTR), + "Attempt to use reference as lvalue in substr" + ); + SvPV_force_nomg(lsv,lsv_len); + if (SvUTF8(lsv)) lsv_len = sv_len_utf8_nomg(lsv); + if (!translate_substr_offsets( + lsv_len, + negoff ? -(IV)lvoff : (IV)lvoff, !negoff, + neglen ? -(IV)lvlen : (IV)lvlen, !neglen, &lvoff, &lvlen + )) + Perl_croak(aTHX_ "substr outside of string"); + oldtarglen = lvlen; if (DO_UTF8(sv)) { - sv_utf8_upgrade(lsv); + sv_utf8_upgrade_nomg(lsv); lvoff = sv_pos_u2b_flags(lsv, lvoff, &lvlen, SV_CONST_RETURN); - sv_insert(lsv, lvoff, lvlen, tmps, len); - LvTARGLEN(sv) = sv_len_utf8(sv); + sv_insert_flags(lsv, lvoff, lvlen, tmps, len, 0); + newtarglen = sv_or_pv_len_utf8(sv, tmps, len); SvUTF8_on(lsv); } - else if (lsv && SvUTF8(lsv)) { + else if (SvUTF8(lsv)) { const char *utf8; lvoff = sv_pos_u2b_flags(lsv, lvoff, &lvlen, SV_CONST_RETURN); - LvTARGLEN(sv) = len; + newtarglen = len; utf8 = (char*)bytes_to_utf8((U8*)tmps, &len); - sv_insert(lsv, lvoff, lvlen, utf8, len); + sv_insert_flags(lsv, lvoff, lvlen, utf8, len, 0); Safefree(utf8); } else { - sv_insert(lsv, lvoff, lvlen, tmps, len); - LvTARGLEN(sv) = len; + sv_insert_flags(lsv, lvoff, lvlen, tmps, len, 0); + newtarglen = len; } + if (!neglen) LvTARGLEN(sv) = newtarglen; + if (negoff) LvTARGOFF(sv) += newtarglen - oldtarglen; return 0; } @@ -2240,6 +2252,9 @@ Perl_magic_gettaint(pTHX_ SV *sv, MAGIC *mg) PERL_ARGS_ASSERT_MAGIC_GETTAINT; PERL_UNUSED_ARG(sv); +#ifdef NO_TAINT_SUPPORT + PERL_UNUSED_ARG(mg); +#endif TAINT_IF((PL_localizing != 1) && (mg->mg_len & 1)); return 0; @@ -2254,7 +2269,7 @@ Perl_magic_settaint(pTHX_ SV *sv, MAGIC *mg) PERL_UNUSED_ARG(sv); /* update taint status */ - if (PL_tainted) + if (TAINT_get) mg->mg_len |= 1; else mg->mg_len &= ~1; @@ -2286,14 +2301,14 @@ Perl_magic_setvec(pTHX_ SV *sv, MAGIC *mg) return 0; } -int -Perl_magic_getdefelem(pTHX_ SV *sv, MAGIC *mg) +SV * +Perl_defelem_target(pTHX_ SV *sv, MAGIC *mg) { dVAR; SV *targ = NULL; - - PERL_ARGS_ASSERT_MAGIC_GETDEFELEM; - + PERL_ARGS_ASSERT_DEFELEM_TARGET; + if (!mg) mg = mg_find(sv, PERL_MAGIC_defelem); + assert(mg); if (LvTARGLEN(sv)) { if (mg->mg_obj) { SV * const ahv = LvTARG(sv); @@ -2315,10 +2330,18 @@ Perl_magic_getdefelem(pTHX_ SV *sv, MAGIC *mg) mg->mg_obj = NULL; mg->mg_flags &= ~MGf_REFCOUNTED; } + return targ; } else - targ = LvTARG(sv); - sv_setsv(sv, targ ? targ : &PL_sv_undef); + return LvTARG(sv); +} + +int +Perl_magic_getdefelem(pTHX_ SV *sv, MAGIC *mg) +{ + PERL_ARGS_ASSERT_MAGIC_GETDEFELEM; + + sv_setsv(sv, defelem_target(sv, mg)); return 0; } @@ -2387,9 +2410,8 @@ Perl_magic_setmglob(pTHX_ SV *sv, MAGIC *mg) { PERL_ARGS_ASSERT_MAGIC_SETMGLOB; PERL_UNUSED_CONTEXT; + PERL_UNUSED_ARG(sv); mg->mg_len = -1; - if (!isGV_with_GP(sv)) - SvSCREAM_off(sv); return 0; } @@ -2460,9 +2482,9 @@ int Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) { dVAR; - register const char *s; - register I32 paren; - register const REGEXP * rx; + const char *s; + I32 paren; + const REGEXP * rx; const char * const remaining = mg->mg_ptr + 1; I32 i; STRLEN len; @@ -2491,20 +2513,31 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) paren = atoi(mg->mg_ptr); setparen: if (PL_curpm && (rx = PM_GETRE(PL_curpm))) { + setparen_got_rx: CALLREG_NUMBUF_STORE((REGEXP * const)rx,paren,sv); } else { /* Croak with a READONLY error when a numbered match var is * set without a previous pattern match. Unless it's C */ + croakparen: if (!PL_localizing) { - Perl_croak_no_modify(aTHX); + Perl_croak_no_modify(); } } break; case '\001': /* ^A */ - sv_setsv(PL_bodytarget, sv); + if (SvOK(sv)) sv_copypv(PL_bodytarget, sv); + else SvOK_off(PL_bodytarget); + FmLINES(PL_bodytarget) = 0; + if (SvPOK(PL_bodytarget)) { + char *s = SvPVX(PL_bodytarget); + while ( ((s = strchr(s, '\n'))) ) { + FmLINES(PL_bodytarget)++; + s++; + } + } /* mg_set() has temporarily made sv non-magical */ - if (PL_tainting) { + if (TAINTING_get) { if ((tmg = mg_find(sv,PERL_MAGIC_taint)) && tmg->mg_len & 1) SvTAINTED_on(PL_bodytarget); else @@ -2562,6 +2595,10 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) Safefree(PL_inplace); PL_inplace = SvOK(sv) ? savesvpv(sv) : NULL; break; + case '\016': /* ^N */ + if (PL_curpm && (rx = PM_GETRE(PL_curpm)) + && (paren = RX_LASTCLOSEPAREN(rx))) goto setparen_got_rx; + goto croakparen; case '\017': /* ^O */ if (*(mg->mg_ptr+1) == '\0') { Safefree(PL_osname); @@ -2629,9 +2666,8 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) } else if (strEQ(mg->mg_ptr+1, "ARNING_BITS")) { if ( ! (PL_dowarn & G_WARN_ALL_MASK)) { - if (!SvPOK(sv) && PL_localizing) { - sv_setpvn(sv, WARN_NONEstring, WARNsize); - PL_compiling.cop_warnings = pWARN_NONE; + if (!SvPOK(sv)) { + PL_compiling.cop_warnings = pWARN_STD; break; } { @@ -2649,8 +2685,11 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) PL_compiling.cop_warnings = pWARN_NONE; } /* Yuck. I can't see how to abstract this: */ - else if (isWARN_on(((STRLEN *)SvPV_nolen_const(sv)) - 1, - WARN_ALL) && !any_fatals) { + else if (isWARN_on( + ((STRLEN *)SvPV_nolen_const(sv)) - 1, + WARN_ALL) + && !any_fatals) + { if (!specialWARN(PL_compiling.cop_warnings)) PerlMemShared_free(PL_compiling.cop_warnings); PL_compiling.cop_warnings = pWARN_ALL; @@ -2681,33 +2720,25 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) IoLINES(GvIOp(PL_last_in_gv)) = SvIV(sv); break; case '^': - if (isGV_with_GP(PL_defoutgv)) { - Safefree(IoTOP_NAME(GvIOp(PL_defoutgv))); - s = IoTOP_NAME(GvIOp(PL_defoutgv)) = savesvpv(sv); - IoTOP_GV(GvIOp(PL_defoutgv)) = gv_fetchsv(sv, GV_ADD, SVt_PVIO); - } + Safefree(IoTOP_NAME(GvIOp(PL_defoutgv))); + s = IoTOP_NAME(GvIOp(PL_defoutgv)) = savesvpv(sv); + IoTOP_GV(GvIOp(PL_defoutgv)) = gv_fetchsv(sv, GV_ADD, SVt_PVIO); break; case '~': - if (isGV_with_GP(PL_defoutgv)) { - Safefree(IoFMT_NAME(GvIOp(PL_defoutgv))); - s = IoFMT_NAME(GvIOp(PL_defoutgv)) = savesvpv(sv); - IoFMT_GV(GvIOp(PL_defoutgv)) = gv_fetchsv(sv, GV_ADD, SVt_PVIO); - } + Safefree(IoFMT_NAME(GvIOp(PL_defoutgv))); + s = IoFMT_NAME(GvIOp(PL_defoutgv)) = savesvpv(sv); + IoFMT_GV(GvIOp(PL_defoutgv)) = gv_fetchsv(sv, GV_ADD, SVt_PVIO); break; case '=': - if (isGV_with_GP(PL_defoutgv)) - IoPAGE_LEN(GvIOp(PL_defoutgv)) = (SvIV(sv)); + IoPAGE_LEN(GvIOp(PL_defoutgv)) = (SvIV(sv)); break; case '-': - if (isGV_with_GP(PL_defoutgv)) { - IoLINES_LEFT(GvIOp(PL_defoutgv)) = (SvIV(sv)); - if (IoLINES_LEFT(GvIOp(PL_defoutgv)) < 0L) + IoLINES_LEFT(GvIOp(PL_defoutgv)) = (SvIV(sv)); + if (IoLINES_LEFT(GvIOp(PL_defoutgv)) < 0L) IoLINES_LEFT(GvIOp(PL_defoutgv)) = 0L; - } break; case '%': - if (isGV_with_GP(PL_defoutgv)) - IoPAGE(GvIOp(PL_defoutgv)) = (SvIV(sv)); + IoPAGE(GvIOp(PL_defoutgv)) = (SvIV(sv)); break; case '|': { @@ -2732,7 +2763,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) break; case '\\': SvREFCNT_dec(PL_ors_sv); - if (SvOK(sv) || SvGMAGICAL(sv)) { + if (SvOK(sv)) { PL_ors_sv = newSVsv(sv); } else { @@ -2740,7 +2771,8 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) } break; case '[': - CopARYBASE_set(&PL_compiling, SvIV(sv)); + if (SvIV(sv) != 0) + Perl_croak(aTHX_ "Assigning non-zero to $[ is no longer possible"); break; case '?': #ifdef COMPLEX_STATUS @@ -2770,89 +2802,94 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) } break; case '<': - PL_uid = SvIV(sv); + { + const Uid_t new_uid = SvUID(sv); + PL_delaymagic_uid = new_uid; if (PL_delaymagic) { PL_delaymagic |= DM_RUID; break; /* don't do magic till later */ } #ifdef HAS_SETRUID - (void)setruid((Uid_t)PL_uid); + (void)setruid(new_uid); #else #ifdef HAS_SETREUID - (void)setreuid((Uid_t)PL_uid, (Uid_t)-1); + (void)setreuid(new_uid, (Uid_t)-1); #else #ifdef HAS_SETRESUID - (void)setresuid((Uid_t)PL_uid, (Uid_t)-1, (Uid_t)-1); + (void)setresuid(new_uid, (Uid_t)-1, (Uid_t)-1); #else - if (PL_uid == PL_euid) { /* special case $< = $> */ + if (new_uid == PerlProc_geteuid()) { /* special case $< = $> */ #ifdef PERL_DARWIN /* workaround for Darwin's setuid peculiarity, cf [perl #24122] */ - if (PL_uid != 0 && PerlProc_getuid() == 0) + if (new_uid != 0 && PerlProc_getuid() == 0) (void)PerlProc_setuid(0); #endif - (void)PerlProc_setuid(PL_uid); + (void)PerlProc_setuid(new_uid); } else { - PL_uid = PerlProc_getuid(); Perl_croak(aTHX_ "setruid() not implemented"); } #endif #endif #endif - PL_uid = PerlProc_getuid(); break; + } case '>': - PL_euid = SvIV(sv); + { + const Uid_t new_euid = SvUID(sv); + PL_delaymagic_euid = new_euid; if (PL_delaymagic) { PL_delaymagic |= DM_EUID; break; /* don't do magic till later */ } #ifdef HAS_SETEUID - (void)seteuid((Uid_t)PL_euid); + (void)seteuid(new_euid); #else #ifdef HAS_SETREUID - (void)setreuid((Uid_t)-1, (Uid_t)PL_euid); + (void)setreuid((Uid_t)-1, new_euid); #else #ifdef HAS_SETRESUID - (void)setresuid((Uid_t)-1, (Uid_t)PL_euid, (Uid_t)-1); + (void)setresuid((Uid_t)-1, new_euid, (Uid_t)-1); #else - if (PL_euid == PL_uid) /* special case $> = $< */ - PerlProc_setuid(PL_euid); + if (new_euid == PerlProc_getuid()) /* special case $> = $< */ + PerlProc_setuid(new_euid); else { - PL_euid = PerlProc_geteuid(); Perl_croak(aTHX_ "seteuid() not implemented"); } #endif #endif #endif - PL_euid = PerlProc_geteuid(); break; + } case '(': - PL_gid = SvIV(sv); + { + const Gid_t new_gid = SvGID(sv); + PL_delaymagic_gid = new_gid; if (PL_delaymagic) { PL_delaymagic |= DM_RGID; break; /* don't do magic till later */ } #ifdef HAS_SETRGID - (void)setrgid((Gid_t)PL_gid); + (void)setrgid(new_gid); #else #ifdef HAS_SETREGID - (void)setregid((Gid_t)PL_gid, (Gid_t)-1); + (void)setregid(new_gid, (Gid_t)-1); #else #ifdef HAS_SETRESGID - (void)setresgid((Gid_t)PL_gid, (Gid_t)-1, (Gid_t) 1); + (void)setresgid(new_gid, (Gid_t)-1, (Gid_t) -1); #else - if (PL_gid == PL_egid) /* special case $( = $) */ - (void)PerlProc_setgid(PL_gid); + if (new_gid == PerlProc_getegid()) /* special case $( = $) */ + (void)PerlProc_setgid(new_gid); else { - PL_gid = PerlProc_getgid(); Perl_croak(aTHX_ "setrgid() not implemented"); } #endif #endif #endif - PL_gid = PerlProc_getgid(); break; + } case ')': + { + Gid_t new_egid; #ifdef HAS_SETGROUPS { const char *p = SvPV_const(sv, len); @@ -2868,7 +2905,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) while (isSPACE(*p)) ++p; - PL_egid = Atol(p); + new_egid = (Gid_t)Atol(p); for (i = 0; i < maxgrp; ++i) { while (*p && !isSPACE(*p)) ++p; @@ -2880,42 +2917,53 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) Newx(gary, i + 1, Groups_t); else Renew(gary, i + 1, Groups_t); - gary[i] = Atol(p); + gary[i] = (Groups_t)Atol(p); } if (i) (void)setgroups(i, gary); Safefree(gary); } #else /* HAS_SETGROUPS */ - PL_egid = SvIV(sv); + new_egid = SvGID(sv); #endif /* HAS_SETGROUPS */ + PL_delaymagic_egid = new_egid; if (PL_delaymagic) { PL_delaymagic |= DM_EGID; break; /* don't do magic till later */ } #ifdef HAS_SETEGID - (void)setegid((Gid_t)PL_egid); + (void)setegid(new_egid); #else #ifdef HAS_SETREGID - (void)setregid((Gid_t)-1, (Gid_t)PL_egid); + (void)setregid((Gid_t)-1, new_egid); #else #ifdef HAS_SETRESGID - (void)setresgid((Gid_t)-1, (Gid_t)PL_egid, (Gid_t)-1); + (void)setresgid((Gid_t)-1, new_egid, (Gid_t)-1); #else - if (PL_egid == PL_gid) /* special case $) = $( */ - (void)PerlProc_setgid(PL_egid); + if (new_egid == PerlProc_getgid()) /* special case $) = $( */ + (void)PerlProc_setgid(new_egid); else { - PL_egid = PerlProc_getegid(); Perl_croak(aTHX_ "setegid() not implemented"); } #endif #endif #endif - PL_egid = PerlProc_getegid(); break; + } case ':': PL_chopset = SvPV_force(sv,len); break; + case '$': /* $$ */ + /* Store the pid in mg->mg_obj so we can tell when a fork has + occurred. mg->mg_obj points to *$ by default, so clear it. */ + if (isGV(mg->mg_obj)) { + if (mg->mg_flags & MGf_REFCOUNTED) /* probably never true */ + SvREFCNT_dec(mg->mg_obj); + mg->mg_flags |= MGf_REFCOUNTED; + mg->mg_obj = newSViv((IV)PerlProc_getpid()); + } + else sv_setiv(mg->mg_obj, (IV)PerlProc_getpid()); + break; case '0': LOCK_DOLLARZERO_MUTEX; #ifdef HAS_SETPROCTITLE @@ -2993,22 +3041,41 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) } I32 -Perl_whichsig(pTHX_ const char *sig) +Perl_whichsig_sv(pTHX_ SV *sigsv) +{ + const char *sigpv; + STRLEN siglen; + PERL_ARGS_ASSERT_WHICHSIG_SV; + PERL_UNUSED_CONTEXT; + sigpv = SvPV_const(sigsv, siglen); + return whichsig_pvn(sigpv, siglen); +} + +I32 +Perl_whichsig_pv(pTHX_ const char *sig) { - register char* const* sigv; + PERL_ARGS_ASSERT_WHICHSIG_PV; + PERL_UNUSED_CONTEXT; + return whichsig_pvn(sig, strlen(sig)); +} + +I32 +Perl_whichsig_pvn(pTHX_ const char *sig, STRLEN len) +{ + char* const* sigv; - PERL_ARGS_ASSERT_WHICHSIG; + PERL_ARGS_ASSERT_WHICHSIG_PVN; PERL_UNUSED_CONTEXT; for (sigv = (char* const*)PL_sig_name; *sigv; sigv++) - if (strEQ(sig,*sigv)) + if (strlen(*sigv) == len && memEQ(sig,*sigv, len)) return PL_sig_num[sigv - (char* const*)PL_sig_name]; #ifdef SIGCLD - if (strEQ(sig,"CHLD")) + if (memEQs(sig, len, "CHLD")) return SIGCLD; #endif #ifdef SIGCHLD - if (strEQ(sig,"CLD")) + if (memEQs(sig, len, "CLD")) return SIGCHLD; #endif return -1; @@ -3035,6 +3102,7 @@ Perl_sighandler(int sig) U32 flags = 0; XPV * const tXpv = PL_Xpv; I32 old_ss_ix = PL_savestack_ix; + SV *errsv_save = NULL; if (!PL_psig_ptr[sig]) { @@ -3113,10 +3181,15 @@ Perl_sighandler(int sig) #endif PUTBACK; + errsv_save = newSVsv(ERRSV); + call_sv(MUTABLE_SV(cv), G_DISCARD|G_EVAL); POPSTACK; - if (SvTRUE(ERRSV)) { + { + SV * const errsv = ERRSV; + if (SvTRUE_NN(errsv)) { + SvREFCNT_dec(errsv_save); #ifndef PERL_MICRO /* Handler "died", for example to get out of a restart-able read(). * Before we re-do that on its behalf re-enable the signal which was @@ -3124,27 +3197,33 @@ Perl_sighandler(int sig) */ #ifdef HAS_SIGPROCMASK #if defined(HAS_SIGACTION) && defined(SA_SIGINFO) - if (sip || uap) + if (sip || uap) #endif - { - sigset_t set; - sigemptyset(&set); - sigaddset(&set,sig); - sigprocmask(SIG_UNBLOCK, &set, NULL); - } + { + sigset_t set; + sigemptyset(&set); + sigaddset(&set,sig); + sigprocmask(SIG_UNBLOCK, &set, NULL); + } #else - /* Not clear if this will work */ - (void)rsignal(sig, SIG_IGN); - (void)rsignal(sig, PL_csighandlerp); + /* Not clear if this will work */ + (void)rsignal(sig, SIG_IGN); + (void)rsignal(sig, PL_csighandlerp); #endif #endif /* !PERL_MICRO */ - die_sv(ERRSV); + die_sv(errsv); + } + else { + sv_setsv(errsv, errsv_save); + SvREFCNT_dec(errsv_save); + } } + cleanup: /* pop any of SAVEFREESV, SAVEDESTRUCTOR_X and "save in progress" */ PL_savestack_ix = old_ss_ix; if (flags & 8) - SvREFCNT_dec(sv); + SvREFCNT_dec_NN(sv); PL_op = myop; /* Apparently not needed... */ PL_Sv = tSv; /* Restore global temporaries. */ @@ -3164,31 +3243,20 @@ S_restore_magic(pTHX_ const void *p) if (!sv) return; - if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv)) - { + if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv)) { + SvTEMP_off(sv); /* if it's still magical, this value isn't temporary */ #ifdef PERL_OLD_COPY_ON_WRITE /* While magic was saved (and off) sv_setsv may well have seen this SV as a prime candidate for COW. */ if (SvIsCOW(sv)) sv_force_normal_flags(sv, 0); #endif - if (mgs->mgs_readonly) SvREADONLY_on(sv); if (mgs->mgs_magical) SvFLAGS(sv) |= mgs->mgs_magical; else mg_magical(sv); - if (SvGMAGICAL(sv)) { - /* downgrade public flags to private, - and discard any other private flags */ - - const U32 pubflags = SvFLAGS(sv) & (SVf_IOK|SVf_NOK|SVf_POK); - if (pubflags) { - SvFLAGS(sv) &= ~( pubflags | (SVp_IOK|SVp_NOK|SVp_POK) ); - SvFLAGS(sv) |= ( pubflags << PRIVSHIFT ); - } - } } bumped = mgs->mgs_bumped; @@ -3217,15 +3285,11 @@ S_restore_magic(pTHX_ const void *p) So artificially keep it alive a bit longer. We avoid turning on the TEMP flag, which can cause the SV's buffer to get stolen (and maybe other stuff). */ - int was_temp = SvTEMP(sv); sv_2mortal(sv); - if (!was_temp) { - SvTEMP_off(sv); - } - SvOK_off(sv); + SvTEMP_off(sv); } else - SvREFCNT_dec(sv); /* undo the inc in S_save_magic() */ + SvREFCNT_dec_NN(sv); /* undo the inc in S_save_magic() */ } } @@ -3292,14 +3356,13 @@ Perl_magic_clearhint(pTHX_ SV *sv, MAGIC *mg) PERL_ARGS_ASSERT_MAGIC_CLEARHINT; PERL_UNUSED_ARG(sv); - assert(mg->mg_len == HEf_SVKEY); - - PERL_UNUSED_ARG(sv); - PL_hints |= HINT_LOCALIZE_HH; CopHINTHASH_set(&PL_compiling, - cophh_delete_sv(CopHINTHASH_get(&PL_compiling), - MUTABLE_SV(mg->mg_ptr), 0, 0)); + mg->mg_len == HEf_SVKEY + ? cophh_delete_sv(CopHINTHASH_get(&PL_compiling), + MUTABLE_SV(mg->mg_ptr), 0, 0) + : cophh_delete_pvn(CopHINTHASH_get(&PL_compiling), + mg->mg_ptr, mg->mg_len, 0, 0)); return 0; } @@ -3321,12 +3384,32 @@ Perl_magic_clearhints(pTHX_ SV *sv, MAGIC *mg) return 0; } +int +Perl_magic_copycallchecker(pTHX_ SV *sv, MAGIC *mg, SV *nsv, + const char *name, I32 namlen) +{ + MAGIC *nmg; + + PERL_ARGS_ASSERT_MAGIC_COPYCALLCHECKER; + PERL_UNUSED_ARG(sv); + PERL_UNUSED_ARG(name); + PERL_UNUSED_ARG(namlen); + + sv_magic(nsv, &PL_sv_undef, mg->mg_type, NULL, 0); + nmg = mg_find(nsv, mg->mg_type); + if (nmg->mg_flags & MGf_REFCOUNTED) SvREFCNT_dec(nmg->mg_obj); + nmg->mg_ptr = mg->mg_ptr; + nmg->mg_obj = SvREFCNT_inc_simple(mg->mg_obj); + nmg->mg_flags |= MGf_REFCOUNTED; + return 1; +} + /* * Local variables: * c-indentation-style: bsd * c-basic-offset: 4 - * indent-tabs-mode: t + * indent-tabs-mode: nil * End: * - * ex: set ts=8 sts=4 sw=4 noet: + * ex: set ts=8 sts=4 sw=4 et: */