From 12556fa98f9d500c2497e5a422e10ed248a9cfb3 Mon Sep 17 00:00:00 2001 From: CrazyDev22 Date: Tue, 21 May 2024 16:38:28 +0200 Subject: [PATCH] improve iris world protection --- .../iris/core/nms/v1_19_R1/NMSBinding.java | 33 +++++++++++----- .../iris/core/nms/v1_19_R2/NMSBinding.java | 33 +++++++++++----- .../iris/core/nms/v1_19_R3/NMSBinding.java | 33 +++++++++++----- .../iris/core/nms/v1_20_R1/NMSBinding.java | 33 +++++++++++----- .../iris/core/nms/v1_20_R2/NMSBinding.java | 33 +++++++++++----- .../iris/core/nms/v1_20_R3/NMSBinding.java | 38 ++++++++++++++----- .../iris/core/nms/v1_20_R4/NMSBinding.java | 33 +++++++++++----- 7 files changed, 173 insertions(+), 63 deletions(-) diff --git a/nms/v1_19_R1/src/main/java/com/volmit/iris/core/nms/v1_19_R1/NMSBinding.java b/nms/v1_19_R1/src/main/java/com/volmit/iris/core/nms/v1_19_R1/NMSBinding.java index 2033666da..264d0abce 100644 --- a/nms/v1_19_R1/src/main/java/com/volmit/iris/core/nms/v1_19_R1/NMSBinding.java +++ b/nms/v1_19_R1/src/main/java/com/volmit/iris/core/nms/v1_19_R1/NMSBinding.java @@ -15,6 +15,7 @@ import java.util.Optional; import java.util.Vector; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicInteger; +import java.util.logging.Logger; import com.google.common.base.Preconditions; import com.google.gson.JsonElement; @@ -714,10 +715,10 @@ public class NMSBinding implements INMSBinding { try { Iris.info("Injecting Bukkit"); new ByteBuddy() - .redefine(WorldCreator.class) - .visit(Advice.to(WorldCreatorAdvice.class).on(ElementMatchers.isConstructor().and(ElementMatchers.takesArguments(String.class)))) + .redefine(CraftServer.class) + .visit(Advice.to(CraftServerAdvice.class).on(ElementMatchers.isMethod().and(ElementMatchers.takesArguments(WorldCreator.class)))) .make() - .load(WorldCreator.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent()); + .load(CraftServer.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent()); new ByteBuddy() .redefine(ServerLevel.class) .visit(Advice.to(ServerLevelAdvice.class).on(ElementMatchers.isConstructor().and(ElementMatchers.takesArguments(MinecraftServer.class, Executor.class, LevelStorageSource.LevelStorageAccess.class, @@ -750,10 +751,10 @@ public class NMSBinding implements INMSBinding { } } - private static class WorldCreatorAdvice { - @Advice.OnMethodEnter - static void enter(@Advice.Argument(0) String name) { - File isIrisWorld = new File(name, "iris"); + private static class CraftServerAdvice { + @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class) + static boolean enter(@Advice.This CraftServer self, @Advice.Argument(0) WorldCreator creator) { + File isIrisWorld = new File(self.getWorldContainer(), creator.name() + "/iris"); boolean isFromIris = false; StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); for (StackTraceElement stack : stackTrace) { @@ -762,8 +763,22 @@ public class NMSBinding implements INMSBinding { break; } } - if (!isFromIris) { - Preconditions.checkArgument(!isIrisWorld.exists(), "Only Iris can load Iris Worlds!"); + if (isIrisWorld.exists() && !isFromIris) { + var logger = Logger.getLogger("Iris"); + logger.warning("detected another Plugin trying to load " + creator.name() + ". This is not supported and will be ignored."); + + if (System.getProperty("iris.debug", "false").equals("true")) { + new RuntimeException().printStackTrace(); + } + return true; + } + return false; + } + + @Advice.OnMethodExit + static void exit(@Advice.Enter boolean bool, @Advice.Return(readOnly = false) World returned) { + if (bool) { + returned = null; } } } diff --git a/nms/v1_19_R2/src/main/java/com/volmit/iris/core/nms/v1_19_R2/NMSBinding.java b/nms/v1_19_R2/src/main/java/com/volmit/iris/core/nms/v1_19_R2/NMSBinding.java index ed1a4a09e..6af6c20bb 100644 --- a/nms/v1_19_R2/src/main/java/com/volmit/iris/core/nms/v1_19_R2/NMSBinding.java +++ b/nms/v1_19_R2/src/main/java/com/volmit/iris/core/nms/v1_19_R2/NMSBinding.java @@ -15,6 +15,7 @@ import java.util.Optional; import java.util.Vector; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicInteger; +import java.util.logging.Logger; import com.google.common.base.Preconditions; import com.google.gson.JsonElement; @@ -715,10 +716,10 @@ public class NMSBinding implements INMSBinding { try { Iris.info("Injecting Bukkit"); new ByteBuddy() - .redefine(WorldCreator.class) - .visit(Advice.to(WorldCreatorAdvice.class).on(ElementMatchers.isConstructor().and(ElementMatchers.takesArguments(String.class)))) + .redefine(CraftServer.class) + .visit(Advice.to(CraftServerAdvice.class).on(ElementMatchers.isMethod().and(ElementMatchers.takesArguments(WorldCreator.class)))) .make() - .load(WorldCreator.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent()); + .load(CraftServer.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent()); new ByteBuddy() .redefine(ServerLevel.class) .visit(Advice.to(ServerLevelAdvice.class).on(ElementMatchers.isConstructor().and(ElementMatchers.takesArguments(MinecraftServer.class, Executor.class, LevelStorageSource.LevelStorageAccess.class, @@ -750,10 +751,10 @@ public class NMSBinding implements INMSBinding { } } - private static class WorldCreatorAdvice { - @Advice.OnMethodEnter - static void enter(@Advice.Argument(0) String name) { - File isIrisWorld = new File(name, "iris"); + private static class CraftServerAdvice { + @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class) + static boolean enter(@Advice.This CraftServer self, @Advice.Argument(0) WorldCreator creator) { + File isIrisWorld = new File(self.getWorldContainer(), creator.name() + "/iris"); boolean isFromIris = false; StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); for (StackTraceElement stack : stackTrace) { @@ -762,8 +763,22 @@ public class NMSBinding implements INMSBinding { break; } } - if (!isFromIris) { - Preconditions.checkArgument(!isIrisWorld.exists(), "Only Iris can load Iris Worlds!"); + if (isIrisWorld.exists() && !isFromIris) { + var logger = Logger.getLogger("Iris"); + logger.warning("detected another Plugin trying to load " + creator.name() + ". This is not supported and will be ignored."); + + if (System.getProperty("iris.debug", "false").equals("true")) { + new RuntimeException().printStackTrace(); + } + return true; + } + return false; + } + + @Advice.OnMethodExit + static void exit(@Advice.Enter boolean bool, @Advice.Return(readOnly = false) World returned) { + if (bool) { + returned = null; } } } diff --git a/nms/v1_19_R3/src/main/java/com/volmit/iris/core/nms/v1_19_R3/NMSBinding.java b/nms/v1_19_R3/src/main/java/com/volmit/iris/core/nms/v1_19_R3/NMSBinding.java index 7499562de..4a33fed2d 100644 --- a/nms/v1_19_R3/src/main/java/com/volmit/iris/core/nms/v1_19_R3/NMSBinding.java +++ b/nms/v1_19_R3/src/main/java/com/volmit/iris/core/nms/v1_19_R3/NMSBinding.java @@ -15,6 +15,7 @@ import java.util.Optional; import java.util.Vector; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicInteger; +import java.util.logging.Logger; import com.google.common.base.Preconditions; import com.google.gson.JsonElement; @@ -719,10 +720,10 @@ public class NMSBinding implements INMSBinding { try { Iris.info("Injecting Bukkit"); new ByteBuddy() - .redefine(WorldCreator.class) - .visit(Advice.to(WorldCreatorAdvice.class).on(ElementMatchers.isConstructor().and(ElementMatchers.takesArguments(String.class)))) + .redefine(CraftServer.class) + .visit(Advice.to(CraftServerAdvice.class).on(ElementMatchers.isMethod().and(ElementMatchers.takesArguments(WorldCreator.class)))) .make() - .load(WorldCreator.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent()); + .load(CraftServer.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent()); new ByteBuddy() .redefine(ServerLevel.class) .visit(Advice.to(ServerLevelAdvice.class).on(ElementMatchers.isConstructor().and(ElementMatchers.takesArguments(MinecraftServer.class, Executor.class, LevelStorageSource.LevelStorageAccess.class, @@ -754,10 +755,10 @@ public class NMSBinding implements INMSBinding { } } - private static class WorldCreatorAdvice { - @Advice.OnMethodEnter - static void enter(@Advice.Argument(0) String name) { - File isIrisWorld = new File(name, "iris"); + private static class CraftServerAdvice { + @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class) + static boolean enter(@Advice.This CraftServer self, @Advice.Argument(0) WorldCreator creator) { + File isIrisWorld = new File(self.getWorldContainer(), creator.name() + "/iris"); boolean isFromIris = false; StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); for (StackTraceElement stack : stackTrace) { @@ -766,8 +767,22 @@ public class NMSBinding implements INMSBinding { break; } } - if (!isFromIris) { - Preconditions.checkArgument(!isIrisWorld.exists(), "Only Iris can load Iris Worlds!"); + if (isIrisWorld.exists() && !isFromIris) { + var logger = Logger.getLogger("Iris"); + logger.warning("detected another Plugin trying to load " + creator.name() + ". This is not supported and will be ignored."); + + if (System.getProperty("iris.debug", "false").equals("true")) { + new RuntimeException().printStackTrace(); + } + return true; + } + return false; + } + + @Advice.OnMethodExit + static void exit(@Advice.Enter boolean bool, @Advice.Return(readOnly = false) World returned) { + if (bool) { + returned = null; } } } diff --git a/nms/v1_20_R1/src/main/java/com/volmit/iris/core/nms/v1_20_R1/NMSBinding.java b/nms/v1_20_R1/src/main/java/com/volmit/iris/core/nms/v1_20_R1/NMSBinding.java index 52102bc32..1451edd92 100644 --- a/nms/v1_20_R1/src/main/java/com/volmit/iris/core/nms/v1_20_R1/NMSBinding.java +++ b/nms/v1_20_R1/src/main/java/com/volmit/iris/core/nms/v1_20_R1/NMSBinding.java @@ -94,6 +94,7 @@ import java.util.Optional; import java.util.Vector; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicInteger; +import java.util.logging.Logger; public class NMSBinding implements INMSBinding { @@ -716,10 +717,10 @@ public class NMSBinding implements INMSBinding { try { Iris.info("Injecting Bukkit"); new ByteBuddy() - .redefine(WorldCreator.class) - .visit(Advice.to(WorldCreatorAdvice.class).on(ElementMatchers.isConstructor().and(ElementMatchers.takesArguments(String.class)))) + .redefine(CraftServer.class) + .visit(Advice.to(CraftServerAdvice.class).on(ElementMatchers.isMethod().and(ElementMatchers.takesArguments(WorldCreator.class)))) .make() - .load(WorldCreator.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent()); + .load(CraftServer.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent()); new ByteBuddy() .redefine(ServerLevel.class) .visit(Advice.to(ServerLevelAdvice.class).on(ElementMatchers.isConstructor().and(ElementMatchers.takesArguments(MinecraftServer.class, Executor.class, LevelStorageSource.LevelStorageAccess.class, @@ -751,10 +752,10 @@ public class NMSBinding implements INMSBinding { } } - private static class WorldCreatorAdvice { - @Advice.OnMethodEnter - static void enter(@Advice.Argument(0) String name) { - File isIrisWorld = new File(name, "iris"); + private static class CraftServerAdvice { + @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class) + static boolean enter(@Advice.This CraftServer self, @Advice.Argument(0) WorldCreator creator) { + File isIrisWorld = new File(self.getWorldContainer(), creator.name() + "/iris"); boolean isFromIris = false; StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); for (StackTraceElement stack : stackTrace) { @@ -763,8 +764,22 @@ public class NMSBinding implements INMSBinding { break; } } - if (!isFromIris) { - Preconditions.checkArgument(!isIrisWorld.exists(), "Only Iris can load Iris Worlds!"); + if (isIrisWorld.exists() && !isFromIris) { + var logger = Logger.getLogger("Iris"); + logger.warning("detected another Plugin trying to load " + creator.name() + ". This is not supported and will be ignored."); + + if (System.getProperty("iris.debug", "false").equals("true")) { + new RuntimeException().printStackTrace(); + } + return true; + } + return false; + } + + @Advice.OnMethodExit + static void exit(@Advice.Enter boolean bool, @Advice.Return(readOnly = false) World returned) { + if (bool) { + returned = null; } } } diff --git a/nms/v1_20_R2/src/main/java/com/volmit/iris/core/nms/v1_20_R2/NMSBinding.java b/nms/v1_20_R2/src/main/java/com/volmit/iris/core/nms/v1_20_R2/NMSBinding.java index 63e36f06b..d74e7c125 100644 --- a/nms/v1_20_R2/src/main/java/com/volmit/iris/core/nms/v1_20_R2/NMSBinding.java +++ b/nms/v1_20_R2/src/main/java/com/volmit/iris/core/nms/v1_20_R2/NMSBinding.java @@ -15,6 +15,7 @@ import java.util.Optional; import java.util.Vector; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicInteger; +import java.util.logging.Logger; import com.google.common.base.Preconditions; import com.google.gson.JsonElement; @@ -721,10 +722,10 @@ public class NMSBinding implements INMSBinding { try { Iris.info("Injecting Bukkit"); new ByteBuddy() - .redefine(WorldCreator.class) - .visit(Advice.to(WorldCreatorAdvice.class).on(ElementMatchers.isConstructor().and(ElementMatchers.takesArguments(String.class)))) + .redefine(CraftServer.class) + .visit(Advice.to(CraftServerAdvice.class).on(ElementMatchers.isMethod().and(ElementMatchers.takesArguments(WorldCreator.class)))) .make() - .load(WorldCreator.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent()); + .load(CraftServer.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent()); new ByteBuddy() .redefine(ServerLevel.class) .visit(Advice.to(ServerLevelAdvice.class).on(ElementMatchers.isConstructor().and(ElementMatchers.takesArguments(MinecraftServer.class, Executor.class, LevelStorageSource.LevelStorageAccess.class, @@ -756,10 +757,10 @@ public class NMSBinding implements INMSBinding { } } - private static class WorldCreatorAdvice { - @Advice.OnMethodEnter - static void enter(@Advice.Argument(0) String name) { - File isIrisWorld = new File(name, "iris"); + private static class CraftServerAdvice { + @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class) + static boolean enter(@Advice.This CraftServer self, @Advice.Argument(0) WorldCreator creator) { + File isIrisWorld = new File(self.getWorldContainer(), creator.name() + "/iris"); boolean isFromIris = false; StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); for (StackTraceElement stack : stackTrace) { @@ -768,8 +769,22 @@ public class NMSBinding implements INMSBinding { break; } } - if (!isFromIris) { - Preconditions.checkArgument(!isIrisWorld.exists(), "Only Iris can load Iris Worlds!"); + if (isIrisWorld.exists() && !isFromIris) { + var logger = Logger.getLogger("Iris"); + logger.warning("detected another Plugin trying to load " + creator.name() + ". This is not supported and will be ignored."); + + if (System.getProperty("iris.debug", "false").equals("true")) { + new RuntimeException().printStackTrace(); + } + return true; + } + return false; + } + + @Advice.OnMethodExit + static void exit(@Advice.Enter boolean bool, @Advice.Return(readOnly = false) World returned) { + if (bool) { + returned = null; } } } diff --git a/nms/v1_20_R3/src/main/java/com/volmit/iris/core/nms/v1_20_R3/NMSBinding.java b/nms/v1_20_R3/src/main/java/com/volmit/iris/core/nms/v1_20_R3/NMSBinding.java index bb056b10e..79ec5e942 100644 --- a/nms/v1_20_R3/src/main/java/com/volmit/iris/core/nms/v1_20_R3/NMSBinding.java +++ b/nms/v1_20_R3/src/main/java/com/volmit/iris/core/nms/v1_20_R3/NMSBinding.java @@ -11,6 +11,7 @@ import java.lang.reflect.Modifier; import java.util.*; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicInteger; +import java.util.logging.Logger; import com.google.common.base.Preconditions; import com.google.gson.JsonElement; @@ -27,7 +28,12 @@ import com.volmit.iris.util.format.C; import it.unimi.dsi.fastutil.objects.Reference2IntMap; import net.bytebuddy.ByteBuddy; import net.bytebuddy.asm.Advice; +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.dynamic.loading.ClassReloadingStrategy; +import net.bytebuddy.implementation.bytecode.StackManipulation; +import net.bytebuddy.implementation.bytecode.assign.Assigner; +import net.bytebuddy.implementation.bytecode.member.MethodInvocation; import net.bytebuddy.matcher.ElementMatchers; import net.minecraft.core.IdMapper; import net.minecraft.core.MappedRegistry; @@ -725,10 +731,10 @@ public class NMSBinding implements INMSBinding { try { Iris.info("Injecting Bukkit"); new ByteBuddy() - .redefine(WorldCreator.class) - .visit(Advice.to(WorldCreatorAdvice.class).on(ElementMatchers.isConstructor().and(ElementMatchers.takesArguments(String.class)))) + .redefine(CraftServer.class) + .visit(Advice.to(CraftServerAdvice.class).on(ElementMatchers.isMethod().and(ElementMatchers.takesArguments(WorldCreator.class)))) .make() - .load(WorldCreator.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent()); + .load(CraftServer.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent()); new ByteBuddy() .redefine(ServerLevel.class) .visit(Advice.to(ServerLevelAdvice.class).on(ElementMatchers.isConstructor().and(ElementMatchers.takesArguments(MinecraftServer.class, Executor.class, LevelStorageSource.LevelStorageAccess.class, @@ -765,10 +771,10 @@ public class NMSBinding implements INMSBinding { } } - private static class WorldCreatorAdvice { - @Advice.OnMethodEnter - static void enter(@Advice.Argument(0) String name) { - File isIrisWorld = new File(name, "iris"); + private static class CraftServerAdvice { + @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class) + static boolean enter(@Advice.This CraftServer self, @Advice.Argument(0) WorldCreator creator) { + File isIrisWorld = new File(self.getWorldContainer(), creator.name() + "/iris"); boolean isFromIris = false; StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); for (StackTraceElement stack : stackTrace) { @@ -777,8 +783,22 @@ public class NMSBinding implements INMSBinding { break; } } - if (!isFromIris) { - Preconditions.checkArgument(!isIrisWorld.exists(), "Only Iris can load Iris Worlds!"); + if (isIrisWorld.exists() && !isFromIris) { + var logger = Logger.getLogger("Iris"); + logger.warning("detected another Plugin trying to load " + creator.name() + ". This is not supported and will be ignored."); + + if (System.getProperty("iris.debug", "false").equals("true")) { + new RuntimeException().printStackTrace(); + } + return true; + } + return false; + } + + @Advice.OnMethodExit + static void exit(@Advice.Enter boolean bool, @Advice.Return(readOnly = false) World returned) { + if (bool) { + returned = null; } } } diff --git a/nms/v1_20_R4/src/main/java/com/volmit/iris/core/nms/v1_20_R4/NMSBinding.java b/nms/v1_20_R4/src/main/java/com/volmit/iris/core/nms/v1_20_R4/NMSBinding.java index 2c989e893..1ecfd0f7e 100644 --- a/nms/v1_20_R4/src/main/java/com/volmit/iris/core/nms/v1_20_R4/NMSBinding.java +++ b/nms/v1_20_R4/src/main/java/com/volmit/iris/core/nms/v1_20_R4/NMSBinding.java @@ -15,6 +15,7 @@ import java.util.Optional; import java.util.Vector; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicInteger; +import java.util.logging.Logger; import com.google.common.base.Preconditions; import com.google.gson.JsonElement; @@ -712,10 +713,10 @@ public class NMSBinding implements INMSBinding { try { Iris.info("Injecting Bukkit"); new ByteBuddy() - .redefine(WorldCreator.class) - .visit(Advice.to(WorldCreatorAdvice.class).on(ElementMatchers.isConstructor().and(ElementMatchers.takesArguments(String.class)))) + .redefine(CraftServer.class) + .visit(Advice.to(CraftServerAdvice.class).on(ElementMatchers.isMethod().and(ElementMatchers.takesArguments(WorldCreator.class)))) .make() - .load(WorldCreator.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent()); + .load(CraftServer.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent()); new ByteBuddy() .redefine(ServerLevel.class) .visit(Advice.to(ServerLevelAdvice.class).on(ElementMatchers.isConstructor().and(ElementMatchers.takesArguments(MinecraftServer.class, Executor.class, LevelStorageSource.LevelStorageAccess.class, @@ -747,10 +748,10 @@ public class NMSBinding implements INMSBinding { } } - private static class WorldCreatorAdvice { - @Advice.OnMethodEnter - static void enter(@Advice.Argument(0) String name) { - File isIrisWorld = new File(name, "iris"); + private static class CraftServerAdvice { + @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class) + static boolean enter(@Advice.This CraftServer self, @Advice.Argument(0) WorldCreator creator) { + File isIrisWorld = new File(self.getWorldContainer(), creator.name() + "/iris"); boolean isFromIris = false; StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); for (StackTraceElement stack : stackTrace) { @@ -759,8 +760,22 @@ public class NMSBinding implements INMSBinding { break; } } - if (!isFromIris) { - Preconditions.checkArgument(!isIrisWorld.exists(), "Only Iris can load Iris Worlds!"); + if (isIrisWorld.exists() && !isFromIris) { + var logger = Logger.getLogger("Iris"); + logger.warning("detected another Plugin trying to load " + creator.name() + ". This is not supported and will be ignored."); + + if (System.getProperty("iris.debug", "false").equals("true")) { + new RuntimeException().printStackTrace(); + } + return true; + } + return false; + } + + @Advice.OnMethodExit + static void exit(@Advice.Enter boolean bool, @Advice.Return(readOnly = false) World returned) { + if (bool) { + returned = null; } } }