f6ea51
From 3e6e57e89f298f450cbe14c61609f08fc01bf233 Mon Sep 17 00:00:00 2001
f6ea51
From: Zefram <zefram@fysh.org>
f6ea51
Date: Sat, 16 Dec 2017 05:33:20 +0000
f6ea51
Subject: [PATCH] perform system() arg processing before fork
f6ea51
MIME-Version: 1.0
f6ea51
Content-Type: text/plain; charset=UTF-8
f6ea51
Content-Transfer-Encoding: 8bit
f6ea51
f6ea51
A lot of things can happen when stringifying an argument list: side
f6ea51
effects, warnings, exceptions.  In the case of system(), these effects
f6ea51
should happen in the context of the parent process.  The stringification
f6ea51
can also depend on which process it happens in, as in the case of
f6ea51
$$, and in that case it should also happen in the parent process.
f6ea51
Therefore reduce the argument scalars to strings first thing in pp_system.
f6ea51
Fixes [perl #121105].
f6ea51
f6ea51
Petr Písař: Ported to 5.26.2-RC1 from
f6ea51
64def2aeaeb63f92dadc6dfa33486c1d7b311963.
f6ea51
f6ea51
Signed-off-by: Petr Písař <ppisar@redhat.com>
f6ea51
---
f6ea51
 pp_sys.c    | 16 ++++++++++------
f6ea51
 t/op/exec.t | 15 ++++++++++++++-
f6ea51
 2 files changed, 24 insertions(+), 7 deletions(-)
f6ea51
f6ea51
diff --git a/pp_sys.c b/pp_sys.c
f6ea51
index 87961f1..07e552a 100644
f6ea51
--- a/pp_sys.c
f6ea51
+++ b/pp_sys.c
f6ea51
@@ -4375,14 +4375,18 @@ PP(pp_system)
f6ea51
     int result;
f6ea51
 # endif
f6ea51
 
f6ea51
+    while (++MARK <= SP) {
f6ea51
+	SV *origsv = *MARK;
f6ea51
+	STRLEN len;
f6ea51
+	char *pv;
f6ea51
+	pv = SvPV(origsv, len);
f6ea51
+	*MARK = newSVpvn_flags(pv, len,
f6ea51
+		    (SvFLAGS(origsv) & SVf_UTF8) | SVs_TEMP);
f6ea51
+    }
f6ea51
+    MARK = ORIGMARK;
f6ea51
+
f6ea51
     if (TAINTING_get) {
f6ea51
 	TAINT_ENV();
f6ea51
-	while (++MARK <= SP) {
f6ea51
-	    (void)SvPV_nolen_const(*MARK);      /* stringify for taint check */
f6ea51
-	    if (TAINT_get)
f6ea51
-		break;
f6ea51
-	}
f6ea51
-	MARK = ORIGMARK;
f6ea51
 	TAINT_PROPER("system");
f6ea51
     }
f6ea51
     PERL_FLUSHALL_FOR_CHILD;
f6ea51
diff --git a/t/op/exec.t b/t/op/exec.t
f6ea51
index 237388b..e29de82 100644
f6ea51
--- a/t/op/exec.t
f6ea51
+++ b/t/op/exec.t
f6ea51
@@ -36,7 +36,7 @@ $ENV{LANGUAGE} = 'C';		# Ditto in GNU.
f6ea51
 my $Is_VMS   = $^O eq 'VMS';
f6ea51
 my $Is_Win32 = $^O eq 'MSWin32';
f6ea51
 
f6ea51
-plan(tests => 34);
f6ea51
+plan(tests => 37);
f6ea51
 
f6ea51
 my $Perl = which_perl();
f6ea51
 
f6ea51
@@ -177,6 +177,19 @@ TODO: {
f6ea51
         "exec failure doesn't terminate process");
f6ea51
 }
f6ea51
 
f6ea51
+package CountRead {
f6ea51
+    sub TIESCALAR { bless({ n => 0 }, $_[0]) }
f6ea51
+    sub FETCH { ++$_[0]->{n} }
f6ea51
+}
f6ea51
+my $cr;
f6ea51
+tie $cr, "CountRead";
f6ea51
+is system($^X, "-e", "exit(\$ARGV[0] eq '1' ? 0 : 1)", $cr), 0,
f6ea51
+    "system args have magic processed exactly once";
f6ea51
+is tied($cr)->{n}, 1, "system args have magic processed before fork";
f6ea51
+
f6ea51
+is system($^X, "-e", "exit(\$ARGV[0] eq \$ARGV[1] ? 0 : 1)", "$$", $$), 0,
f6ea51
+    "system args have magic processed before fork";
f6ea51
+
f6ea51
 my $test = curr_test();
f6ea51
 exec $Perl, '-le', qq{${quote}print 'ok $test - exec PROG, LIST'${quote}};
f6ea51
 fail("This should never be reached if the exec() worked");
f6ea51
-- 
f6ea51
2.14.3
f6ea51