Java Runtime exec() fails to escape characters properly

Tim Strijdhorst picture Tim Strijdhorst · May 11, 2011 · Viewed 14.5k times · Source

This might already been answered before but that was regarding unicode and I don't think this is unicode (it's in ASCII so...).

When I execute this in my terminal there is no problem what so ever

vboxmanage setextradata "Test Machine" "VBoxInternal/Devices/pcnet/0/LUN#0/Config/ssh/HostPort" 2222

However when I use the following in Java

Runtime.getRuntime().exec("vboxmanage setextradata \"Test Machine\" \"VBoxInternal/Devices/pcnet/0/LUN#0/Config/ssh/HostPort\" 2222");

It returns an error: unregistered vm '"TestMachine"'

The same goes for parameters with spaces in them like Test\ Machine, then it doesn't escape the space.

Now I think this has something to do with the character encoding, but I don't see any option to set that o_O

Answer

Edwin Buck picture Edwin Buck · May 11, 2011

You are calling the program and its arguments in one pass, which effectively shoves the entire string into the processing environment (hoping for the best).

In Windows systems, the operating system makes a point of handling the executable and arguments differently, and putting them all in the same string just requires you to pick the perfect string which the environment (of which there are two that i know about) can re-parse into an argument list. The better solution is to use

Runtime.exec(new String[] {"vboxmanage", "setextradata", "Test Machine", "VBoxInternal/Devices/pcnet/0/LUN#0/Config/ssh/HostPort", "2222"});

which corresponds to Runtime's

public Process exec(String[] cmdarray)
         throws IOException

At best, with the one string method you'll eventually find out how to hint and escape out the arguments so they don't get treated as part of the executable name, but then you'll encounter a new issue, that they get passed all as one parameter to the executable. Once you fix that depending on the environment, you'll either find that your quotes aren't getting stripped from the parameters (leading to parameters like "2222") or that Window's semi-broken argument parsing is going to parse on whitespace first (leading to parameters like ("Test). It doesn't make sense, that's why there are more than one exec methods available.