From b60c1bdb370bbedcd444736ea849c157d7c5c5f1 Mon Sep 17 00:00:00 2001 From: md_5 Date: Thu, 5 Jun 2025 21:00:01 +1000 Subject: [PATCH] Limit length of chat string conversions --- .../md_5/bungee/api/chat/BaseComponent.java | 42 ++++++++++++++++--- .../bungee/api/chat/KeybindComponent.java | 4 +- .../md_5/bungee/api/chat/ScoreComponent.java | 4 +- .../bungee/api/chat/SelectorComponent.java | 4 +- .../md_5/bungee/api/chat/TextComponent.java | 4 +- .../api/chat/TranslatableComponent.java | 6 +-- .../md_5/bungee/api/chat/ComponentsTest.java | 9 ++++ 7 files changed, 57 insertions(+), 16 deletions(-) diff --git a/chat/src/main/java/net/md_5/bungee/api/chat/BaseComponent.java b/chat/src/main/java/net/md_5/bungee/api/chat/BaseComponent.java index 005c7c49..6ea86841 100644 --- a/chat/src/main/java/net/md_5/bungee/api/chat/BaseComponent.java +++ b/chat/src/main/java/net/md_5/bungee/api/chat/BaseComponent.java @@ -4,6 +4,7 @@ import java.awt.Color; import java.util.ArrayList; import java.util.List; import lombok.AccessLevel; +import lombok.Data; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; @@ -677,11 +678,11 @@ public abstract class BaseComponent public String toPlainText() { StringBuilder builder = new StringBuilder(); - toPlainText( builder ); + toPlainText( new LimitedStringVisitor( builder, Short.MAX_VALUE ) ); return builder.toString(); } - void toPlainText(StringBuilder builder) + void toPlainText(StringVisitor builder) { if ( extra != null ) { @@ -701,11 +702,11 @@ public abstract class BaseComponent public String toLegacyText() { StringBuilder builder = new StringBuilder(); - toLegacyText( builder ); + toLegacyText( new LimitedStringVisitor( builder, Short.MAX_VALUE ) ); return builder.toString(); } - void toLegacyText(StringBuilder builder) + void toLegacyText(StringVisitor builder) { if ( extra != null ) { @@ -716,7 +717,7 @@ public abstract class BaseComponent } } - void addFormat(StringBuilder builder) + void addFormat(StringVisitor builder) { builder.append( getColor() ); if ( isBold() ) @@ -740,4 +741,35 @@ public abstract class BaseComponent builder.append( ChatColor.MAGIC ); } } + + @FunctionalInterface + protected static interface StringVisitor + { + + void append(String s); + + default void append(Object obj) + { + append( String.valueOf( obj ) ); + } + } + + @Data + protected static class LimitedStringVisitor implements StringVisitor + { + + private final StringBuilder builder; + private final int maxLength; + + @Override + public void append(String s) + { + if ( builder.length() >= maxLength ) + { + throw new IllegalArgumentException( "String exceeded maximum length " + maxLength ); + } + + builder.append( s ); + } + } } diff --git a/chat/src/main/java/net/md_5/bungee/api/chat/KeybindComponent.java b/chat/src/main/java/net/md_5/bungee/api/chat/KeybindComponent.java index 4cefe259..777acffb 100644 --- a/chat/src/main/java/net/md_5/bungee/api/chat/KeybindComponent.java +++ b/chat/src/main/java/net/md_5/bungee/api/chat/KeybindComponent.java @@ -50,14 +50,14 @@ public final class KeybindComponent extends BaseComponent } @Override - protected void toPlainText(StringBuilder builder) + protected void toPlainText(StringVisitor builder) { builder.append( getKeybind() ); super.toPlainText( builder ); } @Override - protected void toLegacyText(StringBuilder builder) + protected void toLegacyText(StringVisitor builder) { addFormat( builder ); builder.append( getKeybind() ); diff --git a/chat/src/main/java/net/md_5/bungee/api/chat/ScoreComponent.java b/chat/src/main/java/net/md_5/bungee/api/chat/ScoreComponent.java index ebf7bb31..775988d6 100644 --- a/chat/src/main/java/net/md_5/bungee/api/chat/ScoreComponent.java +++ b/chat/src/main/java/net/md_5/bungee/api/chat/ScoreComponent.java @@ -85,14 +85,14 @@ public final class ScoreComponent extends BaseComponent } @Override - protected void toPlainText(StringBuilder builder) + protected void toPlainText(StringVisitor builder) { builder.append( this.value ); super.toPlainText( builder ); } @Override - protected void toLegacyText(StringBuilder builder) + protected void toLegacyText(StringVisitor builder) { addFormat( builder ); builder.append( this.value ); diff --git a/chat/src/main/java/net/md_5/bungee/api/chat/SelectorComponent.java b/chat/src/main/java/net/md_5/bungee/api/chat/SelectorComponent.java index ff1e260b..fc9e66d9 100644 --- a/chat/src/main/java/net/md_5/bungee/api/chat/SelectorComponent.java +++ b/chat/src/main/java/net/md_5/bungee/api/chat/SelectorComponent.java @@ -69,14 +69,14 @@ public final class SelectorComponent extends BaseComponent } @Override - protected void toPlainText(StringBuilder builder) + protected void toPlainText(StringVisitor builder) { builder.append( this.selector ); super.toPlainText( builder ); } @Override - protected void toLegacyText(StringBuilder builder) + protected void toLegacyText(StringVisitor builder) { addFormat( builder ); builder.append( this.selector ); diff --git a/chat/src/main/java/net/md_5/bungee/api/chat/TextComponent.java b/chat/src/main/java/net/md_5/bungee/api/chat/TextComponent.java index 0971a384..19d4bf58 100644 --- a/chat/src/main/java/net/md_5/bungee/api/chat/TextComponent.java +++ b/chat/src/main/java/net/md_5/bungee/api/chat/TextComponent.java @@ -280,14 +280,14 @@ public final class TextComponent extends BaseComponent } @Override - protected void toPlainText(StringBuilder builder) + protected void toPlainText(StringVisitor builder) { builder.append( text ); super.toPlainText( builder ); } @Override - protected void toLegacyText(StringBuilder builder) + protected void toLegacyText(StringVisitor builder) { addFormat( builder ); builder.append( text ); diff --git a/chat/src/main/java/net/md_5/bungee/api/chat/TranslatableComponent.java b/chat/src/main/java/net/md_5/bungee/api/chat/TranslatableComponent.java index 402f72be..e83413a8 100644 --- a/chat/src/main/java/net/md_5/bungee/api/chat/TranslatableComponent.java +++ b/chat/src/main/java/net/md_5/bungee/api/chat/TranslatableComponent.java @@ -156,20 +156,20 @@ public final class TranslatableComponent extends BaseComponent } @Override - protected void toPlainText(StringBuilder builder) + protected void toPlainText(StringVisitor builder) { convert( builder, false ); super.toPlainText( builder ); } @Override - protected void toLegacyText(StringBuilder builder) + protected void toLegacyText(StringVisitor builder) { convert( builder, true ); super.toLegacyText( builder ); } - private void convert(StringBuilder builder, boolean applyFormat) + private void convert(StringVisitor builder, boolean applyFormat) { String trans = TranslationRegistry.INSTANCE.translate( translate ); diff --git a/serializer/src/test/java/net/md_5/bungee/api/chat/ComponentsTest.java b/serializer/src/test/java/net/md_5/bungee/api/chat/ComponentsTest.java index 2d8233e6..6ce710d6 100644 --- a/serializer/src/test/java/net/md_5/bungee/api/chat/ComponentsTest.java +++ b/serializer/src/test/java/net/md_5/bungee/api/chat/ComponentsTest.java @@ -564,6 +564,15 @@ public class ComponentsTest assertEquals( "http://google.com/test", url2.getValue() ); } + @Test + public void testLong() + { + BaseComponent test = ComponentSerializer.deserialize( "{\"translate\":\"%1$s%1$s%1$s%1$s%1$s%1$s%1$s%1$s%1$s%1$s\",\"with\":[{\"translate\":\"%1$s%1$s%1$s%1$s%1$s%1$s%1$s%1$s%1$s%1$s\",\"with\":[{\"translate\":\"%1$s%1$s%1$s%1$s%1$s%1$s%1$s%1$s%1$s%1$s\",\"with\":[{\"translate\":\"%1$s%1$s%1$s%1$s%1$s%1$s%1$s%1$s%1$s%1$s\",\"with\":[{\"translate\":\"%1$s%1$s%1$s%1$s%1$s%1$s%1$s%1$s%1$s%1$s\",\"with\":[{\"translate\":\"%1$s%1$s%1$s%1$s%1$s%1$s%1$s%1$s%1$s%1$s\",\"with\":[{\"translate\":\"%1$s%1$s%1$s%1$s%1$s%1$s%1$s%1$s%1$s%1$s\",\"with\":[{\"translate\":\"%1$s%1$s%1$s%1$s%1$s%1$s%1$s%1$s%1$s%1$s\",\"with\":[{\"translate\":\"%1$s%1$s%1$s%1$s%1$s%1$s%1$s%1$s%1$s%1$s\",\"with\":[{\"translate\":\"%1$s%1$s%1$s%1$s%1$s%1$s%1$s%1$s%1$s%1$s\",\"with\":[\"Test\"]}]}]}]}]}]}]}]}]}]}" ); + + assertThrows( RuntimeException.class, test::toLegacyText ); + assertThrows( RuntimeException.class, test::toPlainText ); + } + @Test public void testBuilderCreate() {