Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/main/java/cpw/mods/cl/JarModuleFinder.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ public class JarModuleFinder implements ModuleFinder {
JarModuleFinder(final SecureJar... jars) {
record ref(SecureJar.ModuleDataProvider jar, ModuleReference ref) {}
this.moduleReferenceMap = Arrays.stream(jars)
// Computing the module descriptor can be slow so do it in parallel!
// Jars are not thread safe internally but they are independent, so this is safe.
.parallel()
.map(jar->new ref(jar.moduleDataProvider(), new JarModuleReference(jar.moduleDataProvider())))
.collect(Collectors.toMap(r->r.jar.name(), r->r.ref, (r1, r2)->r1));
}
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/cpw/mods/jarhandling/SecureJarRuntime.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package cpw.mods.jarhandling;

import java.util.Set;

public interface SecureJarRuntime {
/**
* Return the set of top-level folders in the JARs that should not be searched for class files.
*/
default Set<String> ignoredRootPackages() {
return Set.of("META-INF");
}
}
36 changes: 26 additions & 10 deletions src/main/java/cpw/mods/jarhandling/impl/Jar.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@
import java.io.UncheckedIOException;
import java.lang.module.ModuleDescriptor;
import java.net.URI;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.spi.FileSystemProvider;
import java.security.CodeSigner;
import java.util.*;
Expand Down Expand Up @@ -214,16 +217,29 @@ public String name() {
@Override
public Set<String> getPackages() {
if (this.packages == null) {
try (var walk = Files.walk(this.filesystem.getRoot())) {
this.packages = walk
.filter(path->path.getNameCount()>0)
.filter(path->!path.getName(0).toString().equals("META-INF"))
.filter(path->path.getFileName().toString().endsWith(".class"))
.filter(Files::isRegularFile)
.map(Path::getParent)
.map(path->path.toString().replace('/','.'))
.filter(pkg->pkg.length()!=0)
.collect(toSet());
Set<String> packages = new HashSet<>();
try {
Files.walkFileTree(this.filesystem.getRoot(), new SimpleFileVisitor<>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
if (file.getFileName().toString().endsWith(".class") && attrs.isRegularFile()) {
var pkg = file.getParent().toString().replace('/','.');
if (pkg.length() != 0) {
packages.add(pkg);
}
}
return FileVisitResult.CONTINUE;
}

@Override
public FileVisitResult preVisitDirectory(Path path, BasicFileAttributes attrs) {
if (path.getNameCount() > 0 && SecureJarEnvironment.isIgnoredRootPackage(path.getName(0).toString())) {
return FileVisitResult.SKIP_SUBTREE;
}
return FileVisitResult.CONTINUE;
}
});
this.packages = packages;
} catch (IOException e) {
throw new UncheckedIOException(e);
}
Expand Down
30 changes: 30 additions & 0 deletions src/main/java/cpw/mods/jarhandling/impl/SecureJarEnvironment.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package cpw.mods.jarhandling.impl;

import cpw.mods.jarhandling.SecureJarRuntime;

import java.util.ServiceLoader;
import java.util.Set;

class SecureJarEnvironment {
static final SecureJarRuntime runtime = findRuntime();
static final Set<String> ignoredRootPackages = findIgnoredRootPackages();

private static SecureJarRuntime findRuntime() {
return ServiceLoader.load(SecureJarRuntime.class).findFirst().orElse(new SecureJarRuntime() {});
}

private static Set<String> findIgnoredRootPackages() {
var packages = runtime.ignoredRootPackages();
// Validate root packages
for (var pkg : packages) {
if (pkg.contains(".") || pkg.contains("/")) {
throw new IllegalArgumentException("Invalid root package: " + pkg);
}
}
return packages;
}

public static boolean isIgnoredRootPackage(String pkg) {
return ignoredRootPackages.contains(pkg);
}
}
1 change: 1 addition & 0 deletions src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@
provides java.nio.file.spi.FileSystemProvider with UnionFileSystemProvider;
uses cpw.mods.cl.ModularURLHandler.IURLProvider;
provides ModularURLHandler.IURLProvider with UnionURLStreamHandler;
uses cpw.mods.jarhandling.SecureJarRuntime;
}