JDK-6550942 : (process) Runtime.exec(String,String[],File) incorrectly handles quotes
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang
  • Affected Version: 6
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2007-04-27
  • Updated: 2010-04-04
  • Resolved: 2007-04-27
Related Reports
Duplicate :  
Description
FULL PRODUCT VERSION :
java version "1.5.0_10"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_10-b03)
Java HotSpot(TM) Client VM (build 1.5.0_10-b03, mixed mode, sharing)
JRE 1.6.0

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]

A DESCRIPTION OF THE PROBLEM :
Method java.lang.Runtime.exec(String,String[],File) incorrectly handles quotes in commandline if UNC path to executable is used and it is quoted.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the code and compare with Start>Run on Windows.
Start>Run can execute:
"\\slothxp\C$\Program Files\Internet Explorer\iexplore.exe" about:blank

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The process should start.
It does start correctly if I remove quotes from commandline.
ACTUAL -
Process is not created but IOException is thrown.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
java.io.IOException: Cannot run program ""\\host.domain.com\path\file.exe"": CreateProcess error=3, The system cannot find the path specified
 at java.lang.ProcessBuilder.start(ProcessBuilder.java:459)
 at java.lang.Runtime.exec(Runtime.java:593)
 at java.lang.Runtime.exec(Runtime.java:431)
 at java.lang.Runtime.exec(Runtime.java:328)
 at com.ptc.warp.transform.Test.main(Test.java:19)
Caused by: java.io.IOException: CreateProcess error=3, The system cannot find the path specified
 at java.lang.ProcessImpl.create(Native Method)
 at java.lang.ProcessImpl.<init>(ProcessImpl.java:81)
 at java.lang.ProcessImpl.start(ProcessImpl.java:30)
 at java.lang.ProcessBuilder.start(ProcessBuilder.java:452)
 ... 4 more


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
public class Test {

  public static void main( String[] args ) {
    try {
      java.lang.Runtime.getRuntime().exec("\"\\\\slothxp\\C$\\Program Files\\Internet Explorer\\iexplore.exe\" about:blank");
    } catch ( Throwable e ) {
      e.printStackTrace( System.err );
    }
  }
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Please note that the same issue is observed in JRE 1.6.0.

Method Runtime.exec(String[],String[],File) may be used instead of Runtime.exec(String,String[],File). But in this case you should parse command line manually. I use the following code (it is experimental, I am not absolutely sure that this code is correct):

        int pos = 0;
        java.util.ArrayList arglist = new java.util.ArrayList();
        parse_commandline: {

          char c;
          StringBuffer arg = new StringBuffer();
          int length = startCommand.length();
          do {
            while ( Character.isWhitespace(startCommand.charAt(pos)) ) {
              pos++;
              if ( pos>=length ) break parse_commandline;
            }

            arg.setLength(0);
            c = startCommand.charAt(pos);
            if ( c=='"' ) {
              pos++;
              while ( pos<length && (c=startCommand.charAt(pos++))!='"' ) {
                if ( c!='^' ) {
                  arg.append(c);
                } else if ( pos<length ) {
                  arg.append(startCommand.charAt(pos));
                } else {
                  arg.append('^');
                  break;
                }
              }

            } else {

              while ( pos<length && !Character.isWhitespace(c=startCommand.charAt(pos++)) ) {
                if ( c=='^') {
                  if ( pos<length ) {
                    arg.append(startCommand.charAt(pos));
                  } else {
                    arg.append('^');
                    break;
                  }
                } else if ( c=='"' ) {
                  pos++;
                  while ( pos<length && (c=startCommand.charAt(pos++))!='"' ) {
                    if ( c!='^' ) {
                      arg.append(c);
                    } else if ( pos<length ) {
                      arg.append(startCommand.charAt(pos));
                    } else {
                      arg.append('^');
                      break;
                    }
                  }
                } else {
                  arg.append(c);
                }
              }
            }

            arglist.add( arg.toString() );

          } while( pos<length );
        } // parse_commandline

        cmdarray = (String[])arglist.toArray( new String[arglist.size()] );

Comments
EVALUATION Unfortunately, the problematic quoting of command lines on Windows cannot be changed compatibly. See: 6511002: (process) Document the auto-quoting when creating a Windows process; add winQuote
27-04-2007