Scissors/patches/server/0047-Reject-translatable-components-with-more-than-32-pla.patch
2022-11-28 19:20:57 -07:00

89 lines
4 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: VideoGameSmash12 <videogamesm12@gmail.com>
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<Component> {
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<Component> {
}
} 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")) {