Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork9.7k
Description
It is quite easy to breakProcessUtils::escapeArgument on Windows, because it does not follow all the various argument-parsing rules.
I discovered this while working on Composer'sXdebugHandler (which restarts the process and needs a robust way to escape its passed-in arguments) and after much research came up with a single functionWinbox\Args::escape to handle this.
To illustrate the problems, we can pass some contrived arguments to both escape functions and get php to print out its$argv:
Given thiscomposer.json:
{"require": {"symfony/process":"^2.1","winbox/args":"^1.0" }}and this script:
<?phprequire__DIR__ .'/vendor/autoload.php';$params = [PHP_BINARY,'-r','print_r($argv);','--','path=%PATH%','quote="','colors=red & blue',];run($params, ['Symfony\Component\Process\ProcessUtils','escapeArgument']);run($params, ['Winbox\Args','escape']);functionrun($params,$escaper){$command =implode('',array_map($escaper,$params));printf("%s command line:\n%s\n\n",$escaper[0],$command);passthru($command);echoPHP_EOL;}
the expected output fromprint_r($argv); is:
Array( [0] => - [1] => path=%PATH% [2] => quote=" [3] => colors=red & blue)The actual output usingWinbox\Args is as above, whereas the output usingProcessUtils is:
Array( [0] => - [1] => path=C:\WINDOWS\system32 ... and the rest of the PATH variable [2] => quote=" [3] => colors=red)'blue"' is not recognized as an internal or external command,operable program or batch file.The unexpected path-expansion is a simple logic error, but the argument splitting (colors=red followed by cmd.exe trying to run a program calledblue) highlights a more serious problem:
- the escaped arguments are not totally self-contained.
What's happening here is thatquote=" is escaped as"quote=\"" and while this will work fine on its own, the odd number of double-quotes may corrupt subsequent arguments. In this case the escaped"colors=red & blue" is interpreted by cmd.exe as an argument ("colors=red) followed by the special character& which signifies a separate command (blue"). SeeHow cmd.exe parses a command for more information.
The wiki atwinbox-args details the various hoops you have to go through to try and make this stuff work.