From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: VideoGameSmash12 Date: Wed, 19 Oct 2022 00:50:29 -0600 Subject: [PATCH] Reject translatable components with more than 32 placeholders in them diff --git a/src/main/java/net/minecraft/network/chat/Component.java b/src/main/java/net/minecraft/network/chat/Component.java index 6978d14c6bd90ffb640e39e8666430d95d5ef45c..e6d733fc3a4acdb3fd91b5644285854943a02761 100644 --- a/src/main/java/net/minecraft/network/chat/Component.java +++ b/src/main/java/net/minecraft/network/chat/Component.java @@ -33,6 +33,9 @@ import net.minecraft.util.GsonHelper; import net.minecraft.util.LowerCaseEnumTypeAdapterFactory; // CraftBukkit start import com.google.common.collect.Streams; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.stream.Stream; // CraftBukkit end @@ -192,9 +195,53 @@ 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]{1,}\\$s"); public Serializer() {} + // Scissors start - Calculate number of placeholders in translatable components before serializing them + private long calculatePlaceholderCount(JsonElement element) { + long amount = 0; + + if (!element.isJsonObject()) { + return amount; + } + + JsonObject from = element.getAsJsonObject(); + + // Figure out how many placeholders are in a single translatable component + if (from.has("translate") && from.get("translate").isJsonPrimitive()) { + String key = GsonHelper.getAsString(from, "translate"); + Matcher matcher = PLACEHOLDER_PATTERN.matcher(key); + amount += matcher.results().count(); + + // Recursively figure out how many placeholders the component has in the "with" shit + if (from.has("with") && from.get("with").isJsonArray()) { + JsonArray array = GsonHelper.getAsJsonArray(from, "with"); + + for (JsonElement within : array) { + long amountWithin = calculatePlaceholderCount(within); + + if (amountWithin == 1) { + amount++; + } + else if (amountWithin > 1) { + amount = amount * amountWithin; + } + } + } + } + // Also applies to keybind components, but to a lesser extent + else if (from.has("keybind") && from.get("keybind").isJsonPrimitive()) { + String key = GsonHelper.getAsString(from, "keybind"); + Matcher matcher = PLACEHOLDER_PATTERN.matcher(key); + amount += matcher.results().count(); + } + + return amount; + } + // Scissors end + public MutableComponent deserialize(JsonElement jsonelement, Type type, JsonDeserializationContext jsondeserializationcontext) throws JsonParseException { if (jsonelement.isJsonPrimitive()) { return new TextComponent(jsonelement.getAsString()); @@ -221,6 +268,13 @@ public interface Component extends Message, FormattedText, Iterable { } } else { JsonObject jsonobject = jsonelement.getAsJsonObject(); + + // Scissors start - Reject translatable components with more than 32 placeholders in them + if (calculatePlaceholderCount(jsonobject) > 32) { + return new TextComponent("*** Component has too many placeholders ***").withStyle(ChatFormatting.RED); + } + // Scissors end + Object object; if (jsonobject.has("text")) {