-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Process] Windows argument escaping is fragile #19993
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Labels
Comments
@romainneutron can you take a look this? |
@wouterj FYI, the problem you encountered with ProcessUtils surrounding everything in double-quotes (composer #4280) is another example of this fragility. |
This was referenced Jan 12, 2017
fabpot
added a commit
that referenced
this issue
Feb 8, 2017
…ars, fixing signaling and escaping (nicolas-grekas) This PR was merged into the 3.3-dev branch. Discussion ---------- [Process] Accept command line arrays and per-run env vars, fixing signaling and escaping | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | yes | Tests pass? | yes | Fixed tickets | #12488, #11972, #10025, #11335, #5759, #5030, #19993, #10486 | License | MIT | Doc PR | - I think I found a way to fix this network of issues once for all. Of all the linked ones, only the last two are still open: the remaining were closed in dead ends. Instead of trying to make `ProcessUtil::escapeArgument` work correctly on Windows - which is impossible as discussed in #21347 - this PR deprecates it in favor of a more powerful approach. Depending on the use case: - when a simple command should be run, `Process` now accepts an array of arguments (the "binary" being the first arg). Making this the responsibility of `Process` (instead of `ProcessBuilder`) gives two benefits: - escape becomes an internal detail that doesn't leak - thus can't be misused ([see here](#21347 (comment))) - since we know we're running a single command, we can prefix it automatically by "exec" - thus fixing a long standing issue with signaling ```php $p = new Process(array('php', '-r', 'echo 123;')); echo $p->getCommandLine(); // displays on Linux: // exec 'php' '-r' 'echo 123;' ``` - when a shell expression is required, passing a string is still allowed. To make it easy and look-like sql prepared statements, env vars can be used when running the command. Since the shell is OS-specific (think Windows vs Linux) - this PR assumes no portability, so one should just use each shell's specific syntax. From the fixtures: ```php $env = array('FOO' => 'Foo', 'BAR' => 'Bar'); $cmd = '\\' === DIRECTORY_SEPARATOR ? 'echo !FOO! !BAR! !BAZ!' : 'echo $FOO $BAR $BAZ'; $p = new Process($cmd, null, $env); $p->run(null, array('BAR' => 'baR', 'BAZ' => 'baZ')); $this->assertSame('Foo baR baZ', rtrim($p->getOutput())); $this->assertSame($env, $p->getEnv()); ``` Commits ------- 330b61f [Process] Accept command line arrays and per-run env vars, fixing signaling and escaping
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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
:and this script:
the expected output from
print_r($argv);
is:The actual output using
Winbox\Args
is as above, whereas the output usingProcessUtils
is: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: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.
The text was updated successfully, but these errors were encountered: