r113688 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r113687‎ | r113688 | r113689 >
Date:00:05, 13 March 2012
Author:aaron
Status:reverted (Comments)
Tags:
Comment:
Made wfShellMaintenanceCmd() not totally broken due to excess shell escaping.
Modified paths:
  • /trunk/phase3/includes/GlobalFunctions.php (modified) (history)

Diff [purge]

Index: trunk/phase3/includes/GlobalFunctions.php
@@ -2929,8 +2929,8 @@
29302930 $cmd[] = $options['wrapper'];
29312931 }
29322932 $cmd[] = $script;
2933 - // Escape each parameter for shell
2934 - return implode( " ", array_map( 'wfEscapeShellArg', array_merge( $cmd, $parameters ) ) );
 2933+ // Build up the full command, shell escaping each parameter
 2934+ return implode( ' ', array_merge( $cmd, array_map( 'wfEscapeShellArg', $parameters ) ) );
29352935 }
29362936
29372937 /**

Follow-up revisions

RevisionCommit summaryAuthorDate
r113691r113688: updated test assertionsaaron00:18, 13 March 2012
r114162Reverted r113688, r113691 per CR and filed #61440 upstream.aaron18:28, 19 March 2012

Comments

#Comment by Brion VIBBER (talk | contribs)   21:14, 13 March 2012

Offhand that doesn't look excess to me; if $wgPhpCli is in a directory with a space for instance, you need to be quoting that.

#Comment by Aaron Schulz (talk | contribs)   21:28, 13 March 2012

I'm kind of assuming the variable would be set to deal with that. If it is escaped, it needs to be done correctly. I wasted some good time trying to use this function and figure out why the shell call kept failing.

#Comment by Brion VIBBER (talk | contribs)   21:29, 13 March 2012

The variable should probably not assume that it's pre-escaped; other paths are not.

Why's it failing for you?

#Comment by Awjrichards (talk | contribs)   23:26, 16 March 2012

Brion is right. What were you doing that was causing failure? Were you using a $wgPhpCli with a space in it that you'd already quoted? :p

#Comment by Aaron Schulz (talk | contribs)   23:36, 16 March 2012

Passing '"php" "path/to/script.php"' (all ascii chars, no spaces) to proc_open() results in failure.

#Comment by Awjrichards (talk | contribs)   23:44, 16 March 2012

Yeesh. '"php" "path/to/script.php"' is a totally legitimate command to run in bash, but I have no idea about other environments (like WIndows). This sounds like a problem (bug?) with proc_open(). Do you see the same behavior with other PHP functions that take $cmd as an argument? I wonder if proc_open() is also escaping $cmd resulting in nasty double escaped-ness.

#Comment by Aaron Schulz (talk | contribs)   05:15, 17 March 2012

I was messing around with this some more. shell_exec seems to work fine without or without the quotes. the popen() type functions are more interesting. I tried:

<?php

#$r = popen( '"php" "C:\wamp\www\MW_trunk/maintenance/showStats.php"', 'r' );
#var_dump( stream_get_contents( $r ) );

$pipes = array();
$process = proc_open(
	'"php" "C:\wamp\www\MW_trunk/maintenance/showStats.php"',
	#'php C:\wamp\www\MW_trunk/maintenance/showStats.php',
	array(
		0 => array( 'pipe', 'r' ), // input
		1 => array( 'pipe', 'w' ), // output
		2 => array( 'file', 'NUL', 'a' ) // error
	),
	$pipes // respective outputs
);

fclose( $pipes[0] );
var_dump( stream_get_contents( $pipes[1] ) );

fclose( $pipes[1] );
proc_close($process);

popen seems to work in either case. proc_open() also works without the quotes:

Aaron@AARON-PC-GAME /c/wamp/www/MW_trunk
$ php shelltest.php
string(162) "Total views       :    654
Total edits       : 194712
Number of articles:   4900
Total pages       :  16430
Number of users   :      8
Number of images  :     46
"

However, proc_open() gives an empty response when I have the extra quotes

Aaron@AARON-PC-GAME /c/wamp/www/MW_trunk
$ php shelltest.php
string(0) ""
#Comment by Aaron Schulz (talk | contribs)   05:18, 17 March 2012

OK, wtf...If I set the "bypass cmd.exe" flag it works again. See:

$process = proc_open(
	'"php" "C:\wamp\www\MW_trunk/maintenance/showStats.php"',
	#'php C:\wamp\www\MW_trunk/maintenance/showStats.php',
	array(
		0 => array( 'pipe', 'r' ), // input
		1 => array( 'pipe', 'w' ), // output
		2 => array( 'file', 'NUL', 'a' ) // error
	),
	$pipes, // respective outputs
	null,
	null,
	array( 'bypass_shell' => true )
);

Status & tagging log