diff --git a/api/src/main/java/net/md_5/bungee/chat/BaseComponentSerializer.java b/api/src/main/java/net/md_5/bungee/chat/BaseComponentSerializer.java index 92c13d93..344cb38a 100644 --- a/api/src/main/java/net/md_5/bungee/chat/BaseComponentSerializer.java +++ b/api/src/main/java/net/md_5/bungee/chat/BaseComponentSerializer.java @@ -1,5 +1,6 @@ package net.md_5.bungee.chat; +import com.google.common.base.Preconditions; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonObject; import com.google.gson.JsonSerializationContext; @@ -72,6 +73,8 @@ public class BaseComponentSerializer protected void serialize(JsonObject object, BaseComponent component, JsonSerializationContext context) { + Preconditions.checkArgument( !ComponentSerializer.serializedComponents.get().contains( component ), "Component loop" ); + ComponentSerializer.serializedComponents.get().add( component ); if ( component.getColorRaw() != null ) { object.addProperty( "color", component.getColorRaw().getName() ); diff --git a/api/src/main/java/net/md_5/bungee/chat/ComponentSerializer.java b/api/src/main/java/net/md_5/bungee/chat/ComponentSerializer.java index d097d408..d847fabd 100644 --- a/api/src/main/java/net/md_5/bungee/chat/ComponentSerializer.java +++ b/api/src/main/java/net/md_5/bungee/chat/ComponentSerializer.java @@ -14,6 +14,7 @@ import net.md_5.bungee.api.chat.TextComponent; import net.md_5.bungee.api.chat.TranslatableComponent; import java.lang.reflect.Type; +import java.util.HashSet; public class ComponentSerializer implements JsonSerializer, JsonDeserializer { @@ -24,6 +25,15 @@ public class ComponentSerializer implements JsonSerializer, JsonD registerTypeAdapter( TranslatableComponent.class, new TranslatableComponentSerializer() ). create(); + public final static ThreadLocal> serializedComponents = new ThreadLocal>() + { + @Override + protected HashSet initialValue() + { + return new HashSet<>(); + } + }; + public static BaseComponent[] parse(String json) { if ( json.startsWith( "[" ) ) @@ -64,6 +74,11 @@ public class ComponentSerializer implements JsonSerializer, JsonD @Override public JsonElement serialize(BaseComponent src, Type typeOfSrc, JsonSerializationContext context) { - return context.serialize( src, src.getClass() ); + try { + return context.serialize( src, src.getClass() ); + } finally + { + serializedComponents.get().clear(); + } } } diff --git a/proxy/src/test/java/net/md_5/bungee/chat/ComponentsTest.java b/proxy/src/test/java/net/md_5/bungee/chat/ComponentsTest.java index c206e60f..8ba0d3c6 100644 --- a/proxy/src/test/java/net/md_5/bungee/chat/ComponentsTest.java +++ b/proxy/src/test/java/net/md_5/bungee/chat/ComponentsTest.java @@ -80,4 +80,22 @@ public class ComponentsTest + "World" + ChatColor.YELLOW + ChatColor.BOLD + "!", BaseComponent.toLegacyText( components ) ); } + @Test(expected = IllegalArgumentException.class) + public void testLoopSimple() { + TextComponent component = new TextComponent( "Testing" ); + component.addExtra( component ); + ComponentSerializer.toString( component ); + } + + @Test(expected = IllegalArgumentException.class) + public void testLoopComplex() { + TextComponent a = new TextComponent( "A" ); + TextComponent b = new TextComponent( "B" ); + TextComponent c = new TextComponent( "C" ); + a.addExtra( b ); + b.addExtra( c ); + c.addExtra( a ); + ComponentSerializer.toString( a ); + } + }