Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitbe2700f

Browse files
[Process] Strong args escaping on Windows + deprecate compat settings
1 parent60d7d43 commitbe2700f

File tree

12 files changed

+241
-84
lines changed

12 files changed

+241
-84
lines changed

‎.travis.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ script:
9696
-if [[ ! $deps && ! $PHP = hhvm* ]]; then echo "$COMPONENTS" | parallel --gnu '$PHPUNIT --exclude-group tty,benchmark,intl-data {}'"$REPORT"; fi
9797
-if [[ ! $deps && ! $PHP = hhvm* ]]; then echo -e "\\nRunning tests requiring tty"; $PHPUNIT --group tty; fi
9898
-if [[ ! $deps && $PHP = hhvm* ]]; then $PHPUNIT --exclude-group benchmark,intl-data; fi
99-
-if [[ ! $deps && $PHP = ${MIN_PHP%.*} ]]; then echo -e "1\\n0" | xargs -I{} sh -c 'echo "\\nPHP --enable-sigchild enhanced={}" && ENHANCE_SIGCHLD={} php-$MIN_PHP/sapi/cli/php .phpunit/phpunit-4.8/phpunit --colors=always src/Symfony/Component/Process/'; fi
99+
-if [[ ! $deps && $PHP = ${MIN_PHP%.*} ]]; then echo -e "1\\n0" | xargs -I{} sh -c 'echo "\\nPHP --enable-sigchild enhanced={}" &&SYMFONY_DEPRECATIONS_HELPER=weakENHANCE_SIGCHLD={} php-$MIN_PHP/sapi/cli/php .phpunit/phpunit-4.8/phpunit --colors=always src/Symfony/Component/Process/'; fi
100100
-if [[ $deps = high ]]; then echo "$COMPONENTS" | parallel --gnu -j10% 'cd {}; composer update --no-progress --ansi; $PHPUNIT --exclude-group tty,benchmark,intl-data'$LEGACY"$REPORT"; fi
101101
-if [[ $deps = low ]]; then echo "$COMPONENTS" | parallel --gnu -j10% 'cd {}; composer update --no-progress --ansi --prefer-lowest --prefer-stable; $PHPUNIT --exclude-group tty,benchmark,intl-data'"$REPORT"; fi
102102
# Test the PhpUnit bridge using the original phpunit script

‎UPGRADE-3.3.md‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,17 @@ HttpKernel
4141
* The`Psr6CacheClearer::addPool()` method has been deprecated. Pass an array of pools indexed
4242
by name to the constructor instead.
4343

44+
Process
45+
-------
46+
47+
* On Windows,`!VAR!` expansion inside escaped arguments is deprecated.
48+
49+
* Not inheriting environment variables is deprecated.
50+
51+
* Configuring`proc_open()` options is deprecated.
52+
53+
* Configuring Windows and sigchild compatibility is deprecated - they will be always enabled in 4.0.
54+
4455
Security
4556
--------
4657

‎UPGRADE-4.0.md‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,17 @@ HttpKernel
203203
* The`Psr6CacheClearer::addPool()` method has been removed. Pass an array of pools indexed
204204
by name to the constructor instead.
205205

206+
Process
207+
-------
208+
209+
* On Windows,`!VAR!` variables are not expanded anymore in escaped arguments.
210+
211+
* Environment variables are always inherited in sub-processes.
212+
213+
* Configuring`proc_open()` options has been removed.
214+
215+
* Configuring Windows and sigchild compatibility is not possible anymore - they are always enabled.
216+
206217
Security
207218
--------
208219

‎src/Symfony/Component/Console/Tests/Helper/ProcessHelperTest.php‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
useSymfony\Component\Console\Output\StreamOutput;
1717
useSymfony\Component\Console\Helper\ProcessHelper;
1818
useSymfony\Component\Process\Process;
19+
useSymfony\Component\Process\ProcessUtils;
1920

2021
class ProcessHelperTestextends \PHPUnit_Framework_TestCase
2122
{
@@ -84,7 +85,9 @@ public function provideCommandsAndOutput()
8485

8586
$errorMessage ='An error occurred';
8687
if ('\\' ===DIRECTORY_SEPARATOR) {
87-
$successOutputProcessDebug =str_replace("'",'"',$successOutputProcessDebug);
88+
$args =array('php','-r','echo 42;');
89+
$args =array_map(array(ProcessUtils::class,'escapeArgument'),$args);
90+
$successOutputProcessDebug =str_replace("'php' '-r' 'echo 42;'",implode('',$args),$successOutputProcessDebug);
8891
}
8992

9093
returnarray(

‎src/Symfony/Component/Process/CHANGELOG.md‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
CHANGELOG
22
=========
33

4+
3.3.0
5+
-----
6+
7+
* deprecated`!VAR!` expansion inside escaped arguments
8+
* deprecated not inheriting environment variables
9+
* deprecated configuring`proc_open()` options
10+
* deprecated configuring enhanced Windows compatibility
11+
* deprecated configuring enhanced sigchild compatibility
12+
413
2.5.0
514
-----
615

‎src/Symfony/Component/Process/PhpProcess.php‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class PhpProcess extends Process
3333
* @param int $timeout The timeout in seconds
3434
* @param array $options An array of options for proc_open
3535
*/
36-
publicfunction__construct($script,$cwd =null,array$env =null,$timeout =60,array$options =array())
36+
publicfunction__construct($script,$cwd =null,array$env =null,$timeout =60,array$options =null)
3737
{
3838
$executableFinder =newPhpExecutableFinder();
3939
if (false ===$php =$executableFinder->find()) {
@@ -52,6 +52,9 @@ public function __construct($script, $cwd = null, array $env = null, $timeout =
5252
// command with exec
5353
$php ='exec'.$php;
5454
}
55+
if (null !==$options) {
56+
@trigger_error(sprintf('The $options parameter of the %s constructor is deprecated since version 3.3 and will be removed in 4.0.',__CLASS__),E_USER_DEPRECATED);
57+
}
5558

5659
parent::__construct($php,$cwd,$env,$script,$timeout,$options);
5760
}

‎src/Symfony/Component/Process/Process.php‎

Lines changed: 99 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ class Process implements \IteratorAggregate
5858
private$lastOutputTime;
5959
private$timeout;
6060
private$idleTimeout;
61-
private$options;
61+
private$options =array('suppress_errors' =>true);
6262
private$exitcode;
6363
private$fallbackStatus =array();
6464
private$processInformation;
@@ -145,7 +145,7 @@ class Process implements \IteratorAggregate
145145
*
146146
* @throws RuntimeException When proc_open is not installed
147147
*/
148-
publicfunction__construct($commandline,$cwd =null,array$env =null,$input =null,$timeout =60,array$options =array())
148+
publicfunction__construct($commandline,$cwd =null,array$env =null,$input =null,$timeout =60,array$options =null)
149149
{
150150
if (!function_exists('proc_open')) {
151151
thrownewRuntimeException('The Process class relies on proc_open, which is not available on your PHP installation.');
@@ -171,7 +171,10 @@ public function __construct($commandline, $cwd = null, array $env = null, $input
171171
$this->pty =false;
172172
$this->enhanceWindowsCompatibility =true;
173173
$this->enhanceSigchildCompatibility ='\\' !==DIRECTORY_SEPARATOR &&$this->isSigchildEnabled();
174-
$this->options =array_replace(array('suppress_errors' =>true,'binary_pipes' =>true),$options);
174+
if (null !==$options) {
175+
@trigger_error(sprintf('The $options parameter of the %s constructor is deprecated since version 3.3 and will be removed in 4.0.',__CLASS__),E_USER_DEPRECATED);
176+
$this->options =array_replace($this->options,$options);
177+
}
175178
}
176179

177180
publicfunction__destruct()
@@ -268,47 +271,40 @@ public function start(callable $callback = null)
268271
$descriptors =$this->getDescriptors();
269272

270273
$commandline =$this->commandline;
271-
$envline ='';
272274

273-
if (null !==$this->env &&$this->inheritEnv) {
274-
if ('\\' ===DIRECTORY_SEPARATOR && !empty($this->options['bypass_shell']) && !$this->enhanceWindowsCompatibility) {
275-
thrownewLogicException('The "bypass_shell" option must be false to inherit environment variables while enhanced Windows compatibility is off');
276-
}
277-
$env ='\\' ===DIRECTORY_SEPARATOR ?'(SET %s)&&' :'export %s;';
278-
foreach ($this->envas$k =>$v) {
279-
$envline .=sprintf($env, ProcessUtils::escapeArgument("$k=$v"));
275+
$env =$this->env;
276+
$envBackup =array();
277+
if (null !==$env &&$this->inheritEnv) {
278+
foreach ($envas$k =>$v) {
279+
$envBackup[$k] =getenv($v);
280+
putenv(false ===$v ||null ===$v ?$k :"$k=$v");
280281
}
281282
$env =null;
282-
}else {
283-
$env =$this->env;
283+
}elseif (null !==$env) {
284+
@trigger_error(sprintf('Not inheriting environment variables is deprecated since Symfony 3.3 and will always happen in 4.0. Set "Process::inheritEnvironmentVariables()" to true instead.',__METHOD__),E_USER_DEPRECATED);
284285
}
285286
if ('\\' ===DIRECTORY_SEPARATOR &&$this->enhanceWindowsCompatibility) {
286-
$commandline ='cmd /V:ON /E:ON /D /C "('.$envline.$commandline.')';
287-
foreach ($this->processPipes->getFiles()as$offset =>$filename) {
288-
$commandline .=''.$offset.'>'.ProcessUtils::escapeArgument($filename);
289-
}
290-
$commandline .='"';
291-
292-
if (!isset($this->options['bypass_shell'])) {
293-
$this->options['bypass_shell'] =true;
294-
}
287+
$this->options['bypass_shell'] =true;
288+
$commandline =$this->prepareWindowsCommandLine($commandline,$envBackup);
295289
}elseif (!$this->useFileHandles &&$this->enhanceSigchildCompatibility &&$this->isSigchildEnabled()) {
296290
// last exit code is output on the fourth pipe and caught to work around --enable-sigchild
297291
$descriptors[3] =array('pipe','w');
298292

299293
// See https://unix.stackexchange.com/questions/71205/background-process-pipe-input
300-
$commandline =$envline.'{ ('.$this->commandline.') <&3 3<&- 3>/dev/null & } 3<&0;';
294+
$commandline ='{ ('.$this->commandline.') <&3 3<&- 3>/dev/null & } 3<&0;';
301295
$commandline .='pid=$!; echo $pid >&3; wait $pid; code=$?; echo $code >&3; exit $code';
302296

303297
// Workaround for the bug, when PTS functionality is enabled.
304298
// @see : https://bugs.php.net/69442
305299
$ptsWorkaround =fopen(__FILE__,'r');
306-
}elseif ('' !==$envline) {
307-
$commandline =$envline.$commandline;
308300
}
309301

310302
$this->process =proc_open($commandline,$descriptors,$this->processPipes->pipes,$this->cwd,$env,$this->options);
311303

304+
foreach ($envBackupas$k =>$v) {
305+
putenv(false ===$v ?$k :"$k=$v");
306+
}
307+
312308
if (!is_resource($this->process)) {
313309
thrownewRuntimeException('Unable to launch a new process.');
314310
}
@@ -1089,6 +1085,7 @@ public function getEnv()
10891085
*
10901086
* An environment variable value should be a string.
10911087
* If it is an array, the variable is ignored.
1088+
* If it is false, it will be removed when env vars are otherwise inherited.
10921089
*
10931090
* That happens in PHP when 'argv' is registered into
10941091
* the $_ENV array for instance.
@@ -1106,7 +1103,7 @@ public function setEnv(array $env)
11061103

11071104
$this->env =array();
11081105
foreach ($envas$key =>$value) {
1109-
$this->env[$key] =(string)$value;
1106+
$this->env[$key] =$value;
11101107
}
11111108

11121109
return$this;
@@ -1148,9 +1145,13 @@ public function setInput($input)
11481145
* Gets the options for proc_open.
11491146
*
11501147
* @return array The current options
1148+
*
1149+
* @deprecated since version 3.3, to be removed in 4.0.
11511150
*/
11521151
publicfunctiongetOptions()
11531152
{
1153+
@trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0.',__METHOD__),E_USER_DEPRECATED);
1154+
11541155
return$this->options;
11551156
}
11561157

@@ -1160,9 +1161,13 @@ public function getOptions()
11601161
* @param array $options The new options
11611162
*
11621163
* @return self The current Process instance
1164+
*
1165+
* @deprecated since version 3.3, to be removed in 4.0.
11631166
*/
11641167
publicfunctionsetOptions(array$options)
11651168
{
1169+
@trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0.',__METHOD__),E_USER_DEPRECATED);
1170+
11661171
$this->options =$options;
11671172

11681173
return$this;
@@ -1174,9 +1179,13 @@ public function setOptions(array $options)
11741179
* This is true by default.
11751180
*
11761181
* @return bool
1182+
*
1183+
* @deprecated since version 3.3, to be removed in 4.0. Enhanced Windows compatibility will always be enabled.
11771184
*/
11781185
publicfunctiongetEnhanceWindowsCompatibility()
11791186
{
1187+
@trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Enhanced Windows compatibility will always be enabled.',__METHOD__),E_USER_DEPRECATED);
1188+
11801189
return$this->enhanceWindowsCompatibility;
11811190
}
11821191

@@ -1186,9 +1195,13 @@ public function getEnhanceWindowsCompatibility()
11861195
* @param bool $enhance
11871196
*
11881197
* @return self The current Process instance
1198+
*
1199+
* @deprecated since version 3.3, to be removed in 4.0. Enhanced Windows compatibility will always be enabled.
11891200
*/
11901201
publicfunctionsetEnhanceWindowsCompatibility($enhance)
11911202
{
1203+
@trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Enhanced Windows compatibility will always be enabled.',__METHOD__),E_USER_DEPRECATED);
1204+
11921205
$this->enhanceWindowsCompatibility = (bool)$enhance;
11931206

11941207
return$this;
@@ -1198,9 +1211,13 @@ public function setEnhanceWindowsCompatibility($enhance)
11981211
* Returns whether sigchild compatibility mode is activated or not.
11991212
*
12001213
* @return bool
1214+
*
1215+
* @deprecated since version 3.3, to be removed in 4.0. Sigchild compatibility will always be enabled.
12011216
*/
12021217
publicfunctiongetEnhanceSigchildCompatibility()
12031218
{
1219+
@trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Sigchild compatibility will always be enabled.',__METHOD__),E_USER_DEPRECATED);
1220+
12041221
return$this->enhanceSigchildCompatibility;
12051222
}
12061223

@@ -1214,9 +1231,13 @@ public function getEnhanceSigchildCompatibility()
12141231
* @param bool $enhance
12151232
*
12161233
* @return self The current Process instance
1234+
*
1235+
* @deprecated since version 3.3, to be removed in 4.0.
12171236
*/
12181237
publicfunctionsetEnhanceSigchildCompatibility($enhance)
12191238
{
1239+
@trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Sigchild compatibility will always be enabled.',__METHOD__),E_USER_DEPRECATED);
1240+
12201241
$this->enhanceSigchildCompatibility = (bool)$enhance;
12211242

12221243
return$this;
@@ -1231,6 +1252,10 @@ public function setEnhanceSigchildCompatibility($enhance)
12311252
*/
12321253
publicfunctioninheritEnvironmentVariables($inheritEnv =true)
12331254
{
1255+
if (!$inheritEnv) {
1256+
@trigger_error(sprintf('Not inheriting environment variables is deprecated since Symfony 3.3 and will always happen in 4.0. Set "Process::inheritEnvironmentVariables()" to true instead.',__METHOD__),E_USER_DEPRECATED);
1257+
}
1258+
12341259
$this->inheritEnv = (bool)$inheritEnv;
12351260

12361261
return$this;
@@ -1240,9 +1265,13 @@ public function inheritEnvironmentVariables($inheritEnv = true)
12401265
* Returns whether environment variables will be inherited or not.
12411266
*
12421267
* @return bool
1268+
*
1269+
* @deprecated since version 3.3, to be removed in 4.0. Environment variables will always be inherited.
12431270
*/
12441271
publicfunctionareEnvironmentVariablesInherited()
12451272
{
1273+
@trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Environment variables will always be inherited.',__METHOD__),E_USER_DEPRECATED);
1274+
12461275
return$this->inheritEnv;
12471276
}
12481277

@@ -1561,6 +1590,50 @@ private function doSignal($signal, $throwException)
15611590
returntrue;
15621591
}
15631592

1593+
privatefunctionprepareWindowsCommandLine($cmd,array &$envBackup)
1594+
{
1595+
$uid =uniqid('',true);
1596+
$varCount =0;
1597+
$varCache =array();
1598+
$cmd =preg_replace_callback(
1599+
'/"(
1600+
[^"%!^]*+
1601+
(?:
1602+
(?: !LF! | "(?:\^[%!^])?+" )
1603+
[^"%!^]*+
1604+
)++
1605+
)"/x',
1606+
function ($m)use (&$envBackup, &$varCache, &$varCount,$uid) {
1607+
if (isset($varCache[$m[0]])) {
1608+
return$varCache[$m[0]];
1609+
}
1610+
if (false !==strpos($value =$m[1],"\0")) {
1611+
$value =str_replace("\0",'?',$value);
1612+
}
1613+
if (false ===strpbrk($value,"\"%!\n")) {
1614+
return'"'.$value.'"';
1615+
}
1616+
1617+
$value =str_replace(array('!LF!','"^!"','"^%"','"^^"','""'),array("\n",'!','%','^','"'),$value);
1618+
$value =preg_replace('/(\\\\*)"/','$1$1\\"',$value);
1619+
1620+
$var =$uid.++$varCount;
1621+
putenv("$var=\"$value\"");
1622+
$envBackup[$var] =false;
1623+
1624+
return$varCache[$m[0]] ='!'.$var.'!';
1625+
},
1626+
$cmd
1627+
);
1628+
1629+
$cmd ='cmd /V:ON /E:ON /D /C ('.str_replace("\n",'',$cmd).')';
1630+
foreach ($this->processPipes->getFiles()as$offset =>$filename) {
1631+
$cmd .=''.$offset.'>"'.$filename.'"';
1632+
}
1633+
1634+
return$cmd;
1635+
}
1636+
15641637
/**
15651638
* Ensures the process is running or terminated, throws a LogicException if the process has a not started.
15661639
*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp