From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Luna Date: Wed, 31 May 2023 18:14:00 -0300 Subject: [PATCH] Add depth limit to Component deserializer diff --git a/src/main/java/net/minecraft/network/chat/Component.java b/src/main/java/net/minecraft/network/chat/Component.java index a2149452ee461002ea74189c5aa49cddd943d0cf..f1d1501211a923c0ccab6b5982887c3a9262889b 100644 --- a/src/main/java/net/minecraft/network/chat/Component.java +++ b/src/main/java/net/minecraft/network/chat/Component.java @@ -26,6 +26,7 @@ import java.util.List; import java.util.Map.Entry; import java.util.Optional; import javax.annotation.Nullable; +import me.totalfreedom.scissors.ScissorsConfig; // Scissors import net.minecraft.ChatFormatting; // Scissors import net.minecraft.Util; import net.minecraft.network.chat.contents.BlockDataSource; @@ -44,6 +45,7 @@ import net.minecraft.util.GsonHelper; import net.minecraft.util.LowerCaseEnumTypeAdapterFactory; // CraftBukkit start import com.google.common.collect.Streams; +import java.util.regex.Pattern; // Scissors import java.util.stream.Stream; // CraftBukkit end @@ -254,10 +256,16 @@ public interface Component extends Message, FormattedText, Iterable { throw new IllegalStateException("Couldn't get field 'lineStart' for JsonReader", nosuchfieldexception); } }); + private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("%[0-9]+\\$s"); // Scissors public Serializer() {} - public MutableComponent deserialize(JsonElement jsonelement, Type type, JsonDeserializationContext jsondeserializationcontext) throws JsonParseException { + // Scissors start + private MutableComponent deserialize(JsonElement jsonelement, JsonDeserializationContext jsondeserializationcontext, int depth) throws JsonParseException { + if (depth > ScissorsConfig.componentDepthLimit) { + throw new JsonParseException("Depth limit exceeded"); + } + // Scissors end if (jsonelement.isJsonPrimitive()) { return Component.literal(jsonelement.getAsString()); } else { @@ -273,7 +281,7 @@ public interface Component extends Message, FormattedText, Iterable { while (iterator.hasNext()) { JsonElement jsonelement1 = (JsonElement) iterator.next(); - MutableComponent ichatmutablecomponent1 = this.deserialize(jsonelement1, jsonelement1.getClass(), jsondeserializationcontext); + MutableComponent ichatmutablecomponent1 = this.deserialize(jsonelement1, jsondeserializationcontext, depth + 1); // Scissors if (ichatmutablecomponent == null) { ichatmutablecomponent = ichatmutablecomponent1; @@ -297,12 +305,17 @@ public interface Component extends Message, FormattedText, Iterable { s = GsonHelper.getAsString(jsonobject, "translate"); String s1 = GsonHelper.getAsString(jsonobject, "fallback", (String) null); + // Scissors start - Penalize depth for placeholders in translate & fallback + long translate_placeholders = PLACEHOLDER_PATTERN.matcher(s).results().count(); + long fallback_placeholders = s1 != null ? PLACEHOLDER_PATTERN.matcher(s1).results().count() : 0; + int penalty = (int)Math.max(translate_placeholders, fallback_placeholders) * 12; + // Scissors end if (jsonobject.has("with")) { JsonArray jsonarray1 = GsonHelper.getAsJsonArray(jsonobject, "with"); Object[] aobject = new Object[jsonarray1.size()]; for (int i = 0; i < aobject.length; ++i) { - aobject[i] = Serializer.unwrapTextArgument(this.deserialize(jsonarray1.get(i), type, jsondeserializationcontext)); + aobject[i] = Serializer.unwrapTextArgument(this.deserialize(jsonarray1.get(i), jsondeserializationcontext, depth + 1 + penalty)); // Scissors } ichatmutablecomponent = Component.translatableWithFallback(s, s1, aobject); @@ -318,7 +331,7 @@ public interface Component extends Message, FormattedText, Iterable { ichatmutablecomponent = Component.score(GsonHelper.getAsString(jsonobject1, "name"), GsonHelper.getAsString(jsonobject1, "objective")); } else if (jsonobject.has("selector")) { - Optional optional = this.parseSeparator(type, jsondeserializationcontext, jsonobject); + Optional optional = this.parseSeparator(jsondeserializationcontext, jsonobject, depth + 1); // Scissors ichatmutablecomponent = Component.selector(GsonHelper.getAsString(jsonobject, "selector"), optional); } else if (jsonobject.has("keybind")) { @@ -329,7 +342,7 @@ public interface Component extends Message, FormattedText, Iterable { } s = GsonHelper.getAsString(jsonobject, "nbt"); - Optional optional1 = this.parseSeparator(type, jsondeserializationcontext, jsonobject); + Optional optional1 = this.parseSeparator(jsondeserializationcontext, jsonobject, depth + 1); // Scissors boolean flag = GsonHelper.getAsBoolean(jsonobject, "interpret", false); Object object; @@ -356,7 +369,7 @@ public interface Component extends Message, FormattedText, Iterable { } for (int j = 0; j < jsonarray2.size(); ++j) { - ichatmutablecomponent.append((Component) this.deserialize(jsonarray2.get(j), type, jsondeserializationcontext)); + ichatmutablecomponent.append((Component) this.deserialize(jsonarray2.get(j), jsondeserializationcontext, depth + 1)); // Scissors } } @@ -366,6 +379,12 @@ public interface Component extends Message, FormattedText, Iterable { } } + // Scissors start + public MutableComponent deserialize(JsonElement jsonelement, Type type, JsonDeserializationContext jsondeserializationcontext) throws JsonParseException { + return this.deserialize(jsonelement, jsondeserializationcontext, 1); + } + // Scissors end + private static Object unwrapTextArgument(Object text) { if (text instanceof Component) { Component ichatbasecomponent = (Component) text; @@ -384,8 +403,10 @@ public interface Component extends Message, FormattedText, Iterable { return text; } - private Optional parseSeparator(Type type, JsonDeserializationContext context, JsonObject json) { - return json.has("separator") ? Optional.of(this.deserialize(json.get("separator"), type, context)) : Optional.empty(); + // Scissors start + private Optional parseSeparator(JsonDeserializationContext context, JsonObject json, int depth) { + return json.has("separator") ? Optional.of(this.deserialize(json.get("separator"), context, depth + 1)) : Optional.empty(); + // Scissors end } private void serializeStyle(Style style, JsonObject json, JsonSerializationContext context) {