From d297e373b499eec45db6547438156bab99925181 Mon Sep 17 00:00:00 2001 From: Dan Mulloy Date: Mon, 6 May 2019 20:32:20 -0400 Subject: [PATCH] Specifically clone Spigot's chat components to fix stack overflow Addresses #601 --- .../reflect/cloning/BukkitCloner.java | 4 ++++ .../protocol/wrappers/ComponentConverter.java | 8 ++++++++ .../protocol/events/PacketContainerTest.java | 20 +++++++++---------- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/comphenix/protocol/reflect/cloning/BukkitCloner.java b/src/main/java/com/comphenix/protocol/reflect/cloning/BukkitCloner.java index 693f6303..e964b0e8 100644 --- a/src/main/java/com/comphenix/protocol/reflect/cloning/BukkitCloner.java +++ b/src/main/java/com/comphenix/protocol/reflect/cloning/BukkitCloner.java @@ -31,6 +31,8 @@ import com.comphenix.protocol.wrappers.*; import com.comphenix.protocol.wrappers.nbt.NbtFactory; import com.google.common.collect.Maps; +import net.md_5.bungee.api.chat.BaseComponent; + /** * Represents an object that can clone a specific list of Bukkit- and Minecraft-related objects. * @@ -78,6 +80,8 @@ public class BukkitCloner implements Cloner { fromManual(MinecraftReflection::getNonNullListClass, source -> nonNullListCloner().clone(source)); fromWrapper(MinecraftReflection::getNBTBaseClass, NbtFactory::fromNMS); fromWrapper(MinecraftReflection::getIChatBaseComponentClass, WrappedChatComponent::fromHandle); + fromManual(ComponentConverter::getBaseComponentArrayClass, source -> + ComponentConverter.clone((BaseComponent[]) source)); } private Function findCloner(Class type) { diff --git a/src/main/java/com/comphenix/protocol/wrappers/ComponentConverter.java b/src/main/java/com/comphenix/protocol/wrappers/ComponentConverter.java index d2a132c6..8b20bec7 100644 --- a/src/main/java/com/comphenix/protocol/wrappers/ComponentConverter.java +++ b/src/main/java/com/comphenix/protocol/wrappers/ComponentConverter.java @@ -47,4 +47,12 @@ public final class ComponentConverter { public static WrappedChatComponent fromBaseComponent(BaseComponent... components) { return WrappedChatComponent.fromJson(ComponentSerializer.toString(components)); } + + public static Class getBaseComponentArrayClass() { + return BaseComponent[].class; + } + + public static BaseComponent[] clone(BaseComponent... components) { + return ComponentSerializer.parse(ComponentSerializer.toString(components)); + } } diff --git a/src/test/java/com/comphenix/protocol/events/PacketContainerTest.java b/src/test/java/com/comphenix/protocol/events/PacketContainerTest.java index 6fb89397..eb00c4f3 100644 --- a/src/test/java/com/comphenix/protocol/events/PacketContainerTest.java +++ b/src/test/java/com/comphenix/protocol/events/PacketContainerTest.java @@ -16,6 +16,10 @@ */ package com.comphenix.protocol.events; +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.util.*; + import com.comphenix.protocol.BukkitInitialization; import com.comphenix.protocol.PacketType; import com.comphenix.protocol.injector.PacketConstructor; @@ -51,10 +55,6 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.core.classloader.annotations.PowerMockIgnore; -import java.lang.reflect.Array; -import java.lang.reflect.Field; -import java.util.*; - import static com.comphenix.protocol.utility.TestUtils.*; import static org.junit.Assert.*; @@ -66,17 +66,18 @@ public class PacketContainerTest { // Helper converters private EquivalentConverter watchConvert = BukkitConverters.getDataWatcherConverter(); private EquivalentConverter itemConvert = BukkitConverters.getItemStackConverter(); + private static BaseComponent[] TEST_COMPONENT; @BeforeClass public static void initializeBukkit() { BukkitInitialization.initializeItemMeta(); BukkitInitialization.initializePackage(); - TEST_COMPONENT = ComponentConverter.fromBaseComponent( + TEST_COMPONENT = new ComponentBuilder("Hit or miss?") .event(new ClickEvent(ClickEvent.Action.OPEN_URL, "http://reddit.com")) .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new BaseComponent[] { new TextComponent("The \"front page\" of the internet") })) - .append("I guess they never miss, huh?").create()); + .append("I guess they never miss, huh?").create(); } private void testPrimitive(StructureModifier modifier, int index, T initialValue, T testValue) { @@ -511,8 +512,6 @@ public class PacketContainerTest { PacketType.Play.Server.TAGS ); - private static WrappedChatComponent TEST_COMPONENT; - @Test public void testDeepClone() { // Try constructing all the packets @@ -536,10 +535,11 @@ public class PacketContainerTest { "String"), new WrappedWatchableObject(new WrappedDataWatcherObject(0, Registry.get(Float.class)), 1.0F), new WrappedWatchableObject(new WrappedDataWatcherObject(0, Registry.getChatComponentSerializer(true)), - com.google.common.base.Optional.of(TEST_COMPONENT.getHandle())) + com.google.common.base.Optional.of(ComponentConverter.fromBaseComponent(TEST_COMPONENT).getHandle())) )); } else if (type == PacketType.Play.Server.CHAT) { - constructed.getChatComponents().write(0, TEST_COMPONENT); + constructed.getChatComponents().write(0, ComponentConverter.fromBaseComponent(TEST_COMPONENT)); + //constructed.getModifier().write(1, TEST_COMPONENT); } // Clone the packet