From 30ebdf140236fd93263b625416116564132f2038 Mon Sep 17 00:00:00 2001 From: JFronny Date: Thu, 12 May 2022 18:50:14 +0200 Subject: [PATCH] [unsafe] Fix classpath unlocking and use classPathIsolationBypassClasses. Will need to test changes without it now --- build.gradle | 9 +++++---- gradle.properties | 2 +- .../config/impl/ConfigInstanceAbstract.java | 1 - .../libjf/config/impl/JfConfigCommand.java | 3 --- .../client/gui/EntryInfoWidgetBuilder.java | 3 --- .../libjf/unsafe/JfLanguageAdapter.java | 2 +- .../inject/FabricLauncherClassUnlocker.java | 18 +++--------------- .../inject/KnotClassDelegateAccessor.java | 17 ++++++++++++++--- .../KnotClassLoaderInterfaceAccessor.java | 14 +------------- .../src/testmod/resources/fabric.mod.json | 3 ++- 10 files changed, 27 insertions(+), 45 deletions(-) diff --git a/build.gradle b/build.gradle index 407ed2f..8b8fb9c 100644 --- a/build.gradle +++ b/build.gradle @@ -23,10 +23,11 @@ allprojects { source sourceSets.testmod } } - } - // If dev startup fails, add: - // -Dfabric.debug.classPathIsolationBypassClasses=io/gitlab/jfronny/libjf + runConfigs.configureEach { + vmArgs "-Dfabric.debug.classPathIsolationBypassClasses=io/gitlab/jfronny/libjf" + } + } dependencies { modImplementation("com.terraformersmc:modmenu:3.1.0") @@ -45,4 +46,4 @@ subprojects { sourceSets { testmod -} \ No newline at end of file +} diff --git a/gradle.properties b/gradle.properties index f61a9b6..de86598 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,4 +13,4 @@ modrinth_optional_dependencies=P7dR8mSH curseforge_id=482600 curseforge_optional_dependencies=fabric-api -commons_version=2022.5.9+20-3-39 \ No newline at end of file +commons_version=2022.5.10+15-34-20 \ No newline at end of file diff --git a/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/ConfigInstanceAbstract.java b/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/ConfigInstanceAbstract.java index 6207168..5a9968b 100644 --- a/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/ConfigInstanceAbstract.java +++ b/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/ConfigInstanceAbstract.java @@ -1,6 +1,5 @@ package io.gitlab.jfronny.libjf.config.impl; -import io.gitlab.jfronny.commons.throwable.Coerce; import io.gitlab.jfronny.gson.JsonElement; import io.gitlab.jfronny.gson.JsonObject; import io.gitlab.jfronny.gson.stream.JsonWriter; diff --git a/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/JfConfigCommand.java b/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/JfConfigCommand.java index 2fa0042..83aefaa 100644 --- a/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/JfConfigCommand.java +++ b/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/JfConfigCommand.java @@ -5,14 +5,11 @@ import com.mojang.brigadier.arguments.*; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; -import io.gitlab.jfronny.commons.throwable.Coerce; import io.gitlab.jfronny.commons.throwable.ThrowingRunnable; import io.gitlab.jfronny.commons.throwable.ThrowingSupplier; -import io.gitlab.jfronny.commons.throwable.Try; import io.gitlab.jfronny.libjf.LibJf; import io.gitlab.jfronny.libjf.config.api.ConfigHolder; import io.gitlab.jfronny.libjf.config.api.ConfigInstance; -import io.gitlab.jfronny.libjf.config.api.Entry; import io.gitlab.jfronny.libjf.config.api.EntryInfo; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback; diff --git a/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/client/gui/EntryInfoWidgetBuilder.java b/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/client/gui/EntryInfoWidgetBuilder.java index 75d1463..3dadbf0 100644 --- a/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/client/gui/EntryInfoWidgetBuilder.java +++ b/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/client/gui/EntryInfoWidgetBuilder.java @@ -4,10 +4,8 @@ import io.gitlab.jfronny.commons.throwable.Try; import io.gitlab.jfronny.commons.tuple.Tuple; import io.gitlab.jfronny.libjf.LibJf; import io.gitlab.jfronny.libjf.config.api.ConfigInstance; -import io.gitlab.jfronny.libjf.config.api.Entry; import io.gitlab.jfronny.libjf.config.api.EntryInfo; import io.gitlab.jfronny.libjf.config.api.WidgetFactory; -import io.gitlab.jfronny.libjf.config.impl.EntryInfoImpl; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.gui.widget.ButtonWidget; @@ -113,7 +111,6 @@ public class EntryInfoWidgetBuilder { done.active = state.knownStates.stream().allMatch(st -> st.inLimits); if (inLimits) { - //Coerce.consumer(info::setValue).addHandler(e -> {}).accept(isNumber ? (T) value : (T) currentInput); state.cachedValue = isNumber ? (T) value : (T) currentInput; } diff --git a/libjf-unsafe-v0/src/main/java/io/gitlab/jfronny/libjf/unsafe/JfLanguageAdapter.java b/libjf-unsafe-v0/src/main/java/io/gitlab/jfronny/libjf/unsafe/JfLanguageAdapter.java index c700a7a..8261af5 100644 --- a/libjf-unsafe-v0/src/main/java/io/gitlab/jfronny/libjf/unsafe/JfLanguageAdapter.java +++ b/libjf-unsafe-v0/src/main/java/io/gitlab/jfronny/libjf/unsafe/JfLanguageAdapter.java @@ -17,6 +17,7 @@ public class JfLanguageAdapter implements LanguageAdapter { public native T create(net.fabricmc.loader.api.ModContainer mod, String value, Class type); static { + Logger.registerFactory(FLLogger::new); // Reset in mixin plugin Set flags = Flags.getBoolFlags("unsafe.unlock"); if (flags.stream().map(Flags.BooleanFlag::value).reduce(false, (left, right) -> left || right)) { SafeLog.warn("Unlocking classpath due to: " + flags.stream().map(Flags.BooleanFlag::source).collect(Collectors.joining(", "))); @@ -24,7 +25,6 @@ public class JfLanguageAdapter implements LanguageAdapter { } HiddenAnnotationExclusionStrategy.register(); GsonHolder.register(); - Logger.registerFactory(FLLogger::new); // Reset in mixin plugin DynamicEntry.execute("libjf:preEarly", UltraEarlyInit.class, s -> s.instance().init()); DynamicEntry.execute("libjf:early", UltraEarlyInit.class, s -> s.instance().init()); SafeLog.info("LibJF unsafe init completed"); diff --git a/libjf-unsafe-v0/src/main/java/io/gitlab/jfronny/libjf/unsafe/inject/FabricLauncherClassUnlocker.java b/libjf-unsafe-v0/src/main/java/io/gitlab/jfronny/libjf/unsafe/inject/FabricLauncherClassUnlocker.java index 89bdb38..f2181cc 100644 --- a/libjf-unsafe-v0/src/main/java/io/gitlab/jfronny/libjf/unsafe/inject/FabricLauncherClassUnlocker.java +++ b/libjf-unsafe-v0/src/main/java/io/gitlab/jfronny/libjf/unsafe/inject/FabricLauncherClassUnlocker.java @@ -3,14 +3,11 @@ package io.gitlab.jfronny.libjf.unsafe.inject; import net.fabricmc.api.EnvType; import net.fabricmc.loader.impl.launch.FabricLauncher; import net.fabricmc.loader.impl.launch.MappingConfiguration; -import net.fabricmc.loader.impl.util.UrlUtil; import net.fabricmc.loader.impl.util.log.Log; import net.fabricmc.loader.impl.util.log.LogCategory; import java.io.IOException; import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; import java.nio.file.Path; import java.util.Collection; import java.util.List; @@ -30,22 +27,13 @@ public record FabricLauncherClassUnlocker(KnotClassLoaderInterfaceAccessor class public void addToClassPath(Path path, String... allowedPrefixes) { Log.debug(LogCategory.KNOT, "Adding " + path + " to classpath."); - try { - URL url = UrlUtil.asUrl(path); - classLoader.getDelegate().setAllowedPrefixes(url, allowedPrefixes); - classLoader.addURL(url); - } catch (MalformedURLException e) { - throw new RuntimeException(e); - } + classLoader.getDelegate().setAllowedPrefixes(path, allowedPrefixes); + classLoader.getDelegate().addCodeSource(path); } @Override public void setAllowedPrefixes(Path path, String... prefixes) { - try { - classLoader.getDelegate().setAllowedPrefixes(UrlUtil.asUrl(path), prefixes); - } catch (MalformedURLException e) { - throw new RuntimeException(e); - } + classLoader.getDelegate().setAllowedPrefixes(path, prefixes); } @Override diff --git a/libjf-unsafe-v0/src/main/java/io/gitlab/jfronny/libjf/unsafe/inject/KnotClassDelegateAccessor.java b/libjf-unsafe-v0/src/main/java/io/gitlab/jfronny/libjf/unsafe/inject/KnotClassDelegateAccessor.java index 65d0e1a..a4afb14 100644 --- a/libjf-unsafe-v0/src/main/java/io/gitlab/jfronny/libjf/unsafe/inject/KnotClassDelegateAccessor.java +++ b/libjf-unsafe-v0/src/main/java/io/gitlab/jfronny/libjf/unsafe/inject/KnotClassDelegateAccessor.java @@ -2,21 +2,32 @@ package io.gitlab.jfronny.libjf.unsafe.inject; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.net.URL; +import java.nio.file.Path; public record KnotClassDelegateAccessor(Object delegate) { + private static final Method addCodeSourceMethod; private static final Method setAllowedPrefixesMethod; static { try { Class klazz = Class.forName("net.fabricmc.loader.impl.launch.knot.KnotClassDelegate"); - setAllowedPrefixesMethod = klazz.getDeclaredMethod("setAllowedPrefixes", URL.class, String[].class); + addCodeSourceMethod = klazz.getDeclaredMethod("addCodeSource", Path.class); + addCodeSourceMethod.setAccessible(true); + setAllowedPrefixesMethod = klazz.getDeclaredMethod("setAllowedPrefixes", Path.class, String[].class); setAllowedPrefixesMethod.setAccessible(true); } catch (ClassNotFoundException | NoSuchMethodException e) { throw new IllegalStateException("Could not build accessor for class delegate. This version of fabric is likely not yet supported", e); } } - public void setAllowedPrefixes(URL url, String... prefixes) { + public void addCodeSource(Path url) { + try { + addCodeSourceMethod.invoke(delegate, url); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new IllegalStateException("Could not invoke addURL on class loader. This version of fabric is likely not yet supported", e); + } + } + + public void setAllowedPrefixes(Path url, String... prefixes) { try { setAllowedPrefixesMethod.invoke(delegate, url, prefixes); } catch (IllegalAccessException | InvocationTargetException e) { diff --git a/libjf-unsafe-v0/src/main/java/io/gitlab/jfronny/libjf/unsafe/inject/KnotClassLoaderInterfaceAccessor.java b/libjf-unsafe-v0/src/main/java/io/gitlab/jfronny/libjf/unsafe/inject/KnotClassLoaderInterfaceAccessor.java index 5b26a39..2291438 100644 --- a/libjf-unsafe-v0/src/main/java/io/gitlab/jfronny/libjf/unsafe/inject/KnotClassLoaderInterfaceAccessor.java +++ b/libjf-unsafe-v0/src/main/java/io/gitlab/jfronny/libjf/unsafe/inject/KnotClassLoaderInterfaceAccessor.java @@ -2,16 +2,12 @@ package io.gitlab.jfronny.libjf.unsafe.inject; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.net.URL; public record KnotClassLoaderInterfaceAccessor(ClassLoader loader) { - private static final Method addURLMethod; private static final Method getDelegateMethod; static { try { - Class klazz = Class.forName("net.fabricmc.loader.impl.launch.knot.KnotClassLoaderInterface"); - addURLMethod = klazz.getDeclaredMethod("addURL", URL.class); - addURLMethod.setAccessible(true); + Class klazz = Class.forName("net.fabricmc.loader.impl.launch.knot.KnotClassLoader"); getDelegateMethod = klazz.getDeclaredMethod("getDelegate"); getDelegateMethod.setAccessible(true); } catch (ClassNotFoundException | NoSuchMethodException e) { @@ -19,14 +15,6 @@ public record KnotClassLoaderInterfaceAccessor(ClassLoader loader) { } } - public void addURL(URL url) { - try { - addURLMethod.invoke(loader, url); - } catch (IllegalAccessException | InvocationTargetException e) { - throw new IllegalStateException("Could not invoke addURL on class loader. This version of fabric is likely not yet supported", e); - } - } - public KnotClassDelegateAccessor getDelegate() { try { return new KnotClassDelegateAccessor(getDelegateMethod.invoke(loader)); diff --git a/libjf-unsafe-v0/src/testmod/resources/fabric.mod.json b/libjf-unsafe-v0/src/testmod/resources/fabric.mod.json index 0d54739..0d79f3b 100644 --- a/libjf-unsafe-v0/src/testmod/resources/fabric.mod.json +++ b/libjf-unsafe-v0/src/testmod/resources/fabric.mod.json @@ -14,7 +14,8 @@ "custom": { "libjf": { "asm.export": true, - "asm.log": true + "asm.log": true, + "unsafe.unlock": true } } } \ No newline at end of file