https://github.com/oracle/graal/commit/e54f5cfb0dcc21c777bafec9bcba02be2208afd5 introduced passing of command line arguments from native-image to the builder JVM via a file where arguments are delimited by System.lineSeparator(). This works well in most common cases, but makes the JVM fail if any of the arguments contains a newline character.
Steps to reproduce
Have a Java class like the following
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Map;
public class App {
static Socket socket;
static {
try {
socket = new Socket("neverssl.com", 80);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static void main(String[] args) throws IOException {
System.out.println("my.property=" + System.getProperty("my.property") + "=");
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
out.write("hello\r\n");
}
}
Compile it
javac App.java
The native-image should be built from the master after e54f5cfb0dcc21c777bafec9bcba02be2208afd5, in my case 88701d1b22eb003359eff247ef68df0894f90d74
native-image --version
GraalVM Version 21.0.0-dev (Java Version 11.0.9+10-jvmci-21.0-b02)
Use the native-image with legal arguments to see that the scenario is valid:
native-image App --no-server --native-image-info --verbose --initialize-at-build-time=App -H:Class=App \
-H:Name=app -H:FallbackExecutorJavaArg=-Dmy.property=foo
...
Warning: Image 'app' is a fallback image that requires a JDK for execution (use --no-fallback to suppress fallback image generation and to print more detailed information why a fallback image was necessary).
# The above warning is expected
Running the executable gives the expected result.
./app
my.property=foo=
Now let's add a newline to the -H:FallbackExecutorJavaArg=-Dmy.property=foo:
native-image App --no-server --native-image-info --verbose --initialize-at-build-time=App -H:Class=App \
-H:Name=app "-H:FallbackExecutorJavaArg=-Dmy.property=foo
bar"
...
Error: Unknown options: [bar]
Error: Use -H:+ReportExceptionStackTraces to print stacktrace of underlying exception
Error: Image build request failed with exit status 1
com.oracle.svm.driver.NativeImage$NativeImageError: Image build request failed with exit status 1
at com.oracle.svm.driver.NativeImage.showError(NativeImage.java:1636)
at com.oracle.svm.driver.NativeImage.build(NativeImage.java:1386)
at com.oracle.svm.driver.NativeImage.performBuild(NativeImage.java:1347)
at com.oracle.svm.driver.NativeImage.main(NativeImage.java:1306)
at com.oracle.svm.driver.NativeImage$JDK9Plus.main(NativeImage.java:1818)
Expected: the above command succeeds and ./app outputs the property value with the newline.
Describe GraalVM and your environment:
Thanks for reporting this @ppalaga, I will take a look at the issue
Hi @ppalaga please be aware that -H:FallbackExecutorJavaArg is an internal option. It is used by the driver if regular image-build fails and we have to revert to building a fallback-image. We do not support this option to be used explicitly on command line.
That said, we could change the option separator used in the file for passing the image builder arguments to something else than newline. Eg. '\0'. This would prevent issues with options that contain newlines in the option value.
Yeah, I admit, the example is a bit artificial. But as you certainly see, any -H: argument containing a newline will cause the same kind of driver failure. Even if newline is not considered a valid input of any of the current -H: options, I think driver should pass it to the builder JVM rather than fail. I thus welcome your readiness to solve this corner case in some way.
Hard to say whether \0 would not cause some problems, such as editors unable to display the file when a developer opens it for debug purposes. Other than that, can we reliably rule out that \0 is not a valid input for some of the arguments?
java.util.Properties.store()/load() is maybe another good option. It is simple and reliable when it comes to escaping spaces, newlines and other special characters.
java.util.Properties.store()/load() is maybe another good option. It is simple and reliable when it comes to escaping spaces, newlines and other special characters.
That's a very good idea. If the '\0' approach will ever cause problems we consider it.
Other than that, can we reliably rule out ...
But in general ... almost nothing can ever reliably be ruled out ;-)
Fair enough, thanks for taking care, @olpaw.