This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Skip dist/ExtUtils-Install/t/InstallWithMM.t when cross-compiling.
[perl5.git] / doio.c
diff --git a/doio.c b/doio.c
index 56c1019..39cbf6d 100644 (file)
--- a/doio.c
+++ b/doio.c
@@ -206,6 +206,8 @@ Perl_do_openn(pTHX_ GV *gv, const char *oname, I32 len, int as_raw,
            *--tend = '\0';
 
        if (num_svs) {
+            const char *p;
+            STRLEN nlen = 0;
            /* New style explicit name, type is just mode and layer info */
 #ifdef USE_STDIO
            if (SvROK(*svp) && !strchr(oname,'&')) {
@@ -216,8 +218,13 @@ Perl_do_openn(pTHX_ GV *gv, const char *oname, I32 len, int as_raw,
                goto say_false;
            }
 #endif /* USE_STDIO */
-           name = (SvOK(*svp) || SvGMAGICAL(*svp)) ?
-                       savesvpv (*svp) : savepvs ("");
+            p = (SvOK(*svp) || SvGMAGICAL(*svp)) ? SvPV(*svp, nlen) : NULL;
+
+           if (p && !IS_SAFE_PATHNAME(p, nlen, "open"))
+                goto say_false;
+
+           name = p ? savepvn(p, nlen) : savepvs("");
+
            SAVEFREEPV(name);
        }
        else {
@@ -1045,10 +1052,6 @@ Perl_do_tell(pTHX_ GV *gv)
     PERL_ARGS_ASSERT_DO_TELL;
 
     if (io && (fp = IoIFP(io))) {
-#ifdef ULTRIX_STDIO_BOTCH
-       if (PerlIO_eof(fp))
-           (void)PerlIO_seek(fp, 0L, 2);       /* ultrix 1.2 workaround */
-#endif
        return PerlIO_tell(fp);
     }
     report_evil_fh(gv);
@@ -1064,10 +1067,6 @@ Perl_do_seek(pTHX_ GV *gv, Off_t pos, int whence)
     PerlIO *fp;
 
     if (io && (fp = IoIFP(io))) {
-#ifdef ULTRIX_STDIO_BOTCH
-       if (PerlIO_eof(fp))
-           (void)PerlIO_seek(fp, 0L, 2);       /* ultrix 1.2 workaround */
-#endif
        return PerlIO_seek(fp, pos, whence) >= 0;
     }
     report_evil_fh(gv);
@@ -1337,14 +1336,16 @@ Perl_my_lstat_flags(pTHX_ const U32 flags)
     dSP;
     const char *file;
     SV* const sv = TOPs;
+    bool isio = FALSE;
     if (PL_op->op_flags & OPf_REF) {
        if (cGVOP_gv == PL_defgv) {
            if (PL_laststype != OP_LSTAT)
-               Perl_croak(aTHX_ no_prev_lstat);
+               Perl_croak(aTHX_ "%s", no_prev_lstat);
            return PL_laststatval;
        }
        PL_laststatval = -1;
        if (ckWARN(WARN_IO)) {
+           /* diag_listed_as: Use of -l on filehandle%s */
            Perl_warner(aTHX_ packWARN(WARN_IO),
                             "Use of -l on filehandle %"HEKf,
                              HEKfARG(GvENAME_HEK(cGVOP_gv)));
@@ -1354,15 +1355,28 @@ Perl_my_lstat_flags(pTHX_ const U32 flags)
     if ((PL_op->op_private & (OPpFT_STACKED|OPpFT_AFTER_t))
             == OPpFT_STACKED) {
       if (PL_laststype != OP_LSTAT)
-       Perl_croak(aTHX_ no_prev_lstat);
+       Perl_croak(aTHX_ "%s", no_prev_lstat);
       return PL_laststatval;
     }
 
     PL_laststype = OP_LSTAT;
     PL_statgv = NULL;
-    if (SvROK(sv) && isGV_with_GP(SvRV(sv)) && ckWARN(WARN_IO)) {
-        Perl_warner(aTHX_ packWARN(WARN_IO), "Use of -l on filehandle %s",
-           GvENAME((const GV *)SvRV(sv)));
+    if ( (  (SvROK(sv) && (  isGV_with_GP(SvRV(sv))
+                          || (isio = SvTYPE(SvRV(sv)) == SVt_PVIO)  )
+            )
+         || isGV_with_GP(sv)
+         )
+      && ckWARN(WARN_IO)) {
+        if (isio)
+           /* diag_listed_as: Use of -l on filehandle%s */
+            Perl_warner(aTHX_ packWARN(WARN_IO),
+                             "Use of -l on filehandle");
+        else
+           /* diag_listed_as: Use of -l on filehandle%s */
+            Perl_warner(aTHX_ packWARN(WARN_IO),
+                             "Use of -l on filehandle %"HEKf,
+                              GvENAME_HEK((const GV *)
+                                          (SvROK(sv) ? SvRV(sv) : sv)));
     }
     file = SvPV_flags_const_nolen(sv, flags);
     sv_setpv(PL_statname,file);
@@ -1381,7 +1395,7 @@ S_exec_failed(pTHX_ const char *cmd, int fd, int do_report)
        Perl_warner(aTHX_ packWARN(WARN_EXEC), "Can't exec \"%s\": %s",
                    cmd, Strerror(e));
     if (do_report) {
-       PerlLIO_write(fd, (void*)&e, sizeof(int));
+       (void)PerlLIO_write(fd, (void*)&e, sizeof(int));
        PerlLIO_close(fd);
     }
 }
@@ -1589,6 +1603,8 @@ Perl_apply(pTHX_ I32 type, SV **mark, SV **sp)
 
     PERL_ARGS_ASSERT_APPLY;
 
+    PERL_UNUSED_VAR(what); /* may not be used depending on compile options */
+
     /* Doing this ahead of the switch statement preserves the old behaviour,
        where attempting to use kill as a taint test test would fail on
        platforms where kill was not defined.  */
@@ -1641,10 +1657,12 @@ Perl_apply(pTHX_ I32 type, SV **mark, SV **sp)
                    }
                }
                else {
-                   const char *name = SvPV_nomg_const_nolen(*mark);
+                   const char *name = SvPV_nomg_const(*mark, len);
                    APPLY_TAINT_PROPER();
-                   if (PerlLIO_chmod(name, val))
-                       tot--;
+                    if (!IS_SAFE_PATHNAME(name, len, "chmod") ||
+                        PerlLIO_chmod(name, val)) {
+                        tot--;
+                    }
                }
            }
        }
@@ -1675,10 +1693,12 @@ Perl_apply(pTHX_ I32 type, SV **mark, SV **sp)
                    }
                }
                else {
-                   const char *name = SvPV_nomg_const_nolen(*mark);
+                   const char *name = SvPV_nomg_const(*mark, len);
                    APPLY_TAINT_PROPER();
-                   if (PerlLIO_chown(name, val, val2))
+                    if (!IS_SAFE_PATHNAME(name, len, "chown") ||
+                        PerlLIO_chown(name, val, val2)) {
                        tot--;
+                    }
                }
            }
        }
@@ -1776,9 +1796,12 @@ nothing in the core.
        APPLY_TAINT_PROPER();
        tot = sp - mark;
        while (++mark <= sp) {
-           s = SvPV_nolen_const(*mark);
+           s = SvPV_const(*mark, len);
            APPLY_TAINT_PROPER();
-           if (PerlProc_geteuid() || PL_unsafe) {
+           if (!IS_SAFE_PATHNAME(s, len, "unlink")) {
+                tot--;
+            }
+           else if (PerlProc_geteuid() || PL_unsafe) {
                if (UNLINK(s))
                    tot--;
            }
@@ -1854,8 +1877,12 @@ nothing in the core.
                    }
                }
                else {
-                   const char * const name = SvPV_nomg_const_nolen(*mark);
+                   const char * const name = SvPV_nomg_const(*mark, len);
                    APPLY_TAINT_PROPER();
+                   if (!IS_SAFE_PATHNAME(name, len, "utime")) {
+                        tot--;
+                    }
+                    else
 #ifdef HAS_FUTIMES
                    if (utimes(name, (struct timeval *)utbufp))
 #else
@@ -2192,10 +2219,8 @@ Perl_do_msgrcv(pTHX_ SV **mark, SV **sp)
     if (ret >= 0) {
        SvCUR_set(mstr, sizeof(long)+ret);
        *SvEND(mstr) = '\0';
-#ifndef INCOMPLETE_TAINTS
        /* who knows who has been playing with this message? */
        SvTAINTED_on(mstr);
-#endif
     }
     return ret;
 #else
@@ -2302,10 +2327,8 @@ Perl_do_shmio(pTHX_ I32 optype, SV **mark, SV **sp)
        SvCUR_set(mstr, msize);
        *SvEND(mstr) = '\0';
        SvSETMAGIC(mstr);
-#ifndef INCOMPLETE_TAINTS
        /* who knows who has been playing with this shared memory? */
        SvTAINTED_on(mstr);
-#endif
     }
     else {
        STRLEN len;
@@ -2345,9 +2368,14 @@ Perl_start_glob (pTHX_ SV *tmpglob, IO *io)
     dVAR;
     SV * const tmpcmd = newSV(0);
     PerlIO *fp;
+    STRLEN len;
+    const char *s = SvPV(tmpglob, len);
 
     PERL_ARGS_ASSERT_START_GLOB;
 
+    if (!IS_SAFE_SYSCALL(s, len, "pattern", "glob"))
+        return NULL;
+
     ENTER;
     SAVEFREESV(tmpcmd);
 #ifdef VMS /* expand the wildcards right here, rather than opening a pipe, */
@@ -2407,6 +2435,12 @@ Perl_vms_start_glob
     fp = IoIFP(io);
 #endif /* !VMS */
     LEAVE;
+
+    if (!fp && ckWARN(WARN_GLOB)) {
+        Perl_warner(aTHX_ packWARN(WARN_GLOB), "glob failed (can't start child: %s)",
+                    Strerror(errno));
+    }
+
     return fp;
 }