-
Notifications
You must be signed in to change notification settings - Fork 5.4k
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
8282008: Incorrect handling of quoted arguments in ProcessBuilder #7504
Conversation
👋 Welcome back omikhaltcova! A progress list of the required criteria for merging this PR into |
@omikhaltsova The following label will be automatically applied to this pull request:
When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing list. If you would like to change these labels, use the /label pull request command. |
Webrevs
|
(Edited) |
Actually, there's a bit more to this than first meets the eye. "A double quote mark preceded by a backslash (\") is interpreted as a literal double quote mark (")." That was the reason for the change in JDK-8250568. So the application supplied quotes combined with the trailing file separator results in unbalanced quotes. Without the application supplied quotes, the implementation quotes the string (because of the embedded space) and doubles up the backslash so it does not escape the final quote. |
@omikhaltsova Please take another look at the comment above. The fix incorrectly allows a final double-quote to be escaped, resulting in unbalanced quotes and possibly allowing an argument to be joined with the next. |
Roger, thanks for your comments! But in this case how it is possible to present a path ending with '\' and including a space inside? |
ProcessBuilder handles the quoting of arguments with spaces.
That worked for me using openjdk version "17.0.2". |
Please close this PR; the proposed change to the application should resolve the issue. |
Roger, writing a test via echo was not a good idea obviously for this particular case because of the fact well shown in the doc "4. Everyone Parses Differently", https://daviddeley.com/autohotkey/parameters/parameters.htm#WINCRULESMSEX. The task is more complicated than it seems at the first glance. The same command line correctly parsed in an app written in C/C++ might be incorrectly parsed in a VBS app etc. The suggestion not to use the path-argument surroundings with Below there are some experiments with an app attached to JDK-8282008: NO FIX
FIXED (as in pr)
Reading the code of unQuote() in terms of logic: "no beginning or ending quote, or too short => not quoted", - and it seems that if all these conditions are just opposite (starting and ending quotes and long enough) then a string should be treated as quoted but it's not. One exception was added and it's strange that it's applied even in case of paired quotes. Is it truly necessary for the security fix to skip (=to treat as unquoted) a string starting and ending with This proposed fix returns back possibility (as was previously) to use surrounding with |
Mailing list message from Raffaello Giulietti on core-libs-dev: Hi, as far as I know, on Windows every program can obtain the lpCommandLine There are no fixed rules on how to parse the command line, as witnessed Consequently, there are no fixed rules on how to encode a command line Without knowing the parsing rules of the target program, it is not The best we can hope is to implement encoders (and decoders) for Greetings ---- [1] On 2022-02-24 20:18, Olga Mikhaltsova wrote: |
It is apparent there is no one "correct" way to quote, but one of the key features of the Java ecosystem has been its backwards compatibility. In that light, this change allows our clients to continue doing what they did the way they did it without the need for modification of their Java code or their (maybe even foreign) native code. FWIW. Separately from the above, I wonder if this change would make the fix less controversial? - if (str.endsWith("\\\"")) {
+ if (str.endsWith("\\\"") && !str.endsWith("\\\\\"")) { This way we verify that the end quote is really just an escaped quote, while correctly identifying escaped backslash as having nothing to do with the following quote. |
Actually, this change should be made even more generic because the string might end with any even number of the backslash characters followed by a free-standing quote, in which case additional quoting should not be required. |
(I'm still working on a more nuanced fix that works with .exe, .cmd, and with allowAmbiguousCommands both true and false). The suggested workaround was to remove the application quotes and let ProcessBuilder do the quoting. The case of the backslash at the end of an argument occurs mainly in a directory path. |
@RogerRiggs ProcessBuilder("java.exe", "-classpath", "\"C:\\New folder\"", "Test", "test"); this doesn't and, as I understand, shouldn't (the string ends with ProcessBuilder("java.exe", "-classpath", "\"C:\\New folder\\\"", "Test", "test"); and produces errors like these
However, the following still doesn't work, but, I believe, should (the string ends with ProcessBuilder("java.exe", "-classpath", "\"C:\\New folder\\\\\"", "Test", "test"); |
Thanks for the example, though my question was in the case in which the extra quotes were not included by the app.
I thought the troublesome case was specific to VB/WScript being invoked with ".exe" quoting but WSCRIPT interpreting the command line string using simple quoting with no escapes. |
As an alternative fix, please take a look at Draft PR: #7709. In the default handling of arguments, the check for what is quoted is reverted to prior to 8255068. First and last quotes are sufficient to identify a "quoted" string. The check for a backslash ("\") is removed. For the case where the system property The PR includes a test of the 12 combinations of invoking an "java"/.exe program, a .cmd script, and a Visual Basic script (which uses the .exe rules but different command line parser); with and without application quotes and compares the actual results with the expected arguments. |
@RogerRiggs I believe your patch fixes the use case(s) we are interested in. Would be good to see it merged into |
@RogerRiggs Sorry for the delay! I also checked, the test-case with VBS, that raised this issue, successfully workes with your patch. It would be great to have it asap. |
Closed due to an alternative fix #7709. |
Thanks for the followup and confirmation. I'll move #7709 to review from draft. |
This fix made equal processing of strings such as ""C:\Program Files\Git\"" before and after JDK-8250568.
For example, it's needed to execute the following command on Windows:
C:\Windows\SysWOW64\WScript.exe "MyVB.vbs" "C:\Program Files\Git\" "Test"
it's equal to:
new ProcessBuilder("C:\\Windows\\SysWOW64\\WScript.exe", "MyVB.vbs", "\"C:\\Program Files\\Git\\\"", "Test").start();
While processing, the 3rd argument ""C:\Program Files\Git\"" treated as unquoted due to the condition added in JDK-8250568.
that leads to the additional surrounding by quotes in ProcessImpl::createCommandLine(..) because needsEscaping(..) returns true due to the space inside the string argument.
As a result the native function CreateProcessW (src/java.base/windows/native/libjava/ProcessImpl_md.c) gets the incorrectly quoted argument:
Obviously, a string ending with
"\\\""
must not be started with"\""
to treat as unquoted overwise it’s should be treated as properly quoted.Progress
Issue
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.java.net/jdk pull/7504/head:pull/7504
$ git checkout pull/7504
Update a local copy of the PR:
$ git checkout pull/7504
$ git pull https://git.openjdk.java.net/jdk pull/7504/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 7504
View PR using the GUI difftool:
$ git pr show -t 7504
Using diff file
Download this PR as a diff file:
https://git.openjdk.java.net/jdk/pull/7504.diff