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