diff --git a/patches/server/0047-Reject-translatable-components-with-more-than-32-pla.patch b/patches/server/0047-Reject-translatable-components-with-more-than-32-pla.patch new file mode 100644 index 0000000..82e5d54 --- /dev/null +++ b/patches/server/0047-Reject-translatable-components-with-more-than-32-pla.patch @@ -0,0 +1,89 @@ +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")) {