Skip to content

Commit

Permalink
Fixed plugin classes not being validated for internal api usages, als…
Browse files Browse the repository at this point in the history
…o fix them not using the knot class loader (which prevented them from accessing logging classes)
  • Loading branch information
AlexIIL committed Jul 23, 2023
1 parent c3d102b commit 355ccca
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,23 @@
import java.util.Set;

import org.quiltmc.loader.api.plugin.ModMetadataExt;
import org.quiltmc.loader.impl.transformer.InternalsHiderTransform;
import org.quiltmc.loader.impl.util.FileUtil;
import org.quiltmc.loader.impl.util.QuiltLoaderInternal;
import org.quiltmc.loader.impl.util.QuiltLoaderInternalType;

@QuiltLoaderInternal(QuiltLoaderInternalType.NEW_INTERNAL)
class QuiltPluginClassLoader extends ClassLoader {

final QuiltPluginManagerImpl manager;
final QuiltPluginContextImpl context;
final Path from;
final Set<String> loadablePackages;

public QuiltPluginClassLoader(QuiltPluginManagerImpl manager, ClassLoader parent, Path from,
public QuiltPluginClassLoader(QuiltPluginContextImpl context, ClassLoader parent, Path from,
ModMetadataExt.ModPlugin plugin) {

super(parent);
this.manager = manager;
this.context = context;
this.from = from;
this.loadablePackages = new HashSet<>(plugin.packages());
}
Expand Down Expand Up @@ -90,6 +91,10 @@ private Class<?> loadClassInner(String name) throws ClassNotFoundException {
try (InputStream is = Files.newInputStream(from.resolve(path))) {
byte[] src = FileUtil.readAllBytes(is);

InternalsHiderTransform transform = new InternalsHiderTransform(InternalsHiderTransform.Target.PLUGIN);

src = transform.run(context.optionFrom, src);

try {
definePackage(pkg, null, null, null, null, null, null, null);
} catch (IllegalArgumentException e) {
Expand All @@ -104,7 +109,7 @@ private Class<?> loadClassInner(String name) throws ClassNotFoundException {
}
}

return manager.findClass(name, pkg);
return context.manager.findClass(name, pkg);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,12 @@ public QuiltPluginContextImpl(//
this.optionFrom = from;
this.pluginPath = from.resourceRoot();

ClassLoader parent = getClass().getClassLoader();
ClassLoader parent = Thread.currentThread().getContextClassLoader();
ModPlugin pluginMeta = from.metadata().plugin();
if (pluginMeta == null) {
throw new IllegalArgumentException("No plugin metadata!");
}
classLoader = new QuiltPluginClassLoader(manager, parent, pluginPath, pluginMeta);
classLoader = new QuiltPluginClassLoader(this, parent, pluginPath, pluginMeta);

Class<?> cls = classLoader.loadClassDirectly(pluginMeta.pluginClass(), true);
Object obj = cls.getDeclaredConstructor().newInstance();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,24 +36,33 @@
import org.quiltmc.loader.api.ModInternal;
import org.quiltmc.loader.api.plugin.solver.ModLoadOption;
import org.quiltmc.loader.impl.QuiltLoaderImpl;
import org.quiltmc.loader.impl.launch.knot.IllegalQuiltInternalAccessError;
import org.quiltmc.loader.impl.util.QuiltLoaderInternal;
import org.quiltmc.loader.impl.util.QuiltLoaderInternalType;
import org.quiltmc.loader.impl.util.log.Log;
import org.quiltmc.loader.impl.util.log.LogCategory;

class InternalsHiderTransform {
@QuiltLoaderInternal(QuiltLoaderInternalType.NEW_INTERNAL)
public class InternalsHiderTransform {

@QuiltLoaderInternal(QuiltLoaderInternalType.NEW_INTERNAL)
public enum Target {
PLUGIN,
MOD;
}

private static final String MOD_INTERNAL_DESCRIPTOR = Type.getDescriptor(ModInternal.class);

private static final String METHOD_OWNER = Type.getInternalName(QuiltInternalExceptionUtil.class);

final Target target;
final Map<String, InternalValue> internalPackages = new HashMap<>();
final Map<String, InternalValue> internalClasses = new HashMap<>();
final Map<MethodKey, InternalValue> internalMethods = new HashMap<>();
final Map<FieldKey, InternalValue> internalFields = new HashMap<>();

InternalsHiderTransform() {}
public InternalsHiderTransform(Target target) {
this.target = target;
}

void scanClass(ModLoadOption mod, Path file, byte[] classBytes) {
// TODO: Replace this with full-reflect lookup!
Expand Down Expand Up @@ -125,7 +134,7 @@ public void visitEnd() {
reader.accept(visitor, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
}

byte[] run(ModLoadOption mod, byte[] classBytes) {
public byte[] run(ModLoadOption mod, byte[] classBytes) {
ClassReader reader = new ClassReader(classBytes);
String className = reader.getClassName();
ClassWriter writer = new ClassWriter(reader, 0) {
Expand Down Expand Up @@ -297,17 +306,27 @@ private InternalValue getAnnotationSet(String owner) {
type = QuiltLoaderInternalType.LEGACY_NO_WARN;
}

if (type == QuiltLoaderInternalType.LEGACY_NO_WARN) {
value = PermittedLoaderInternalValue.INSTANCE;
} else {
if (type == QuiltLoaderInternalType.LEGACY_EXPOSED) {
value = new WarnLoaderInternalValue();
if (target == Target.MOD) {
if (type == QuiltLoaderInternalType.LEGACY_NO_WARN) {
value = PermittedLoaderInternalValue.INSTANCE;
} else {
value = new LoaderInternalValue();
if (type == QuiltLoaderInternalType.LEGACY_EXPOSED) {
value = new WarnLoaderInternalValue();
} else {
value = new LoaderInternalValue();
}
for (Class<?> cls : replacements) {
value.replacements.add(cls.toString());
}
}
for (Class<?> cls : replacements) {
value.replacements.add(cls.toString());
} else if (target == Target.PLUGIN) {
if (name.startsWith("org.quiltmc.loader.api.")) {
value = PermittedLoaderInternalValue.INSTANCE;
} else {
value = new LoaderInternalValue();
}
} else {
throw new IllegalStateException("Unknown Target " + target);
}
internalClasses.put(owner, value);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ private static void populateTransformCache(Path root, List<ModLoadOption> modLis
ChasmInvoker.applyChasm(root, modList, solveResult);
}

InternalsHiderTransform internalsHider = new InternalsHiderTransform();
InternalsHiderTransform internalsHider = new InternalsHiderTransform(InternalsHiderTransform.Target.MOD);
Map<Path, ClassData> classes = new HashMap<>();

forEachClassFile(root, modList, (mod, file) -> {
Expand Down

0 comments on commit 355ccca

Please sign in to comment.