X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=mg.c;h=d162cd31ffc4b406e61104f95d3da487898d1330;hb=8bbf3450a1ff0a3996dade29a4194cc0939d871f;hp=b69da05403850530429f3b41c8ffdd743fb26856;hpb=d99b02a1a9949639f16470065ea5568cd92f788d;p=p5sagit%2Fp5-mst-13.2.git diff --git a/mg.c b/mg.c index b69da05..d162cd3 100644 --- a/mg.c +++ b/mg.c @@ -1,7 +1,7 @@ /* mg.c * * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - * 2000, 2001, 2002, 2003, by Larry Wall and others + * 2000, 2001, 2002, 2003, 2004, by Larry Wall and others * * You may distribute under the terms of either the GNU General Public * License or the Artistic License, as specified in the README file. @@ -48,6 +48,14 @@ Signal_t Perl_csighandler(int sig); static void restore_magic(pTHX_ void *p); static void unwind_handler_stack(pTHX_ void *p); +#ifdef __Lynx__ +/* Missing protos on LynxOS */ +void setruid(uid_t id); +void seteuid(uid_t id); +void setrgid(uid_t id); +void setegid(uid_t id); +#endif + /* * Use the "DESTRUCTOR" scope cleanup to reinstate magic. */ @@ -139,6 +147,10 @@ Perl_mg_get(pTHX_ SV *sv) if (SvTYPE(sv) == SVTYPEMASK) { Perl_croak(aTHX_ "Tied variable freed while still in use"); } + /* guard against magic having been deleted - eg FETCH calling + * untie */ + if (!SvMAGIC(sv)) + break; /* Don't restore the flags for this entry if it was deleted. */ if (mg->mg_flags & MGf_GSKIP) @@ -372,7 +384,7 @@ Perl_mg_free(pTHX_ SV *sv) if (vtbl && vtbl->svt_free) CALL_FPTR(vtbl->svt_free)(aTHX_ sv, mg); if (mg->mg_ptr && mg->mg_type != PERL_MAGIC_regex_global) { - if (mg->mg_len > 0) + if (mg->mg_len > 0 || mg->mg_type == PERL_MAGIC_utf8) Safefree(mg->mg_ptr); else if (mg->mg_len == HEf_SVKEY) SvREFCNT_dec((SV*)mg->mg_ptr); @@ -385,10 +397,7 @@ Perl_mg_free(pTHX_ SV *sv) return 0; } - -#if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX) #include -#endif U32 Perl_magic_regdata_cnt(pTHX_ SV *sv, MAGIC *mg) @@ -482,12 +491,12 @@ Perl_magic_len(pTHX_ SV *sv, MAGIC *mg) } else { if (ckWARN(WARN_UNINITIALIZED)) - report_uninit(); + report_uninit(sv); } } else { if (ckWARN(WARN_UNINITIALIZED)) - report_uninit(); + report_uninit(sv); } return 0; case '+': @@ -543,7 +552,7 @@ int Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) { register I32 paren; - register char *s; + register char *s = NULL; register I32 i; register REGEXP *rx; @@ -557,9 +566,6 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) case '\004': /* ^D */ sv_setiv(sv, (IV)(PL_debug & DEBUG_MASK)); -#if defined(YYDEBUG) && defined(DEBUGGING) - PL_yydebug = DEBUG_p_TEST; -#endif break; case '\005': /* ^E */ if (*(mg->mg_ptr+1) == '\0') { @@ -611,8 +617,12 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) SetLastError(dwErr); } #else - sv_setnv(sv, (NV)errno); - sv_setpv(sv, errno ? Strerror(errno) : ""); + { + int saveerrno = errno; + sv_setnv(sv, (NV)errno); + sv_setpv(sv, errno ? Strerror(errno) : ""); + errno = saveerrno; + } #endif #endif #endif @@ -635,8 +645,10 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) sv_setsv(sv, &PL_sv_undef); break; case '\017': /* ^O & ^OPEN */ - if (*(mg->mg_ptr+1) == '\0') + if (*(mg->mg_ptr+1) == '\0') { sv_setpv(sv, PL_osname); + SvTAINTED_off(sv); + } else if (strEQ(mg->mg_ptr, "\017PEN")) { if (!PL_compiling.cop_io) sv_setsv(sv, &PL_sv_undef); @@ -801,7 +813,8 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) } break; case '^': - s = IoTOP_NAME(GvIOp(PL_defoutgv)); + if (GvIOp(PL_defoutgv)) + s = IoTOP_NAME(GvIOp(PL_defoutgv)); if (s) sv_setpv(sv,s); else { @@ -810,20 +823,24 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) } break; case '~': - s = IoFMT_NAME(GvIOp(PL_defoutgv)); + if (GvIOp(PL_defoutgv)) + s = IoFMT_NAME(GvIOp(PL_defoutgv)); if (!s) s = GvENAME(PL_defoutgv); sv_setpv(sv,s); break; #ifndef lint case '=': - sv_setiv(sv, (IV)IoPAGE_LEN(GvIOp(PL_defoutgv))); + if (GvIOp(PL_defoutgv)) + sv_setiv(sv, (IV)IoPAGE_LEN(GvIOp(PL_defoutgv))); break; case '-': - sv_setiv(sv, (IV)IoLINES_LEFT(GvIOp(PL_defoutgv))); + if (GvIOp(PL_defoutgv)) + sv_setiv(sv, (IV)IoLINES_LEFT(GvIOp(PL_defoutgv))); break; case '%': - sv_setiv(sv, (IV)IoPAGE(GvIOp(PL_defoutgv))); + if (GvIOp(PL_defoutgv)) + sv_setiv(sv, (IV)IoPAGE(GvIOp(PL_defoutgv))); break; #endif case ':': @@ -834,7 +851,8 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) WITH_THR(sv_setiv(sv, (IV)PL_curcop->cop_arybase)); break; case '|': - sv_setiv(sv, (IV)(IoFLAGS(GvIOp(PL_defoutgv)) & IOf_FLUSH) != 0 ); + if (GvIOp(PL_defoutgv)) + sv_setiv(sv, (IV)(IoFLAGS(GvIOp(PL_defoutgv)) & IOf_FLUSH) != 0 ); break; case ',': break; @@ -1018,6 +1036,7 @@ Perl_magic_set_all_env(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_clear_all_env(pTHX_ SV *sv, MAGIC *mg) { +#ifndef PERL_MICRO #if defined(VMS) || defined(EPOC) Perl_die(aTHX_ "Can't make list assignment to %%ENV on this system"); #else @@ -1044,7 +1063,8 @@ Perl_magic_clear_all_env(pTHX_ SV *sv, MAGIC *mg) } # endif /* USE_ENVIRON_ARRAY */ # endif /* PERL_IMPLICIT_SYS || WIN32 */ -#endif /* VMS || EPC */ +#endif /* VMS || EPOC */ +#endif /* !PERL_MICRO */ return 0; } @@ -1144,7 +1164,7 @@ Perl_magic_clearsig(pTHX_ SV *sv, MAGIC *mg) #endif #ifdef FAKE_DEFAULT_SIGNAL_HANDLERS sig_defaulting[i] = 1; - (void)rsignal(i, &Perl_csighandler); + (void)rsignal(i, PL_csighandlerp); #else (void)rsignal(i, SIG_DFL); #endif @@ -1183,7 +1203,7 @@ Perl_csighandler(int sig) dTHX; #endif #ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS - (void) rsignal(sig, &Perl_csighandler); + (void) rsignal(sig, PL_csighandlerp); if (sig_ignoring[sig]) return; #endif #ifdef FAKE_DEFAULT_SIGNAL_HANDLERS @@ -1213,7 +1233,7 @@ Perl_csighandler_init(void) #ifdef FAKE_DEFAULT_SIGNAL_HANDLERS dTHX; sig_defaulting[sig] = 1; - (void) rsignal(sig, &Perl_csighandler); + (void) rsignal(sig, PL_csighandlerp); #endif #ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS sig_ignoring[sig] = 0; @@ -1306,7 +1326,7 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg) } if (SvTYPE(sv) == SVt_PVGV || SvROK(sv)) { if (i) { - (void)rsignal(i, &Perl_csighandler); + (void)rsignal(i, PL_csighandlerp); #ifdef HAS_SIGPROCMASK LEAVE; #endif @@ -1322,7 +1342,7 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg) if (i) { #ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS sig_ignoring[i] = 1; - (void)rsignal(i, &Perl_csighandler); + (void)rsignal(i, PL_csighandlerp); #else (void)rsignal(i, SIG_IGN); #endif @@ -1333,7 +1353,7 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg) #ifdef FAKE_DEFAULT_SIGNAL_HANDLERS { sig_defaulting[i] = 1; - (void)rsignal(i, &Perl_csighandler); + (void)rsignal(i, PL_csighandlerp); } #else (void)rsignal(i, SIG_DFL); @@ -1348,7 +1368,7 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg) if (!strchr(s,':') && !strchr(s,'\'')) sv_insert(sv, 0, 0, "main::", 6); if (i) - (void)rsignal(i, &Perl_csighandler); + (void)rsignal(i, PL_csighandlerp); else *svp = SvREFCNT_inc(sv); } @@ -1457,9 +1477,9 @@ S_magic_methpack(pTHX_ SV *sv, MAGIC *mg, char *meth) int Perl_magic_getpack(pTHX_ SV *sv, MAGIC *mg) { - magic_methpack(sv,mg,"FETCH"); if (mg->mg_ptr) mg->mg_flags |= MGf_GSKIP; + magic_methpack(sv,mg,"FETCH"); return 0; } @@ -1514,6 +1534,7 @@ Perl_magic_wipepack(pTHX_ SV *sv, MAGIC *mg) call_method("CLEAR", G_SCALAR|G_DISCARD); POPSTACK; LEAVE; + return 0; } @@ -1548,6 +1569,41 @@ Perl_magic_existspack(pTHX_ SV *sv, MAGIC *mg) return magic_methpack(sv,mg,"EXISTS"); } +SV * +Perl_magic_scalarpack(pTHX_ HV *hv, MAGIC *mg) +{ + dSP; + SV *retval = &PL_sv_undef; + SV *tied = SvTIED_obj((SV*)hv, mg); + HV *pkg = SvSTASH((SV*)SvRV(tied)); + + if (!gv_fetchmethod_autoload(pkg, "SCALAR", FALSE)) { + SV *key; + if (HvEITER(hv)) + /* we are in an iteration so the hash cannot be empty */ + return &PL_sv_yes; + /* no xhv_eiter so now use FIRSTKEY */ + key = sv_newmortal(); + magic_nextpack((SV*)hv, mg, key); + HvEITER(hv) = NULL; /* need to reset iterator */ + return SvOK(key) ? &PL_sv_yes : &PL_sv_no; + } + + /* there is a SCALAR method that we can call */ + ENTER; + PUSHSTACKi(PERLSI_MAGIC); + PUSHMARK(SP); + EXTEND(SP, 1); + PUSHs(tied); + PUTBACK; + + if (call_method("SCALAR", G_SCALAR)) + retval = *PL_stack_sp--; + POPSTACK; + LEAVE; + return retval; +} + int Perl_magic_setdbline(pTHX_ SV *sv, MAGIC *mg) { @@ -1724,16 +1780,21 @@ Perl_magic_setsubstr(pTHX_ SV *sv, MAGIC *mg) sv_utf8_upgrade(lsv); sv_pos_u2b(lsv, &lvoff, &lvlen); sv_insert(lsv, lvoff, lvlen, tmps, len); + LvTARGLEN(sv) = sv_len_utf8(sv); SvUTF8_on(lsv); } else if (lsv && SvUTF8(lsv)) { sv_pos_u2b(lsv, &lvoff, &lvlen); + LvTARGLEN(sv) = len; tmps = (char*)bytes_to_utf8((U8*)tmps, &len); sv_insert(lsv, lvoff, lvlen, tmps, len); Safefree(tmps); } - else - sv_insert(lsv, lvoff, lvlen, tmps, len); + else { + sv_insert(lsv, lvoff, lvlen, tmps, len); + LvTARGLEN(sv) = len; + } + return 0; } @@ -1870,14 +1931,14 @@ Perl_magic_killbackrefs(pTHX_ SV *sv, MAGIC *mg) SV **svp = AvARRAY(av); I32 i = AvFILLp(av); while (i >= 0) { - if (svp[i] && svp[i] != &PL_sv_undef) { + if (svp[i]) { if (!SvWEAKREF(svp[i])) Perl_croak(aTHX_ "panic: magic_killbackrefs"); /* XXX Should we check that it hasn't changed? */ SvRV(svp[i]) = 0; (void)SvOK_off(svp[i]); SvWEAKREF_off(svp[i]); - svp[i] = &PL_sv_undef; + svp[i] = Nullsv; } i--; } @@ -2032,12 +2093,14 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) break; case '\017': /* ^O */ if (*(mg->mg_ptr+1) == '\0') { - if (PL_osname) + if (PL_osname) { Safefree(PL_osname); - if (SvOK(sv)) - PL_osname = savepv(SvPV(sv,len)); - else PL_osname = Nullch; + } + if (SvOK(sv)) { + TAINT_PROPER("assigning to $^O"); + PL_osname = savepv(SvPV(sv,len)); + } } else if (strEQ(mg->mg_ptr, "\017PEN")) { if (!PL_compiling.cop_io) @@ -2048,7 +2111,8 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) break; case '\020': /* ^P */ PL_perldb = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv); - if (PL_perldb && !PL_DBsingle) + if ((PERLDB_SUB || PERLDB_LINE || PERLDB_SUBLINE || PERLDB_ASSERTION) + && !PL_DBsingle) init_debugger(); break; case '\024': /* ^T */ @@ -2220,9 +2284,14 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) #ifdef HAS_SETRESUID (void)setresuid((Uid_t)PL_uid, (Uid_t)-1, (Uid_t)-1); #else - if (PL_uid == PL_euid) /* special case $< = $> */ + if (PL_uid == PL_euid) { /* special case $< = $> */ +#ifdef PERL_DARWIN + /* workaround for Darwin's setuid peculiarity, cf [perl #24122] */ + if (PL_uid != 0 && PerlProc_getuid() == 0) + (void)PerlProc_setuid(0); +#endif (void)PerlProc_setuid(PL_uid); - else { + } else { PL_uid = PerlProc_getuid(); Perl_croak(aTHX_ "setruid() not implemented"); } @@ -2375,10 +2444,10 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) #endif /* PL_origalen is set in perl_parse(). */ s = SvPV_force(sv,len); - if (len >= (I32)PL_origalen) { - /* Longer than original, will be truncated. */ - Copy(s, PL_origargv[0], PL_origalen, char); - PL_origargv[0][PL_origalen - 1] = 0; + if (len >= (STRLEN)PL_origalen-1) { + /* Longer than original, will be truncated. We assume that + * PL_origalen bytes are available. */ + Copy(s, PL_origargv[0], PL_origalen-1, char); } else { /* Shorter than original, will be padded. */ @@ -2391,9 +2460,10 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) * --jhi */ (int)' ', PL_origalen - len - 1); - for (i = 1; i < PL_origargc; i++) - PL_origargv[i] = 0; } + PL_origargv[0][PL_origalen-1] = 0; + for (i = 1; i < PL_origargc; i++) + PL_origargv[i] = 0; UNLOCK_DOLLARZERO_MUTEX; break; #endif @@ -2518,7 +2588,7 @@ Perl_sighandler(int sig) #else /* Not clear if this will work */ (void)rsignal(sig, SIG_IGN); - (void)rsignal(sig, &Perl_csighandler); + (void)rsignal(sig, PL_csighandlerp); #endif #endif /* !PERL_MICRO */ Perl_die(aTHX_ Nullformat); @@ -2553,6 +2623,13 @@ restore_magic(pTHX_ void *p) if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv)) { +#ifdef PERL_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(sv); +#endif + if (mgs->mgs_flags) SvFLAGS(sv) |= mgs->mgs_flags; else