Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Process] Windows argument escaping is fragile #19993

Closed
@johnstevenson

Description

@johnstevenson

It is quite easy to break ProcessUtils::escapeArgument on Windows, because it does not follow all the various argument-parsing rules.

I discovered this while working on Composer's XdebugHandler (which restarts the process and needs a robust way to escape its passed-in arguments) and after much research came up with a single function Winbox\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 this composer.json:

{
    "require": {
        "symfony/process": "^2.1",
        "winbox/args": "^1.0"
    }
}

and this script:

<?php
require __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']);

function run($params, $escaper)
{
    $command = implode(' ', array_map($escaper, $params));
    printf("%s command line:\n%s\n\n", $escaper[0], $command);
    passthru($command);
    echo PHP_EOL;
}

the expected output from print_r($argv); is:

Array
(
    [0] => -
    [1] => path=%PATH%
    [2] => quote="
    [3] => colors=red & blue
)

The actual output using Winbox\Args is as above, whereas the output using ProcessUtils 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 called blue) highlights a more serious problem:

  • the escaped arguments are not totally self-contained.

What's happening here is that quote=" 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"). See How cmd.exe parses a command for more information.

The wiki at winbox-args details the various hoops you have to go through to try and make this stuff work.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions