Skip to content

Commit

Permalink
Handle the case of a Multi-Release Jar not actually containing Multi-…
Browse files Browse the repository at this point in the history
…Release Classes (#42)

Seen a couple of people encounter this in mod dev (when adding
dependencies):

SJH considers a Jar to be `Multi-Release` based on the `Manifest`

<https://github.com/McModLauncher/securejarhandler/blob/96a7b6a8fe1f1117e01dfd94c640757154372a68/src/main/java/cpw/mods/jarhandling/impl/Jar.java#L124>

If it is then it resolves a path to `/META-INF/versions`

<https://github.com/McModLauncher/securejarhandler/blob/96a7b6a8fe1f1117e01dfd94c640757154372a68/src/main/java/cpw/mods/jarhandling/impl/Jar.java#L126>

And tries to walk it

<https://github.com/McModLauncher/securejarhandler/blob/96a7b6a8fe1f1117e01dfd94c640757154372a68/src/main/java/cpw/mods/jarhandling/impl/Jar.java#L127>

This works for most Jars, however it does not consider the case where a
Jar is erroneously marked as `Multi-Release`, with `/META-INF/versions`
**not** existing.

If this is the case, `Files.walk` will throw a
`UnionFileSystem$NoSuchFileException` which is then wrapped and rethrown
as a `UncheckedIOException`

<https://github.com/McModLauncher/securejarhandler/blob/96a7b6a8fe1f1117e01dfd94c640757154372a68/src/main/java/cpw/mods/jarhandling/impl/Jar.java#L138>

Attached Example Stacktrace,
<https://gist.github.com/AterAnimAvis/35ded98d52a78c2f257d59173c86366c>

---

Current implementation of a fix is from a bit of spitballing [in
Discord](https://discord.com/channels/313125603924639766/922237746460893234/1129415771567689738)
  • Loading branch information
AterAnimAvis authored Feb 14, 2024
1 parent bbf1ff4 commit 8d3b608
Show file tree
Hide file tree
Showing 3 changed files with 10 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/main/java/cpw/mods/jarhandling/impl/JarContentsImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ private Map<Path, Integer> readMultiReleaseInfo() {
}

var vers = filesystem.getRoot().resolve("META-INF/versions");
if (!Files.isDirectory(vers)) return Map.of();

try (var walk = Files.walk(vers)) {
Map<Path, Integer> pathToJavaVersion = new HashMap<>();
walk
Expand Down
7 changes: 7 additions & 0 deletions src/test/java/cpw/mods/jarhandling/impl/TestMultiRelease.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ public void testMultiRelease() {
Assertions.assertNotEquals("too new", bContents.strip());
}

@Test
public void testMultiReleaseNoVersions() {
Path rootDir = Paths.get("src", "test", "resources", "multirelease-noversions");
// Jars marked with Multi-Release but don't actually have a versions folder should not throw
Assertions.assertDoesNotThrow(() -> SecureJar.from(rootDir));
}

private static String readString(SecureJar jar, String file) {
// Note: we must read the jar through the module data provider for version-specific files to be used
try (var is = jar.moduleDataProvider().open(file).get()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Multi-Release: true

0 comments on commit 8d3b608

Please sign in to comment.