gpu: Fix loading gluegen natives on some Windows configurations

This commit works around a bug with loading natives when the user's home
folder contains special characters such as `&`, `^` or `!`.

When Gluegen loads native libraries on Windows, it uses a temporary
directory located in `%appdata%` under the user's home directory, and
Gluegen checks whether files can be executed from this temporary
directory. To perform this check, it writes an executable to the
directory, executes it, and ensures that the return code is zero. The
executable file it writes is by default a `.bat` file, but it can be
told to write an `.exe` file instead by supplying this VM argument:
`-Djogamp.gluegen.UseNativeExeFile=true`.

The default behaviour of writing and executing a `.bat` file is broken
when the path to the temp folder contains a special character, due to a
convoluted trail of calls that leads to undefined behaviour:
- Gluegen attempts to execute the `.bat` file by calling `Runtime.exec()`:
  `Runtime.exec(new String[] { "...absolute path...bat" }, null, null)`
- OpenJDK 11.0.8 passes the command to `ProcessBuilder`, which calls
  `ProcessImpl.start(...)`, which creates a new `ProcessImpl` instance.
- In the `ProcessImpl` constructor, there are two different character
  escape modes:
  - **Legacy mode**, which allows ambiguous commands.
  - **Non-legacy mode**, which does more rigorous escaping.
- Legacy is the default mode as long as `System.getSecurityManager()`
  returns `null`, which is the case for RuneLite currently.
  This mode can be changed by supplying the following VM argument:
  `-Djdk.lang.Process.allowAmbiguousCommands=false`.
  - Incidentally this also fixes the issue of loading natives with
    special characters in the path, however it applies to *all*
    `Runtime.exec()` calls.
- In legacy mode, the command is wrapped in quotes if it contains either
  a space or tab character. The command is then passed along to the
  native function `Java_java_lang_ProcessImpl_create`, which eventually
  passes it along untouched to Microsoft's `CreateProcessW` function as
  the `lpCommandLine` argument.
- In the documentation for this function, it is mentioned that an
  interpreter (i.e. `cmd.exe`) is required in order to run a `.bat`
  file. It is not specified what will happen if you instead pass the
  path to a `.bat` file directly to the function, which is what Gluegen
  ends up doing. However, `CreateProcessW` *does* support supplying the
  path to an `.exe`, which Gluegen will do when
  `jogamp.gluegen.UseNativeExeFile` is set to `true`.

It is unclear why supplying a `.bat` file normally works, yet breaks
when special characters are in the path. It seems like it should not
work in the first place.

This might help with #6509 and #14180.

Some other special characters, like Cyrillic letters, are more
fundamentally broken in RuneLite. This patch only slightly helps with
that.
This commit is contained in:
Hooder
2022-02-23 02:41:00 +01:00
committed by Adam
parent edf647f1ab
commit 35949bce22

View File

@@ -353,6 +353,8 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
System.setProperty("jogl.debug", "true");
}
System.setProperty("jogamp.gluegen.UseNativeExeFile", "true");
GLProfile.initSingleton();
invokeOnMainThread(() ->