X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/052a7c766b9640ee847979cb9d2351a63e23a378..eb699a9c8fb7ddfcafc714f1eba1bbc395dc3675:/pp_sys.c diff --git a/pp_sys.c b/pp_sys.c index f9579af..e28e890 100644 --- a/pp_sys.c +++ b/pp_sys.c @@ -76,18 +76,16 @@ extern int h_errno; #ifdef HAS_PASSWD # ifdef I_PWD # include -# else -# if !defined(VMS) +# elif !defined(VMS) struct passwd *getpwnam (char *); struct passwd *getpwuid (Uid_t); -# endif # endif # ifdef HAS_GETPWENT -#ifndef getpwent +# ifndef getpwent struct passwd *getpwent (void); -#elif defined (VMS) && defined (my_getpwent) +# elif defined (VMS) && defined (my_getpwent) struct passwd *Perl_my_getpwent (pTHX); -#endif +# endif # endif #endif @@ -99,9 +97,9 @@ extern int h_errno; struct group *getgrgid (Gid_t); # endif # ifdef HAS_GETGRENT -#ifndef getgrent +# ifndef getgrent struct group *getgrent (void); -#endif +# endif # endif #endif @@ -118,12 +116,10 @@ extern int h_errno; # undef my_chsize # endif # define my_chsize PerlLIO_chsize +#elif defined(HAS_TRUNCATE) +# define my_chsize PerlLIO_chsize #else -# ifdef HAS_TRUNCATE -# define my_chsize PerlLIO_chsize -# else I32 my_chsize(int fd, Off_t length); -# endif #endif #ifdef HAS_FLOCK @@ -141,12 +137,10 @@ I32 my_chsize(int fd, Off_t length); # if defined(HAS_FCNTL) && defined(FCNTL_CAN_LOCK) # define FLOCK fcntl_emulate_flock # define FCNTL_EMULATE_FLOCK -# else /* no flock() or fcntl(F_SETLK,...) */ -# ifdef HAS_LOCKF -# define FLOCK lockf_emulate_flock -# define LOCKF_EMULATE_FLOCK -# endif /* lockf */ -# endif /* no flock() or fcntl(F_SETLK,...) */ +# elif defined(HAS_LOCKF) +# define FLOCK lockf_emulate_flock +# define LOCKF_EMULATE_FLOCK +# endif # ifdef FLOCK static int FLOCK (int, int); @@ -219,8 +213,8 @@ void endservent(void); #endif #if !defined(PERL_EFF_ACCESS) && defined(HAS_ACCESSX) && defined(ACC_SELF) - /* AIX */ -# define PERL_EFF_ACCESS(p,f) (accessx((p), (f), ACC_SELF)) + /* AIX's accessx() doesn't declare its argument const, unlike every other platform */ +# define PERL_EFF_ACCESS(p,f) (accessx((char*)(p), (f), ACC_SELF)) #endif @@ -240,13 +234,11 @@ S_emulate_eaccess(pTHX_ const char* path, Mode_t mode) #if !defined(HAS_SETREUID) && !defined(HAS_SETRESUID) Perl_croak(aTHX_ "switching effective uid is not implemented"); #else -#ifdef HAS_SETREUID +# ifdef HAS_SETREUID if (setreuid(euid, ruid)) -#else -#ifdef HAS_SETRESUID +# elif defined(HAS_SETRESUID) if (setresuid(euid, ruid, (Uid_t)-1)) -#endif -#endif +# endif /* diag_listed_as: entering effective %s failed */ Perl_croak(aTHX_ "entering effective uid failed"); #endif @@ -254,13 +246,11 @@ S_emulate_eaccess(pTHX_ const char* path, Mode_t mode) #if !defined(HAS_SETREGID) && !defined(HAS_SETRESGID) Perl_croak(aTHX_ "switching effective gid is not implemented"); #else -#ifdef HAS_SETREGID +# ifdef HAS_SETREGID if (setregid(egid, rgid)) -#else -#ifdef HAS_SETRESGID +# elif defined(HAS_SETRESGID) if (setresgid(egid, rgid, (Gid_t)-1)) -#endif -#endif +# endif /* diag_listed_as: entering effective %s failed */ Perl_croak(aTHX_ "entering effective gid failed"); #endif @@ -269,21 +259,17 @@ S_emulate_eaccess(pTHX_ const char* path, Mode_t mode) #ifdef HAS_SETREUID if (setreuid(ruid, euid)) -#else -#ifdef HAS_SETRESUID +#elif defined(HAS_SETRESUID) if (setresuid(ruid, euid, (Uid_t)-1)) #endif -#endif /* diag_listed_as: leaving effective %s failed */ Perl_croak(aTHX_ "leaving effective uid failed"); #ifdef HAS_SETREGID if (setregid(rgid, egid)) -#else -#ifdef HAS_SETRESGID +#elif defined(HAS_SETRESGID) if (setresgid(rgid, egid, (Gid_t)-1)) #endif -#endif /* diag_listed_as: leaving effective %s failed */ Perl_croak(aTHX_ "leaving effective gid failed"); @@ -297,7 +283,7 @@ PP(pp_backtick) dSP; dTARGET; PerlIO *fp; const char * const tmps = POPpconstx; - const I32 gimme = GIMME_V; + const U8 gimme = GIMME_V; const char *mode = "r"; TAINT_PROPER("``"); @@ -320,7 +306,7 @@ PP(pp_backtick) ENTER_with_name("backtick"); SAVESPTR(PL_rs); PL_rs = &PL_sv_undef; - sv_setpvs(TARG, ""); /* note that this preserves previous buffer */ + SvPVCLEAR(TARG); /* note that this preserves previous buffer */ while (sv_gets(TARG, fp, SvCUR(TARG)) != NULL) NOOP; LEAVE_with_name("backtick"); @@ -431,7 +417,7 @@ PP(pp_warn) } else if (SP == MARK) { exsv = &PL_sv_no; - EXTEND(SP, 1); + MEXTEND(SP, 1); SP = MARK + 1; } else { @@ -462,7 +448,7 @@ PP(pp_warn) } } if (SvROK(exsv) && !PL_warnhook) - Perl_warn(aTHX_ "%"SVf, SVfARG(exsv)); + Perl_warn(aTHX_ "%" SVf, SVfARG(exsv)); else warn_sv(exsv); RETSETYES; } @@ -545,9 +531,17 @@ Perl_tied_method(pTHX_ SV *methname, SV **sp, SV *const sv, PUTBACK; /* sp is at *foot* of args, so this pops args from old stack */ PUSHSTACKi(PERLSI_MAGIC); /* extend for object + args. If argc might wrap/truncate when cast - * to SSize_t, set to -1 which will trigger a panic in EXTEND() */ + * to SSize_t and incremented, set to -1, which will trigger a panic in + * EXTEND(). + * The weird way this is written is because g++ is dumb enough to + * warn "comparison is always false" on something like: + * + * sizeof(a) >= sizeof(b) && a >= B_t_MAX -1 + * + * (where the LH condition is false) + */ extend_size = - sizeof(argc) >= sizeof(SSize_t) && argc > SSize_t_MAX - 1 + (argc > (sizeof(argc) >= sizeof(SSize_t) ? SSize_t_MAX - 1 : argc)) ? -1 : (SSize_t)argc + 1; EXTEND(SP, extend_size); PUSHMARK(sp); @@ -621,8 +615,7 @@ PP(pp_open) IoFLAGS(GvIOp(gv)) &= ~IOf_UNTAINT; if (IoDIRP(io)) - Perl_ck_warner_d(aTHX_ packWARN2(WARN_IO, WARN_DEPRECATED), - "Opening dirhandle %"HEKf" also as a file", + Perl_croak(aTHX_ "Cannot open %" HEKf " as a filehandle: it is already open as a dirhandle", HEKfARG(GvENAME_HEK(gv))); mg = SvTIED_mg((const SV *)io, PERL_MAGIC_tiedscalar); @@ -648,7 +641,7 @@ PP(pp_open) if (ok) PUSHi( (I32)PL_forkprocess ); else if (PL_forkprocess == 0) /* we are a new child */ - PUSHi(0); + PUSHs(&PL_sv_zero); else RETPUSHUNDEF; RETURN; @@ -657,6 +650,8 @@ PP(pp_open) PP(pp_close) { dSP; + /* pp_coreargs pushes a NULL to indicate no args passed to + * CORE::close() */ GV * const gv = MAXARG == 0 || (!TOPs && !POPs) ? PL_defoutgv : MUTABLE_GV(POPs); @@ -687,8 +682,6 @@ PP(pp_pipe_op) GV * const wgv = MUTABLE_GV(POPs); GV * const rgv = MUTABLE_GV(POPs); - assert (isGV_with_GP(rgv)); - assert (isGV_with_GP(wgv)); rstio = GvIOn(rgv); if (IoIFP(rstio)) do_close(rgv, FALSE); @@ -697,11 +690,11 @@ PP(pp_pipe_op) if (IoIFP(wstio)) do_close(wgv, FALSE); - if (PerlProc_pipe(fd) < 0) + if (PerlProc_pipe_cloexec(fd) < 0) goto badexit; - IoIFP(rstio) = PerlIO_fdopen(fd[0], "r"PIPE_OPEN_MODE); - IoOFP(wstio) = PerlIO_fdopen(fd[1], "w"PIPE_OPEN_MODE); + IoIFP(rstio) = PerlIO_fdopen(fd[0], "r" PIPE_OPEN_MODE); + IoOFP(wstio) = PerlIO_fdopen(fd[1], "w" PIPE_OPEN_MODE); IoOFP(rstio) = IoIFP(rstio); IoIFP(wstio) = IoOFP(wstio); IoTYPE(rstio) = IoTYPE_RDONLY; @@ -718,12 +711,6 @@ PP(pp_pipe_op) PerlLIO_close(fd[1]); goto badexit; } -#if defined(HAS_FCNTL) && defined(F_SETFD) && defined(FD_CLOEXEC) - /* ensure close-on-exec */ - if ((fd[0] > PL_maxsysfd && fcntl(fd[0], F_SETFD, FD_CLOEXEC) < 0) || - (fd[1] > PL_maxsysfd && fcntl(fd[1], F_SETFD, FD_CLOEXEC) < 0)) - goto badexit; -#endif RETPUSHYES; badexit: @@ -946,10 +933,36 @@ PP(pp_tie) * (Sorry obfuscation writers. You're not going to be given this one.) */ stash = gv_stashsv(*MARK, 0); - if (!stash || !(gv = gv_fetchmethod(stash, methname))) { - DIE(aTHX_ "Can't locate object method \"%s\" via package \"%"SVf"\"", - methname, SVfARG(SvOK(*MARK) ? *MARK : &PL_sv_no)); - } + if (!stash) { + if (SvROK(*MARK)) + DIE(aTHX_ "Can't locate object method \"%s\" via package \"%" SVf "\"", + methname, SVfARG(*MARK)); + else if (isGV(*MARK)) { + /* If the glob doesn't name an existing package, using + * SVfARG(*MARK) would yield "*Foo::Bar" or *main::Foo. So + * generate the name for the error message explicitly. */ + SV *stashname = sv_2mortal(newSV(0)); + gv_fullname4(stashname, (GV *) *MARK, NULL, FALSE); + DIE(aTHX_ "Can't locate object method \"%s\" via package \"%" SVf "\"", + methname, SVfARG(stashname)); + } + else { + SV *stashname = !SvPOK(*MARK) ? &PL_sv_no + : SvCUR(*MARK) ? *MARK + : sv_2mortal(newSVpvs("main")); + DIE(aTHX_ "Can't locate object method \"%s\" via package \"%" SVf "\"" + " (perhaps you forgot to load \"%" SVf "\"?)", + methname, SVfARG(stashname), SVfARG(stashname)); + } + } + else if (!(gv = gv_fetchmethod(stash, methname))) { + /* The effective name can only be NULL for stashes that have + * been deleted from the symbol table, which this one can't + * be, since we just looked it up by name. + */ + DIE(aTHX_ "Can't locate object method \"%s\" via package \"%" HEKf "\"", + methname, HvENAME_HEK_NN(stash)); + } ENTER_with_name("call_TIE"); PUSHSTACKi(PERLSI_MAGIC); PUSHMARK(SP); @@ -998,7 +1011,7 @@ PP(pp_untie) if ((mg = SvTIED_mg(sv, how))) { SV * const obj = SvRV(SvTIED_obj(sv, mg)); - if (obj) { + if (obj && SvSTASH(obj)) { GV * const gv = gv_fetchmethod_autoload(SvSTASH(obj), "UNTIE", FALSE); CV *cv; if (gv && isGV(gv) && (cv = GvCV(gv))) { @@ -1013,7 +1026,7 @@ PP(pp_untie) } else if (mg && SvREFCNT(obj) > 1) { Perl_ck_warner(aTHX_ packWARN(WARN_UNTIE), - "untie attempted while %"UVuf" inner references still exist", + "untie attempted while %" UVuf " inner references still exist", (UV)SvREFCNT(obj) - 1 ) ; } } @@ -1118,6 +1131,7 @@ PP(pp_sselect) struct timeval *tbuf = &timebuf; I32 growsize; char *fd_sets[4]; + SV *svs[4]; #if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678 I32 masksize; I32 offset; @@ -1133,7 +1147,7 @@ PP(pp_sselect) SP -= 4; for (i = 1; i <= 3; i++) { - SV * const sv = SP[i]; + SV * const sv = svs[i] = SP[i]; SvGETMAGIC(sv); if (!SvOK(sv)) continue; @@ -1146,9 +1160,14 @@ PP(pp_sselect) if (!SvPOKp(sv)) Perl_ck_warner(aTHX_ packWARN(WARN_MISC), "Non-string passed as bitmask"); - SvPV_force_nomg_nolen(sv); /* force string conversion */ + if (SvGAMAGIC(sv)) { + svs[i] = sv_newmortal(); + sv_copypv_nomg(svs[i], sv); + } + else + SvPV_force_nomg_nolen(sv); /* force string conversion */ } - j = SvCUR(sv); + j = SvCUR(svs[i]); if (maxlen < j) maxlen = j; } @@ -1197,7 +1216,7 @@ PP(pp_sselect) tbuf = NULL; for (i = 1; i <= 3; i++) { - sv = SP[i]; + sv = svs[i]; if (!SvOK(sv) || SvCUR(sv) == 0) { fd_sets[i] = 0; continue; @@ -1244,7 +1263,7 @@ PP(pp_sselect) #endif for (i = 1; i <= 3; i++) { if (fd_sets[i]) { - sv = SP[i]; + sv = svs[i]; #if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678 s = SvPVX(sv); for (offset = 0; offset < growsize; offset += masksize) { @@ -1253,7 +1272,10 @@ PP(pp_sselect) } Safefree(fd_sets[i]); #endif - SvSETMAGIC(sv); + if (sv != SP[i]) + SvSetMagicSV(SP[i], sv); + else + SvSETMAGIC(sv); } } @@ -1286,10 +1308,13 @@ of the typeglob that C points to is decreased by one. void Perl_setdefout(pTHX_ GV *gv) { + GV *oldgv = PL_defoutgv; + PERL_ARGS_ASSERT_SETDEFOUT; + SvREFCNT_inc_simple_void_NN(gv); - SvREFCNT_dec(PL_defoutgv); PL_defoutgv = gv; + SvREFCNT_dec(oldgv); } PP(pp_select) @@ -1326,6 +1351,8 @@ PP(pp_select) PP(pp_getc) { dSP; dTARGET; + /* pp_coreargs pushes a NULL to indicate no args passed to + * CORE::getc() */ GV * const gv = MAXARG==0 || (!TOPs && !POPs) ? PL_stdingv : MUTABLE_GV(POPs); IO *const io = GvIO(gv); @@ -1336,7 +1363,7 @@ PP(pp_getc) if (io) { const MAGIC * const mg = SvTIED_mg((const SV *)io, PERL_MAGIC_tiedscalar); if (mg) { - const U32 gimme = GIMME_V; + const U8 gimme = GIMME_V; Perl_tied_method(aTHX_ SV_CONST(GETC), SP, MUTABLE_SV(io), mg, gimme, 0); if (gimme == G_SCALAR) { SPAGAIN; @@ -1373,23 +1400,17 @@ STATIC OP * S_doform(pTHX_ CV *cv, GV *gv, OP *retop) { PERL_CONTEXT *cx; - const I32 gimme = GIMME_V; + const U8 gimme = GIMME_V; PERL_ARGS_ASSERT_DOFORM; if (CvCLONE(cv)) cv = MUTABLE_CV(sv_2mortal(MUTABLE_SV(cv_clone(cv)))); - ENTER; - SAVETMPS; - - PUSHBLOCK(cx, CXt_FORMAT, PL_stack_sp); - PUSHFORMAT(cx, retop); - if (CvDEPTH(cv) >= 2) { - PERL_STACK_OVERFLOW_CHECK(); + cx = cx_pushblock(CXt_FORMAT, gimme, PL_stack_sp, PL_savestack_ix); + cx_pushformat(cx, cv, retop, gv); + if (CvDEPTH(cv) >= 2) pad_push(CvPADLIST(cv), CvDEPTH(cv)); - } - SAVECOMPPAD(); PAD_SET_CUR_NOSAVE(CvPADLIST(cv), CvDEPTH(cv)); setdefout(gv); /* locally select filehandle so $% et al work */ @@ -1403,7 +1424,6 @@ PP(pp_enterwrite) IO *io; GV *fgv; CV *cv = NULL; - SV *tmpsv = NULL; if (MAXARG == 0) { EXTEND(SP, 1); @@ -1427,9 +1447,9 @@ PP(pp_enterwrite) cv = GvFORM(fgv); if (!cv) { - tmpsv = sv_newmortal(); + SV * const tmpsv = sv_newmortal(); gv_efullname4(tmpsv, fgv, NULL, FALSE); - DIE(aTHX_ "Undefined format \"%"SVf"\" called", SVfARG(tmpsv)); + DIE(aTHX_ "Undefined format \"%" SVf "\" called", SVfARG(tmpsv)); } IoFLAGS(io) &= ~IOf_DIDTOP; RETURNOP(doform(cv,gv,PL_op->op_next)); @@ -1438,12 +1458,10 @@ PP(pp_enterwrite) PP(pp_leavewrite) { dSP; - GV * const gv = cxstack[cxstack_ix].blk_format.gv; + GV * const gv = CX_CUR()->blk_format.gv; IO * const io = GvIOp(gv); PerlIO *ofp; PerlIO *fp; - SV **newsp; - I32 gimme; PERL_CONTEXT *cx; OP *retop; bool is_return = cBOOL(PL_op->op_type == OP_RETURN); @@ -1466,7 +1484,7 @@ PP(pp_leavewrite) SV *topname; if (!IoFMT_NAME(io)) IoFMT_NAME(io) = savepv(GvNAME(gv)); - topname = sv_2mortal(Perl_newSVpvf(aTHX_ "%"HEKf"_TOP", + topname = sv_2mortal(Perl_newSVpvf(aTHX_ "%" HEKf "_TOP", HEKfARG(GvNAME_HEK(gv)))); topgv = gv_fetchsv(topname, 0, SVt_PVFM); if ((topgv && GvFORM(topgv)) || @@ -1485,10 +1503,11 @@ PP(pp_leavewrite) if (IoFLAGS(io) & IOf_DIDTOP) { /* Oh dear. It still doesn't fit. */ I32 lines = IoLINES_LEFT(io); const char *s = SvPVX_const(PL_formtarget); + const char *e = SvEND(PL_formtarget); if (lines <= 0) /* Yow, header didn't even fit!!! */ goto forget_top; while (lines-- > 0) { - s = strchr(s, '\n'); + s = (char *) memchr(s, '\n', e - s); if (!s) break; s++; @@ -1514,17 +1533,22 @@ PP(pp_leavewrite) if (!cv) { SV * const sv = sv_newmortal(); gv_efullname4(sv, fgv, NULL, FALSE); - DIE(aTHX_ "Undefined top format \"%"SVf"\" called", SVfARG(sv)); + DIE(aTHX_ "Undefined top format \"%" SVf "\" called", SVfARG(sv)); } return doform(cv, gv, PL_op); } forget_top: - POPBLOCK(cx,PL_curpm); + cx = CX_CUR(); + assert(CxTYPE(cx) == CXt_FORMAT); + SP = PL_stack_base + cx->blk_oldsp; /* ignore retval of formline */ + CX_LEAVE_SCOPE(cx); + cx_popformat(cx); + cx_popblock(cx); retop = cx->blk_sub.retop; - POPFORMAT(cx); - SP = newsp; /* ignore retval of formline */ - LEAVE; + CX_POP(cx); + + EXTEND(SP, 1); if (is_return) /* XXX the semantics of doing 'return' in a format aren't documented. @@ -1555,7 +1579,6 @@ PP(pp_leavewrite) } } PL_formtarget = PL_bodytarget; - PERL_UNUSED_VAR(gimme); RETURNOP(retop); } @@ -1631,7 +1654,7 @@ PP(pp_sysopen) /* Need TIEHANDLE method ? */ const char * const tmps = SvPV_const(sv, len); - if (do_open_raw(gv, tmps, len, mode, perm)) { + if (do_open_raw(gv, tmps, len, mode, perm, NULL)) { IoLINES(GvIOp(gv)) = 0; PUSHs(&PL_sv_yes); } @@ -1681,7 +1704,7 @@ PP(pp_sysread) goto say_undef; bufsv = *++MARK; if (! SvOK(bufsv)) - sv_setpvs(bufsv, ""); + SvPVCLEAR(bufsv); length = SvIVx(*++MARK); if (length < 0) DIE(aTHX_ "Negative length"); @@ -1702,9 +1725,9 @@ PP(pp_sysread) if ((fp_utf8 = PerlIO_isutf8(IoIFP(io))) && !IN_BYTES) { if (PL_op->op_type == OP_SYSREAD || PL_op->op_type == OP_RECV) { - Perl_ck_warner(aTHX_ packWARN(WARN_DEPRECATED), - "%s() is deprecated on :utf8 handles", - OP_DESC(PL_op)); + Perl_croak(aTHX_ + "%s() isn't allowed on :utf8 handles", + OP_DESC(PL_op)); } buffer = SvPVutf8_force(bufsv, blen); /* UTF-8 may not have been set if they are all low bytes */ @@ -1730,7 +1753,7 @@ PP(pp_sysread) char namebuf[MAXPATHLEN]; if (fd < 0) { SETERRNO(EBADF,SS_IVCHAN); - RETPUSHUNDEF; + goto say_undef; } #if (defined(VMS_DO_SOCKETS) && defined(DECCRTL_SOCKETS)) || defined(__QNXNTO__) bufsize = sizeof (struct sockaddr_in); @@ -1746,7 +1769,7 @@ PP(pp_sysread) count = PerlSock_recvfrom(fd, buffer, length, offset, (struct sockaddr *)namebuf, &bufsize); if (count < 0) - RETPUSHUNDEF; + goto say_undef; /* MSG_TRUNC can give oversized count; quietly lose it */ if (count > length) count = length; @@ -1915,7 +1938,6 @@ PP(pp_syswrite) const char *buffer; SSize_t retval; STRLEN blen; - STRLEN orig_blen_bytes; const int op_type = PL_op->op_type; bool doing_utf8; U8 *tmpbuf = NULL; @@ -1961,19 +1983,12 @@ PP(pp_syswrite) /* Do this first to trigger any overloading. */ buffer = SvPV_const(bufsv, blen); - orig_blen_bytes = blen; doing_utf8 = DO_UTF8(bufsv); if (PerlIO_isutf8(IoIFP(io))) { - Perl_ck_warner(aTHX_ packWARN(WARN_DEPRECATED), - "%s() is deprecated on :utf8 handles", - OP_DESC(PL_op)); - if (!SvUTF8(bufsv)) { - /* We don't modify the original scalar. */ - tmpbuf = bytes_to_utf8((const U8*) buffer, &blen); - buffer = (char *) tmpbuf; - doing_utf8 = TRUE; - } + Perl_croak(aTHX_ + "%s() isn't allowed on :utf8 handles", + OP_DESC(PL_op)); } else if (doing_utf8) { STRLEN tmplen = blen; @@ -2006,25 +2021,10 @@ PP(pp_syswrite) #endif { Size_t length = 0; /* This length is in characters. */ - STRLEN blen_chars; IV offset; - if (doing_utf8) { - if (tmpbuf) { - /* The SV is bytes, and we've had to upgrade it. */ - blen_chars = orig_blen_bytes; - } else { - /* The SV really is UTF-8. */ - /* Don't call sv_len_utf8 on a magical or overloaded - scalar, as we might get back a different result. */ - blen_chars = sv_or_pv_len_utf8(bufsv, buffer, blen); - } - } else { - blen_chars = blen; - } - if (MARK >= SP) { - length = blen_chars; + length = blen; } else { #if Size_t_size > IVSIZE length = (Size_t)SvNVx(*++MARK); @@ -2040,46 +2040,21 @@ PP(pp_syswrite) if (MARK < SP) { offset = SvIVx(*++MARK); if (offset < 0) { - if (-offset > (IV)blen_chars) { + if (-offset > (IV)blen) { Safefree(tmpbuf); DIE(aTHX_ "Offset outside string"); } - offset += blen_chars; - } else if (offset > (IV)blen_chars) { + offset += blen; + } else if (offset > (IV)blen) { Safefree(tmpbuf); DIE(aTHX_ "Offset outside string"); } } else offset = 0; - if (length > blen_chars - offset) - length = blen_chars - offset; - if (doing_utf8) { - /* Here we convert length from characters to bytes. */ - if (tmpbuf || SvGMAGICAL(bufsv) || SvAMAGIC(bufsv)) { - /* Either we had to convert the SV, or the SV is magical, or - the SV has overloading, in which case we can't or mustn't - or mustn't call it again. */ - - buffer = (const char*)utf8_hop((const U8 *)buffer, offset); - length = utf8_hop((U8 *)buffer, length) - (U8 *)buffer; - } else { - /* It's a real UTF-8 SV, and it's not going to change under - us. Take advantage of any cache. */ - I32 start = offset; - I32 len_I32 = length; - - /* Convert the start and end character positions to bytes. - Remember that the second argument to sv_pos_u2b is relative - to the first. */ - sv_pos_u2b(bufsv, &start, &len_I32); - - buffer += start; - length = len_I32; - } - } - else { - buffer = buffer+offset; - } + if (length > blen - offset) + length = blen - offset; + buffer = buffer+offset; + #ifdef PERL_SOCK_SYSWRITE_IS_SEND if (IoTYPE(io) == IoTYPE_SOCKET) { retval = PerlSock_send(fd, buffer, length, 0); @@ -2095,8 +2070,6 @@ PP(pp_syswrite) if (retval < 0) goto say_undef; SP = ORIGMARK; - if (doing_utf8) - retval = utf8_length((U8*)buffer, (U8*)buffer + retval); Safefree(tmpbuf); #if Size_t_size > IVSIZE @@ -2148,7 +2121,7 @@ PP(pp_eof) } if (!gv) - RETPUSHNO; + RETPUSHYES; if ((io = GvIO(gv)) && (mg = SvTIED_mg((const SV *)io, PERL_MAGIC_tiedscalar))) { return tied_method1(SV_CONST(EOF), SP, MUTABLE_SV(io), mg, newSVuv(which)); @@ -2348,7 +2321,7 @@ PP(pp_truncate) */ mode |= O_BINARY; #endif - tmpfd = PerlLIO_open(name, mode); + tmpfd = PerlLIO_open_cloexec(name, mode); if (tmpfd < 0) { result = 0; @@ -2418,13 +2391,11 @@ PP(pp_ioctl) else #ifndef HAS_FCNTL DIE(aTHX_ "fcntl is not implemented"); -#else -#if defined(OS2) && defined(__EMX__) +#elif defined(OS2) && defined(__EMX__) retval = fcntl(PerlIO_fileno(IoIFP(io)), func, (int)s); #else retval = fcntl(PerlIO_fileno(IoIFP(io)), func, s); #endif -#endif #if defined(HAS_IOCTL) || defined(HAS_FCNTL) if (SvPOK(argsv)) { @@ -2492,13 +2463,12 @@ PP(pp_socket) do_close(gv, FALSE); TAINT_PROPER("socket"); - fd = PerlSock_socket(domain, type, protocol); + fd = PerlSock_socket_cloexec(domain, type, protocol); if (fd < 0) { - SETERRNO(EBADF,RMS_IFI); RETPUSHUNDEF; } - IoIFP(io) = PerlIO_fdopen(fd, "r"SOCKET_OPEN_MODE); /* stdio gets confused about sockets */ - IoOFP(io) = PerlIO_fdopen(fd, "w"SOCKET_OPEN_MODE); + IoIFP(io) = PerlIO_fdopen(fd, "r" SOCKET_OPEN_MODE); /* stdio gets confused about sockets */ + IoOFP(io) = PerlIO_fdopen(fd, "w" SOCKET_OPEN_MODE); IoTYPE(io) = IoTYPE_SOCKET; if (!IoIFP(io) || !IoOFP(io)) { if (IoIFP(io)) PerlIO_close(IoIFP(io)); @@ -2506,11 +2476,6 @@ PP(pp_socket) if (!IoIFP(io) && !IoOFP(io)) PerlLIO_close(fd); RETPUSHUNDEF; } -#if defined(HAS_FCNTL) && defined(F_SETFD) && defined(FD_CLOEXEC) - /* ensure close-on-exec */ - if (fd > PL_maxsysfd && fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) - RETPUSHUNDEF; -#endif RETPUSHYES; } @@ -2536,13 +2501,13 @@ PP(pp_sockpair) do_close(gv2, FALSE); TAINT_PROPER("socketpair"); - if (PerlSock_socketpair(domain, type, protocol, fd) < 0) + if (PerlSock_socketpair_cloexec(domain, type, protocol, fd) < 0) RETPUSHUNDEF; - IoIFP(io1) = PerlIO_fdopen(fd[0], "r"SOCKET_OPEN_MODE); - IoOFP(io1) = PerlIO_fdopen(fd[0], "w"SOCKET_OPEN_MODE); + IoIFP(io1) = PerlIO_fdopen(fd[0], "r" SOCKET_OPEN_MODE); + IoOFP(io1) = PerlIO_fdopen(fd[0], "w" SOCKET_OPEN_MODE); IoTYPE(io1) = IoTYPE_SOCKET; - IoIFP(io2) = PerlIO_fdopen(fd[1], "r"SOCKET_OPEN_MODE); - IoOFP(io2) = PerlIO_fdopen(fd[1], "w"SOCKET_OPEN_MODE); + IoIFP(io2) = PerlIO_fdopen(fd[1], "r" SOCKET_OPEN_MODE); + IoOFP(io2) = PerlIO_fdopen(fd[1], "w" SOCKET_OPEN_MODE); IoTYPE(io2) = IoTYPE_SOCKET; if (!IoIFP(io1) || !IoOFP(io1) || !IoIFP(io2) || !IoOFP(io2)) { if (IoIFP(io1)) PerlIO_close(IoIFP(io1)); @@ -2553,12 +2518,6 @@ PP(pp_sockpair) if (!IoIFP(io2) && !IoOFP(io2)) PerlLIO_close(fd[1]); RETPUSHUNDEF; } -#if defined(HAS_FCNTL) && defined(F_SETFD) && defined(FD_CLOEXEC) - /* ensure close-on-exec */ - if ((fd[0] > PL_maxsysfd && fcntl(fd[0], F_SETFD, FD_CLOEXEC) < 0) || - (fd[1] > PL_maxsysfd && fcntl(fd[1], F_SETFD, FD_CLOEXEC) < 0)) - RETPUSHUNDEF; -#endif RETPUSHYES; #else @@ -2645,7 +2604,7 @@ PP(pp_accept) goto nuts; nstio = GvIOn(ngv); - fd = PerlSock_accept(PerlIO_fileno(IoIFP(gstio)), (struct sockaddr *) namebuf, &len); + fd = PerlSock_accept_cloexec(PerlIO_fileno(IoIFP(gstio)), (struct sockaddr *) namebuf, &len); #if defined(OEMVS) if (len == 0) { /* Some platforms indicate zero length when an AF_UNIX client is @@ -2661,8 +2620,8 @@ PP(pp_accept) goto badexit; if (IoIFP(nstio)) do_close(ngv, FALSE); - IoIFP(nstio) = PerlIO_fdopen(fd, "r"SOCKET_OPEN_MODE); - IoOFP(nstio) = PerlIO_fdopen(fd, "w"SOCKET_OPEN_MODE); + IoIFP(nstio) = PerlIO_fdopen(fd, "r" SOCKET_OPEN_MODE); + IoOFP(nstio) = PerlIO_fdopen(fd, "w" SOCKET_OPEN_MODE); IoTYPE(nstio) = IoTYPE_SOCKET; if (!IoIFP(nstio) || !IoOFP(nstio)) { if (IoIFP(nstio)) PerlIO_close(IoIFP(nstio)); @@ -2670,11 +2629,6 @@ PP(pp_accept) if (!IoIFP(nstio) && !IoOFP(nstio)) PerlLIO_close(fd); goto badexit; } -#if defined(HAS_FCNTL) && defined(F_SETFD) && defined(FD_CLOEXEC) - /* ensure close-on-exec */ - if (fd > PL_maxsysfd && fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) - goto badexit; -#endif #ifdef __SCO_VERSION__ len = sizeof (struct sockaddr_in); /* OpenUNIX 8 somehow truncates info */ @@ -2867,7 +2821,7 @@ PP(pp_stat) dSP; GV *gv = NULL; IO *io = NULL; - I32 gimme; + U8 gimme; I32 max = 13; SV* sv; @@ -2877,7 +2831,7 @@ PP(pp_stat) if (gv != PL_defgv) { do_fstat_warning_check: Perl_ck_warner(aTHX_ packWARN(WARN_IO), - "lstat() on filehandle%s%"SVf, + "lstat() on filehandle%s%" SVf, gv ? " " : "", SVfARG(gv ? sv_2mortal(newSVhek(GvENAME_HEK(gv))) @@ -2887,13 +2841,14 @@ PP(pp_stat) Perl_croak(aTHX_ "The stat preceding lstat() wasn't an lstat"); } - if (gv != PL_defgv) { - bool havefp; + if (gv == PL_defgv) { + if (PL_laststatval < 0) + SETERRNO(EBADF,RMS_IFI); + } else { do_fstat_have_io: - havefp = FALSE; PL_laststype = OP_STAT; PL_statgv = gv ? gv : (GV *)io; - sv_setpvs(PL_statname, ""); + SvPVCLEAR(PL_statname); if(gv) { io = GvIO(gv); } @@ -2901,22 +2856,25 @@ PP(pp_stat) if (IoIFP(io)) { int fd = PerlIO_fileno(IoIFP(io)); if (fd < 0) { + report_evil_fh(gv); PL_laststatval = -1; SETERRNO(EBADF,RMS_IFI); } else { PL_laststatval = PerlLIO_fstat(fd, &PL_statcache); - havefp = TRUE; } } else if (IoDIRP(io)) { PL_laststatval = PerlLIO_fstat(my_dirfd(IoDIRP(io)), &PL_statcache); - havefp = TRUE; } else { + report_evil_fh(gv); PL_laststatval = -1; + SETERRNO(EBADF,RMS_IFI); } - } - else PL_laststatval = -1; - if (PL_laststatval < 0 && !havefp) report_evil_fh(gv); + } else { + report_evil_fh(gv); + PL_laststatval = -1; + SETERRNO(EBADF,RMS_IFI); + } } if (PL_laststatval < 0) { @@ -2925,28 +2883,33 @@ PP(pp_stat) } else { const char *file; + const char *temp; + STRLEN len; if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVIO) { io = MUTABLE_IO(SvRV(sv)); if (PL_op->op_type == OP_LSTAT) goto do_fstat_warning_check; goto do_fstat_have_io; } - SvTAINTED_off(PL_statname); /* previous tainting irrelevant */ - sv_setpv(PL_statname, SvPV_nomg_const_nolen(sv)); + temp = SvPV_nomg_const(sv, len); + sv_setpv(PL_statname, temp); PL_statgv = NULL; PL_laststype = PL_op->op_type; file = SvPV_nolen_const(PL_statname); - if (PL_op->op_type == OP_LSTAT) + if (!IS_SAFE_PATHNAME(temp, len, OP_NAME(PL_op))) { + PL_laststatval = -1; + } + else if (PL_op->op_type == OP_LSTAT) PL_laststatval = PerlLIO_lstat(file, &PL_statcache); else PL_laststatval = PerlLIO_stat(file, &PL_statcache); if (PL_laststatval < 0) { if (ckWARN(WARN_NEWLINE) && should_warn_nl(file)) { /* PL_warn_nl is constant */ - GCC_DIAG_IGNORE(-Wformat-nonliteral); + GCC_DIAG_IGNORE_STMT(-Wformat-nonliteral); Perl_warner(aTHX_ packWARN(WARN_NEWLINE), PL_warn_nl, "stat"); - GCC_DIAG_RESTORE; + GCC_DIAG_RESTORE_STMT; } max = 0; } @@ -2962,15 +2925,63 @@ PP(pp_stat) EXTEND(SP, max); EXTEND_MORTAL(max); mPUSHi(PL_statcache.st_dev); -#if ST_INO_SIZE > IVSIZE - mPUSHn(PL_statcache.st_ino); -#else -# if ST_INO_SIGN <= 0 - mPUSHi(PL_statcache.st_ino); -# else - mPUSHu(PL_statcache.st_ino); -# endif -#endif + { + /* + * We try to represent st_ino as a native IV or UV where + * possible, but fall back to a decimal string where + * necessary. The code to generate these decimal strings + * is quite obtuse, because (a) we're portable to non-POSIX + * platforms where st_ino might be signed; (b) we didn't + * necessarily detect at Configure time whether st_ino is + * signed; (c) we're portable to non-POSIX platforms where + * ino_t isn't defined, so have no name for the type of + * st_ino; and (d) sprintf() doesn't necessarily support + * integers as large as st_ino. + */ + bool neg; + Stat_t s; + CLANG_DIAG_IGNORE_STMT(-Wtautological-compare); + GCC_DIAG_IGNORE_STMT(-Wtype-limits); + neg = PL_statcache.st_ino < 0; + GCC_DIAG_RESTORE_STMT; + CLANG_DIAG_RESTORE_STMT; + if (neg) { + s.st_ino = (IV)PL_statcache.st_ino; + if (LIKELY(s.st_ino == PL_statcache.st_ino)) { + mPUSHi(s.st_ino); + } else { + char buf[sizeof(s.st_ino)*3+1], *p; + s.st_ino = PL_statcache.st_ino; + for (p = buf + sizeof(buf); p != buf+1; ) { + Stat_t t; + t.st_ino = s.st_ino / 10; + *--p = '0' + (int)(t.st_ino*10 - s.st_ino); + s.st_ino = t.st_ino; + } + while (*p == '0') + p++; + *--p = '-'; + mPUSHp(p, buf+sizeof(buf) - p); + } + } else { + s.st_ino = (UV)PL_statcache.st_ino; + if (LIKELY(s.st_ino == PL_statcache.st_ino)) { + mPUSHu(s.st_ino); + } else { + char buf[sizeof(s.st_ino)*3], *p; + s.st_ino = PL_statcache.st_ino; + for (p = buf + sizeof(buf); p != buf; ) { + Stat_t t; + t.st_ino = s.st_ino / 10; + *--p = '0' + (int)(s.st_ino - t.st_ino*10); + s.st_ino = t.st_ino; + } + while (*p == '0') + p++; + mPUSHp(p, buf+sizeof(buf) - p); + } + } + } mPUSHu(PL_statcache.st_mode); mPUSHu(PL_statcache.st_nlink); @@ -3031,7 +3042,7 @@ S_ft_return_false(pTHX_ SV *ret) { PUTBACK; if (PL_op->op_private & OPpFT_STACKING) { - while (OP_IS_FILETEST(next->op_type) + while (next && OP_IS_FILETEST(next->op_type) && next->op_private & OPpFT_STACKED) next = next->op_next; } @@ -3173,8 +3184,12 @@ PP(pp_ftrread) if (use_access) { #if defined(HAS_ACCESS) || defined (PERL_EFF_ACCESS) - const char *name = SvPV_nolen(*PL_stack_sp); - if (effective) { + STRLEN len; + const char *name = SvPV(*PL_stack_sp, len); + if (!IS_SAFE_PATHNAME(name, len, OP_NAME(PL_op))) { + result = -1; + } + else if (effective) { # ifdef PERL_EFF_ACCESS result = PERL_EFF_ACCESS(name, access_mode); # else @@ -3254,7 +3269,7 @@ PP(pp_ftis) break; } SvSETMAGIC(TARG); - return SvTRUE_nomg(TARG) + return SvTRUE_nomg_NN(TARG) ? S_ft_return_true(aTHX_ TARG) : S_ft_return_false(aTHX_ TARG); } } @@ -3285,24 +3300,6 @@ PP(pp_ftrowned) } tryAMAGICftest_MG(opchar); - /* I believe that all these three are likely to be defined on most every - system these days. */ -#ifndef S_ISUID - if(PL_op->op_type == OP_FTSUID) { - FT_RETURNNO; - } -#endif -#ifndef S_ISGID - if(PL_op->op_type == OP_FTSGID) { - FT_RETURNNO; - } -#endif -#ifndef S_ISVTX - if(PL_op->op_type == OP_FTSVTX) { - FT_RETURNNO; - } -#endif - result = my_stat_flags(0); if (result < 0) FT_RETURNUNDEF; @@ -3404,7 +3401,7 @@ PP(pp_fttty) else if (name && isDIGIT(*name) && grok_atoUV(name, &uv, NULL) && uv <= PERL_INT_MAX) fd = (int)uv; else - FT_RETURNUNDEF; + fd = -1; if (fd < 0) { SETERRNO(EBADF,RMS_IFI); FT_RETURNUNDEF; @@ -3428,6 +3425,7 @@ PP(pp_fttext) SV *sv = NULL; GV *gv; PerlIO *fp; + const U8 * first_variant; tryAMAGICftest_MG(PL_op->op_type == OP_FTTEXT ? 'T' : 'B'); @@ -3453,7 +3451,7 @@ PP(pp_fttext) } else { PL_statgv = gv; - sv_setpvs(PL_statname, ""); + SvPVCLEAR(PL_statname); io = GvIO(PL_statgv); } PL_laststatval = -1; @@ -3499,10 +3497,18 @@ PP(pp_fttext) } else { const char *file; + const char *temp; + STRLEN temp_len; int fd; assert(sv); - sv_setpv(PL_statname, SvPV_nomg_const_nolen(sv)); + temp = SvPV_nomg_const(sv, temp_len); + sv_setpv(PL_statname, temp); + if (!IS_SAFE_PATHNAME(temp, temp_len, OP_NAME(PL_op))) { + PL_laststatval = -1; + PL_laststype = OP_STAT; + FT_RETURNUNDEF; + } really_filename: file = SvPVX_const(PL_statname); PL_statgv = NULL; @@ -3513,9 +3519,9 @@ PP(pp_fttext) } if (ckWARN(WARN_NEWLINE) && should_warn_nl(file)) { /* PL_warn_nl is constant */ - GCC_DIAG_IGNORE(-Wformat-nonliteral); + GCC_DIAG_IGNORE_STMT(-Wformat-nonliteral); Perl_warner(aTHX_ packWARN(WARN_NEWLINE), PL_warn_nl, "open"); - GCC_DIAG_RESTORE; + GCC_DIAG_RESTORE_STMT; } FT_RETURNUNDEF; } @@ -3528,8 +3534,9 @@ PP(pp_fttext) } PL_laststatval = PerlLIO_fstat(fd, &PL_statcache); if (PL_laststatval < 0) { + dSAVE_ERRNO; (void)PerlIO_close(fp); - SETERRNO(EBADF,RMS_IFI); + RESTORE_ERRNO; FT_RETURNUNDEF; } PerlIO_binmode(aTHX_ fp, '<', O_BINARY, NULL); @@ -3552,14 +3559,13 @@ PP(pp_fttext) #endif assert(len); - if (! is_invariant_string((U8 *) s, len)) { - const U8 *ep; + if (! is_utf8_invariant_string_loc((U8 *) s, len, &first_variant)) { /* Here contains a variant under UTF-8 . See if the entire string is - * UTF-8. But the buffer may end in a partial character, so consider - * it UTF-8 if the first non-UTF8 char is an ending partial */ - if (is_utf8_string_loc((U8 *) s, len, &ep) - || ep + UTF8SKIP(ep) > (U8 *) (s + len)) + * UTF-8. */ + if (is_utf8_fixed_width_buf_flags(first_variant, + len - ((char *) first_variant - (char *) s), + 0)) { if (PL_op->op_type == OP_FTTEXT) { FT_RETURNYES; @@ -3586,14 +3592,14 @@ PP(pp_fttext) } else #endif - if (isPRINT_A(*s) - /* VT occurs so rarely in text, that we consider it odd */ - || (isSPACE_A(*s) && *s != VT_NATIVE) + if ( isPRINT_A(*s) + /* VT occurs so rarely in text, that we consider it odd */ + || (isSPACE_A(*s) && *s != VT_NATIVE) /* But there is a fair amount of backspaces and escapes in * some text */ - || *s == '\b' - || *s == ESC_NATIVE) + || *s == '\b' + || *s == ESC_NATIVE) { continue; } @@ -3624,7 +3630,7 @@ PP(pp_chdir) "chdir() on unopened filehandle %" SVf, sv); } SETERRNO(EBADF,RMS_IFI); - PUSHi(0); + PUSHs(&PL_sv_zero); TAINT_PROPER("chdir"); RETURN; } @@ -3636,6 +3642,7 @@ PP(pp_chdir) HV * const table = GvHVn(PL_envgv); SV **svp; + EXTEND(SP, 1); if ( (svp = hv_fetchs(table, "HOME", FALSE)) || (svp = hv_fetchs(table, "LOGDIR", FALSE)) #ifdef VMS @@ -3646,7 +3653,7 @@ PP(pp_chdir) tmps = SvPV_nolen_const(*svp); } else { - PUSHi(0); + PUSHs(&PL_sv_zero); SETERRNO(EINVAL, LIB_INVARG); TAINT_PROPER("chdir"); RETURN; @@ -3691,7 +3698,7 @@ PP(pp_chdir) nuts: report_evil_fh(gv); SETERRNO(EBADF,RMS_IFI); - PUSHi(0); + PUSHs(&PL_sv_zero); RETURN; #endif } @@ -3726,17 +3733,20 @@ PP(pp_rename) { dSP; dTARGET; int anum; +#ifndef HAS_RENAME + Stat_t statbuf; +#endif const char * const tmps2 = POPpconstx; const char * const tmps = SvPV_nolen_const(TOPs); TAINT_PROPER("rename"); #ifdef HAS_RENAME anum = PerlLIO_rename(tmps, tmps2); #else - if (!(anum = PerlLIO_stat(tmps, &PL_statbuf))) { + if (!(anum = PerlLIO_stat(tmps, &statbuf))) { if (same_dirent(tmps2, tmps)) /* can always rename to same name */ anum = 1; else { - if (PerlProc_geteuid() || PerlLIO_stat(tmps2, &PL_statbuf) < 0 || !S_ISDIR(PL_statbuf.st_mode)) + if (PerlProc_geteuid() || PerlLIO_stat(tmps2, &statbuf) < 0 || !S_ISDIR(statbuf.st_mode)) (void)UNLINK(tmps2); if (!(anum = link(tmps, tmps2))) anum = UNLINK(tmps); @@ -3771,20 +3781,16 @@ PP(pp_link) const char * const tmps = SvPV_nolen_const(TOPs); TAINT_PROPER(PL_op_desc[op_type]); result = -# if defined(HAS_LINK) -# if defined(HAS_SYMLINK) +# if defined(HAS_LINK) && defined(HAS_SYMLINK) /* Both present - need to choose which. */ (op_type == OP_LINK) ? PerlLIO_link(tmps, tmps2) : symlink(tmps, tmps2); -# else +# elif defined(HAS_LINK) /* Only have link, so calls to pp_symlink will have DIE()d above. */ PerlLIO_link(tmps, tmps2); -# endif -# else -# if defined(HAS_SYMLINK) +# elif defined(HAS_SYMLINK) /* Only have symlink, so calls to pp_link will have DIE()d above. */ symlink(tmps, tmps2); -# endif # endif } @@ -3818,8 +3824,7 @@ PP(pp_readlink) len = readlink(tmps, buf, sizeof(buf) - 1); if (len < 0) RETPUSHUNDEF; - if (len != -1) - buf[len] = '\0'; + buf[len] = '\0'; PUSHp(buf, len); RETURN; #else @@ -3898,7 +3903,8 @@ S_dooneliner(pTHX_ const char *cmd, const char *filename) return 0; } else { /* some mkdirs return no failure indication */ - anum = (PerlLIO_stat(save_filename, &PL_statbuf) >= 0); + Stat_t statbuf; + anum = (PerlLIO_stat(save_filename, &statbuf) >= 0); if (PL_op->op_type == OP_RMDIR) anum = !anum; if (anum) @@ -3990,9 +3996,8 @@ PP(pp_open_dir) IO * const io = GvIOn(gv); if ((IoIFP(io) || IoOFP(io))) - Perl_ck_warner_d(aTHX_ packWARN2(WARN_IO, WARN_DEPRECATED), - "Opening filehandle %"HEKf" also as a directory", - HEKfARG(GvENAME_HEK(gv)) ); + Perl_croak(aTHX_ "Cannot open %" HEKf " as a dirhandle: it is already open as a filehandle", + HEKfARG(GvENAME_HEK(gv))); if (IoDIRP(io)) PerlDir_close(IoDIRP(io)); if (!(IoDIRP(io) = PerlDir_open(dirname))) @@ -4019,14 +4024,14 @@ PP(pp_readdir) dSP; SV *sv; - const I32 gimme = GIMME_V; + const U8 gimme = GIMME_V; GV * const gv = MUTABLE_GV(POPs); const Direntry_t *dp; IO * const io = GvIOn(gv); if (!IoDIRP(io)) { Perl_ck_warner(aTHX_ packWARN(WARN_IO), - "readdir() attempted on invalid dirhandle %"HEKf, + "readdir() attempted on invalid dirhandle %" HEKf, HEKfARG(GvENAME_HEK(gv))); goto nope; } @@ -4076,7 +4081,7 @@ PP(pp_telldir) if (!IoDIRP(io)) { Perl_ck_warner(aTHX_ packWARN(WARN_IO), - "telldir() attempted on invalid dirhandle %"HEKf, + "telldir() attempted on invalid dirhandle %" HEKf, HEKfARG(GvENAME_HEK(gv))); goto nope; } @@ -4102,7 +4107,7 @@ PP(pp_seekdir) if (!IoDIRP(io)) { Perl_ck_warner(aTHX_ packWARN(WARN_IO), - "seekdir() attempted on invalid dirhandle %"HEKf, + "seekdir() attempted on invalid dirhandle %" HEKf, HEKfARG(GvENAME_HEK(gv))); goto nope; } @@ -4127,7 +4132,7 @@ PP(pp_rewinddir) if (!IoDIRP(io)) { Perl_ck_warner(aTHX_ packWARN(WARN_IO), - "rewinddir() attempted on invalid dirhandle %"HEKf, + "rewinddir() attempted on invalid dirhandle %" HEKf, HEKfARG(GvENAME_HEK(gv))); goto nope; } @@ -4151,7 +4156,7 @@ PP(pp_closedir) if (!IoDIRP(io)) { Perl_ck_warner(aTHX_ packWARN(WARN_IO), - "closedir() attempted on invalid dirhandle %"HEKf, + "closedir() attempted on invalid dirhandle %" HEKf, HEKfARG(GvENAME_HEK(gv))); goto nope; } @@ -4216,8 +4221,7 @@ PP(pp_fork) } PUSHi(childpid); RETURN; -#else -# if (defined(USE_ITHREADS) && defined(PERL_IMPLICIT_SYS)) || defined(__amigaos4__) +#elif (defined(USE_ITHREADS) && defined(PERL_IMPLICIT_SYS)) || defined(__amigaos4__) dSP; dTARGET; Pid_t childpid; @@ -4228,9 +4232,8 @@ PP(pp_fork) RETPUSHUNDEF; PUSHi(childpid); RETURN; -# else +#else DIE(aTHX_ PL_no_func, "fork"); -# endif #endif } @@ -4314,14 +4317,45 @@ PP(pp_system) int result; # endif + while (++MARK <= SP) { + SV *origsv = *MARK, *copysv; + STRLEN len; + char *pv; + SvGETMAGIC(origsv); +#if defined(WIN32) || defined(__VMS) + /* + * Because of a nasty platform-specific variation on the meaning + * of arguments to this op, we must preserve numeric arguments + * as numeric, not just retain the string value. + */ + if (SvNIOK(origsv) || SvNIOKp(origsv)) { + copysv = newSV_type(SVt_PVNV); + sv_2mortal(copysv); + if (SvPOK(origsv) || SvPOKp(origsv)) { + pv = SvPV_nomg(origsv, len); + sv_setpvn(copysv, pv, len); + SvPOK_off(copysv); + } + if (SvIOK(origsv) || SvIOKp(origsv)) + SvIV_set(copysv, SvIVX(origsv)); + if (SvNOK(origsv) || SvNOKp(origsv)) + SvNV_set(copysv, SvNVX(origsv)); + SvFLAGS(copysv) |= SvFLAGS(origsv) & + (SVf_IOK|SVf_NOK|SVf_POK|SVp_IOK|SVp_NOK|SVp_POK| + SVf_UTF8|SVf_IVisUV); + } else +#endif + { + pv = SvPV_nomg(origsv, len); + copysv = newSVpvn_flags(pv, len, + (SvFLAGS(origsv) & SVf_UTF8) | SVs_TEMP); + } + *MARK = copysv; + } + MARK = ORIGMARK; + if (TAINTING_get) { TAINT_ENV(); - while (++MARK <= SP) { - (void)SvPV_nolen_const(*MARK); /* stringify for taint check */ - if (TAINT_get) - break; - } - MARK = ORIGMARK; TAINT_PROPER("system"); } PERL_FLUSHALL_FOR_CHILD; @@ -4340,7 +4374,7 @@ PP(pp_system) sigset_t newset, oldset; #endif - if (PerlProc_pipe(pp) >= 0) + if (PerlProc_pipe_cloexec(pp) >= 0) did_pipes = 1; #ifdef __amigaos4__ amigaos_fork_set_userdata(aTHX_ @@ -4402,15 +4436,13 @@ PP(pp_system) (void)rsignal_restore(SIGQUIT, &qhand); #endif STATUS_NATIVE_CHILD_SET(result == -1 ? -1 : status); - do_execfree(); /* free any memory child malloced on fork */ SP = ORIGMARK; if (did_pipes) { int errkid; unsigned n = 0; - SSize_t n1; while (n < sizeof(int)) { - n1 = PerlLIO_read(pp[0], + const SSize_t n1 = PerlLIO_read(pp[0], (void*)(((char*)&errkid)+n), (sizeof(int)) - n); if (n1 <= 0) @@ -4439,13 +4471,8 @@ PP(pp_system) #ifdef HAS_SIGPROCMASK sigprocmask(SIG_SETMASK, &oldset, NULL); #endif - if (did_pipes) { + if (did_pipes) PerlLIO_close(pp[0]); -#if defined(HAS_FCNTL) && defined(F_SETFD) && defined(FD_CLOEXEC) - if (fcntl(pp[1], F_SETFD, FD_CLOEXEC) < 0) - RETPUSHUNDEF; -#endif - } if (PL_op->op_flags & OPf_STACKED) { SV * const really = *++MARK; value = (I32)do_aexec5(really, MARK, SP, pp[1], did_pipes); @@ -4482,7 +4509,6 @@ PP(pp_system) if (PL_statusvalue == -1) /* hint that value must be returned as is */ result = 1; STATUS_NATIVE_CHILD_SET(value); - do_execfree(); SP = ORIGMARK; XPUSHi(result ? value : STATUS_CURRENT); #endif /* !FORK or VMS or OS/2 */ @@ -4658,8 +4684,7 @@ PP(pp_tms) mPUSHn(((NV)timesbuf.tms_cstime)/(NV)PL_clocktick); } RETURN; -#else -# ifdef PERL_MICRO +#elif defined(PERL_MICRO) dSP; mPUSHn(0.0); EXTEND(SP, 4); @@ -4669,9 +4694,8 @@ PP(pp_tms) mPUSHn(0.0); } RETURN; -# else +#else DIE(aTHX_ "times not implemented"); -# endif #endif /* HAS_TIMES */ } @@ -4754,7 +4778,7 @@ PP(pp_gmtime) else { dTARGET; PUSHs(TARG); - Perl_sv_setpvf_mg(aTHX_ TARG, "%s %s %2d %02d:%02d:%02d %"IVdf, + Perl_sv_setpvf_mg(aTHX_ TARG, "%s %s %2d %02d:%02d:%02d %" IVdf, dayname[tmbuf.tm_wday], monname[tmbuf.tm_mon], tmbuf.tm_mday, @@ -4819,7 +4843,6 @@ PP(pp_alarm) PP(pp_sleep) { dSP; dTARGET; - I32 duration; Time_t lasttime; Time_t when; @@ -4827,13 +4850,13 @@ PP(pp_sleep) if (MAXARG < 1 || (!TOPs && !POPs)) PerlProc_pause(); else { - duration = POPi; + const I32 duration = POPi; if (duration < 0) { /* diag_listed_as: %s() with negative argument */ Perl_ck_warner_d(aTHX_ packWARN(WARN_MISC), "sleep() with negative argument"); SETERRNO(EINVAL, LIB_INVARG); - XPUSHi(0); + XPUSHs(&PL_sv_zero); RETURN; } else { PerlProc_sleep((unsigned int)duration); @@ -4927,9 +4950,7 @@ S_space_join_names_mortal(pTHX_ char *const *array) { SV *target; - PERL_ARGS_ASSERT_SPACE_JOIN_NAMES_MORTAL; - - if (*array) { + if (array && *array) { target = newSVpvs_flags("", SVs_TEMP); while (1) { sv_catpv(target, *array); @@ -5520,30 +5541,24 @@ PP(pp_gpwent) * but we are accursed by our history, alas. --jhi. */ # ifdef PWCHANGE mPUSHi(pwent->pw_change); -# else -# ifdef PWQUOTA +# elif defined(PWQUOTA) mPUSHi(pwent->pw_quota); -# else -# ifdef PWAGE +# elif defined(PWAGE) mPUSHs(newSVpv(pwent->pw_age, 0)); -# else +# else /* I think that you can never get this compiled, but just in case. */ PUSHs(sv_mortalcopy(&PL_sv_no)); -# endif -# endif # endif /* pw_class and pw_comment are mutually exclusive--. * see the above note for pw_change, pw_quota, and pw_age. */ # ifdef PWCLASS mPUSHs(newSVpv(pwent->pw_class, 0)); -# else -# ifdef PWCOMMENT +# elif defined(PWCOMMENT) mPUSHs(newSVpv(pwent->pw_comment, 0)); -# else +# else /* I think that you can never get this compiled, but just in case. */ PUSHs(sv_mortalcopy(&PL_sv_no)); -# endif # endif # ifdef PWGECOS