JDK-8205102 : ProcessBuilder badly handles quotes by sending them masked with backslashes
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang
  • Affected Version: 8,9,10,11
  • Priority: P4
  • Status: Resolved
  • Resolution: Not an Issue
  • OS: linux
  • CPU: x86_64
  • Submitted: 2018-06-14
  • Updated: 2018-07-12
  • Resolved: 2018-06-19
Description
ADDITIONAL SYSTEM INFORMATION :
Tested on Fedora 28 and Oracle JDK 1.8.0_171.
Tested on macOS 10.13.4 and Oracle JDK 1.8.0_171.
Tested on Windows 10 and Oracle JDK 1.8.0_171.

The bug only happens on Fedora and macOS, not on Windows.

A DESCRIPTION OF THE PROBLEM :
When calling an executable through java.lang.ProcessBuilder, quotes passed as parameters are sent to the executable still masked with backslashes.

For instance, instead of calling (1):
./processbuilder_test -test ""

It becomes (2):
./processbuilder_test -test \"\"

This is really (1) I want to get executed.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1/ compile the C++ code to produce the executable processbuilder_test
2/ move it to your home folder
3/ compile the Java code and launch it
4/ open a terminal and directly execute: ./processbuilder_test -test ""
5/ open a terminal and directly execute: ./processbuilder_test -test \"\"

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
At step 3/ and 4/, in your home folder, you'll get a new file called args.log with this content:
/home/<username>/processbuilder_test
-test
<empty line>

5/ in your home folder, you'll get a new file called args.log with this content:
/home/<username>/processbuilder_test
-test
""

ACTUAL -
At step 3/ and 5/, in your home folder, you'll get a new file called args.log with this content:
/home/<username>/processbuilder_test
-test
""

4/ in your home folder, you'll get a new file called args.log with this content:
/home/<username>/processbuilder_test
-test
<empty line>


---------- BEGIN SOURCE ----------
C++ code:

#include <iostream>
#include <fstream>

using namespace std;

int main(int argc, const char * argv[])
{
	ofstream myfile;
	myfile.open ("args.log");
	for (int i = 0;i < argc; ++i)
		myfile << argv[i] << endl;
	myfile.close();
	return 0;
}

Java code:

package processbuilder.test;

import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

public class ProcessBuilderTest {

    public static void main(String[] args) throws IOException {
        List<String> command = new ArrayList<>();
        command.add(Paths.get(System.getProperty("user.home"), "processbuilder_test").toString());
        command.add("-test");
        command.add("\"\"");
        ProcessBuilder pb = new ProcessBuilder(command);
        pb.directory(new File(System.getProperty("user.home")));
        pb.redirectErrorStream(true).start();   
    }   
}
---------- END SOURCE ----------

FREQUENCY : always



Comments
In the examples (#4 and #5), the shell is processing the quotes and removing them from the argument unless they are quoted. The ProcessBuilder API literally passes the string provided as the argument; there is no processing to remove quotes or further interpret quoted quotes.
19-06-2018

Tested on linux ubuntu 14.0.1: JDK 8u172 - Fail JDK 10.0.1+11- Fail JDK 11-ea - Fail The outputs of step3 , step 4 and step 5 are attached in the bug report.
15-06-2018