aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorNassim Jahnke <[email protected]>2024-02-18 12:53:27 +0100
committerNassim Jahnke <[email protected]>2024-02-18 13:52:12 +0100
commit4939f8711884901ddf1c56337f606de71cdae78d (patch)
tree2a591400181d3b8e968c0a0b2cf033a1402e5999
parent351923d17e3b5f2a2a3ed848c171d7d2b077a55a (diff)
downloadPaper-4939f8711884901ddf1c56337f606de71cdae78d.tar.gz
Paper-4939f8711884901ddf1c56337f606de71cdae78d.zip
Add more ResourceLocation checks, some cleanup
-rw-r--r--patches/server/0092-LootTable-API-and-replenishable-lootables.patch4
-rw-r--r--patches/server/0248-Add-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch31
-rw-r--r--patches/server/0342-Do-not-allow-bees-to-load-chunks-for-beehives.patch16
-rw-r--r--patches/server/0978-Validate-ResourceLocation-in-NBT-reading.patch33
-rw-r--r--patches/server/1039-Improve-tag-parser-handling.patch68
5 files changed, 110 insertions, 42 deletions
diff --git a/patches/server/0092-LootTable-API-and-replenishable-lootables.patch b/patches/server/0092-LootTable-API-and-replenishable-lootables.patch
index 2f441da2cc..2c728e93f8 100644
--- a/patches/server/0092-LootTable-API-and-replenishable-lootables.patch
+++ b/patches/server/0092-LootTable-API-and-replenishable-lootables.patch
@@ -654,7 +654,7 @@ index e0fbacd574e0c83c2e1d164ded8e9ccf4af30480..7529751afa2932fd16bc4591189b0358
+ // Paper end
}
diff --git a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
-index aa4181e59f88be04a3605352fa5ceb3e04149dd3..7cbd403f9e96e7ce35475c8102cd9f9c04819c27 100644
+index aa4181e59f88be04a3605352fa5ceb3e04149dd3..e4e827a57c2913c719282cc0d5da33586607677b 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
@@ -17,6 +17,7 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc
@@ -675,7 +675,7 @@ index aa4181e59f88be04a3605352fa5ceb3e04149dd3..7cbd403f9e96e7ce35475c8102cd9f9c
+ // Copied from super with changes, always check the original method
+ this.lootableData.loadNbt(nbt); // Paper
+ if (nbt.contains("LootTable", 8)) {
-+ this.setLootTable(new ResourceLocation(nbt.getString("LootTable")));
++ this.setLootTable(ResourceLocation.tryParse(nbt.getString("LootTable")));
+ try { org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(this.lootTable); } catch (IllegalArgumentException ex) { this.lootTable = null; } // Paper - validate
+ this.setLootTableSeed(nbt.getLong("LootTableSeed"));
+ return false; // Paper - always load the items, table may still remain
diff --git a/patches/server/0248-Add-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch b/patches/server/0248-Add-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch
index 61c1bd0e6e..f179b48bd7 100644
--- a/patches/server/0248-Add-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch
+++ b/patches/server/0248-Add-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch
@@ -5,7 +5,7 @@ Subject: [PATCH] Add API for CanPlaceOn and CanDestroy NBT values
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
-index 1920cf7ad846f57cd278cb9a72dce03f3d014fbb..629fa76e6c7c2ede36ab855bb3a7a65dfd601449 100644
+index 1920cf7ad846f57cd278cb9a72dce03f3d014fbb..7cf1153ae532a9d53ee85b05f77ed74b94cf5fbc 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
@@ -85,6 +85,12 @@ import org.bukkit.persistence.PersistentDataContainer;
@@ -67,7 +67,7 @@ index 1920cf7ad846f57cd278cb9a72dce03f3d014fbb..629fa76e6c7c2ede36ab855bb3a7a65d
+ if (tag.contains(CAN_DESTROY.NBT)) {
+ ListTag list = tag.getList(CAN_DESTROY.NBT, CraftMagicNumbers.NBT.TAG_STRING);
+ for (int i = 0; i < list.size(); i++) {
-+ Namespaced namespaced = this.deserializeNamespaced(list.getString(i));
++ Namespaced namespaced = this.blockKeyFromString(list.getString(i));
+ if (namespaced == null) {
+ continue;
+ }
@@ -79,7 +79,7 @@ index 1920cf7ad846f57cd278cb9a72dce03f3d014fbb..629fa76e6c7c2ede36ab855bb3a7a65d
+ if (tag.contains(CAN_PLACE_ON.NBT)) {
+ ListTag list = tag.getList(CAN_PLACE_ON.NBT, CraftMagicNumbers.NBT.TAG_STRING);
+ for (int i = 0; i < list.size(); i++) {
-+ Namespaced namespaced = this.deserializeNamespaced(list.getString(i));
++ Namespaced namespaced = this.blockKeyFromString(list.getString(i));
+ if (namespaced == null) {
+ continue;
+ }
@@ -100,7 +100,7 @@ index 1920cf7ad846f57cd278cb9a72dce03f3d014fbb..629fa76e6c7c2ede36ab855bb3a7a65d
+ if (canPlaceOnSerialized != null) {
+ for (Object canPlaceOnElement : canPlaceOnSerialized) {
+ String canPlaceOnRaw = (String) canPlaceOnElement;
-+ Namespaced value = this.deserializeNamespaced(canPlaceOnRaw);
++ Namespaced value = this.blockKeyFromString(canPlaceOnRaw);
+ if (value == null) {
+ continue;
+ }
@@ -113,7 +113,7 @@ index 1920cf7ad846f57cd278cb9a72dce03f3d014fbb..629fa76e6c7c2ede36ab855bb3a7a65d
+ if (canDestroySerialized != null) {
+ for (Object canDestroyElement : canDestroySerialized) {
+ String canDestroyRaw = (String) canDestroyElement;
-+ Namespaced value = this.deserializeNamespaced(canDestroyRaw);
++ Namespaced value = this.blockKeyFromString(canDestroyRaw);
+ if (value == null) {
+ continue;
+ }
@@ -253,7 +253,7 @@ index 1920cf7ad846f57cd278cb9a72dce03f3d014fbb..629fa76e6c7c2ede36ab855bb3a7a65d
// Paper end
CraftMetaCompass.LODESTONE_DIMENSION.NBT,
CraftMetaCompass.LODESTONE_POS.NBT,
-@@ -1545,4 +1688,146 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
+@@ -1545,4 +1688,141 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
}
// Paper end
@@ -347,8 +347,8 @@ index 1920cf7ad846f57cd278cb9a72dce03f3d014fbb..629fa76e6c7c2ede36ab855bb3a7a65d
+ return mats;
+ }
+
-+ private @Nullable Namespaced deserializeNamespaced(String raw) {
-+ boolean isTag = raw.length() > 0 && raw.codePointAt(0) == '#';
++ private @Nullable Namespaced blockKeyFromString(String raw) {
++ boolean isTag = !raw.isEmpty() && raw.codePointAt(0) == '#';
+ com.mojang.datafixers.util.Either<net.minecraft.commands.arguments.blocks.BlockStateParser.BlockResult, net.minecraft.commands.arguments.blocks.BlockStateParser.TagResult> result;
+ try {
+ result = net.minecraft.commands.arguments.blocks.BlockStateParser.parseForTesting(net.minecraft.core.registries.BuiltInRegistries.BLOCK.asLookup(), raw, false);
@@ -367,20 +367,15 @@ index 1920cf7ad846f57cd278cb9a72dce03f3d014fbb..629fa76e6c7c2ede36ab855bb3a7a65d
+ return null;
+ }
+
-+ // don't DC the player if something slips through somehow
-+ Namespaced resource = null;
+ try {
+ if (isTag) {
-+ resource = new NamespacedTag(key.getNamespace(), key.getPath());
-+ } else {
-+ resource = CraftNamespacedKey.fromMinecraft(key);
++ return new NamespacedTag(key.getNamespace(), key.getPath());
++
+ }
-+ } catch (IllegalArgumentException ex) {
-+ org.bukkit.Bukkit.getLogger().warning("Namespaced resource does not validate: " + key.toString());
-+ ex.printStackTrace();
++ return CraftNamespacedKey.fromMinecraft(key);
++ } catch (IllegalArgumentException ignored) {
++ return null;
+ }
-+
-+ return resource;
+ }
+
+ private @Nonnull String serializeNamespaced(Namespaced resource) {
diff --git a/patches/server/0342-Do-not-allow-bees-to-load-chunks-for-beehives.patch b/patches/server/0342-Do-not-allow-bees-to-load-chunks-for-beehives.patch
index 9c629a712d..79bb156283 100644
--- a/patches/server/0342-Do-not-allow-bees-to-load-chunks-for-beehives.patch
+++ b/patches/server/0342-Do-not-allow-bees-to-load-chunks-for-beehives.patch
@@ -40,3 +40,19 @@ index 06e990b6957a4ef48c8778bbd175d3afddf52ca3..07ecc038a1000581335b8d18c094298f
BlockEntity tileentity = Bee.this.level().getBlockEntity(Bee.this.hivePos);
if (tileentity instanceof BeehiveBlockEntity) {
+diff --git a/src/main/java/net/minecraft/world/entity/monster/Vex.java b/src/main/java/net/minecraft/world/entity/monster/Vex.java
+index 30ea3f64234fd1fda8dada3c7fb12be0730322a8..f443006c1e32feee97b32312814e2447a50c45e2 100644
+--- a/src/main/java/net/minecraft/world/entity/monster/Vex.java
++++ b/src/main/java/net/minecraft/world/entity/monster/Vex.java
+@@ -377,7 +377,10 @@ public class Vex extends Monster implements TraceableEntity {
+ for (int i = 0; i < 3; ++i) {
+ BlockPos blockposition1 = blockposition.offset(Vex.this.random.nextInt(15) - 7, Vex.this.random.nextInt(11) - 5, Vex.this.random.nextInt(15) - 7);
+
+- if (Vex.this.level().isEmptyBlock(blockposition1)) {
++ // Paper start - Don't load chunks
++ final net.minecraft.world.level.block.state.BlockState blockState = Vex.this.level().getBlockStateIfLoaded(blockposition1);
++ if (blockState != null && blockState.isAir()) {
++ // Paper end - Don't load chunks
+ Vex.this.moveControl.setWantedPosition((double) blockposition1.getX() + 0.5D, (double) blockposition1.getY() + 0.5D, (double) blockposition1.getZ() + 0.5D, 0.25D);
+ if (Vex.this.getTarget() == null) {
+ Vex.this.getLookControl().setLookAt((double) blockposition1.getX() + 0.5D, (double) blockposition1.getY() + 0.5D, (double) blockposition1.getZ() + 0.5D, 180.0F, 20.0F);
diff --git a/patches/server/0978-Validate-ResourceLocation-in-NBT-reading.patch b/patches/server/0978-Validate-ResourceLocation-in-NBT-reading.patch
index 2f94b7ad03..eab18ce886 100644
--- a/patches/server/0978-Validate-ResourceLocation-in-NBT-reading.patch
+++ b/patches/server/0978-Validate-ResourceLocation-in-NBT-reading.patch
@@ -53,7 +53,7 @@ index 8ba573bb4099ee5b27b61f333e72d794c48d5f29..69bdf3f2ee731e59e8d454816a9ca72c
@Nullable
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
-index 4591011a142f33f0c0ff84a2765cededde0e0c57..c0bfce7266bbdfe0c5a753367032eb333f56c182 100644
+index 6502dfa62fb0e5a0e3369c62c6ad97aecced4d2b..484056cf77334818aab98ad20e99685d1e240adc 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -871,12 +871,13 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -110,3 +110,34 @@ index 7529751afa2932fd16bc4591189b0358268a7b14..e2e1c7a017e82dc7299e5cd1783818e4
this.setLootTableSeed(nbt.getLong("LootTableSeed"));
}
+diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
+index d04fc84eef11adb5ea64077f48794b6ed7fb3ada..89d06253b00604114e543ebbe12a9993ae95dc41 100644
+--- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
++++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
+@@ -290,7 +290,12 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit
+ while (iterator.hasNext()) {
+ String s = (String) iterator.next();
+
+- this.recipesUsed.put(new ResourceLocation(s), nbttagcompound1.getInt(s));
++ // Paper start - Validate ResourceLocation
++ final ResourceLocation resourceLocation = ResourceLocation.tryParse(s);
++ if (resourceLocation != null) {
++ this.recipesUsed.put(resourceLocation, nbttagcompound1.getInt(s));
++ }
++ // Paper end - Validate ResourceLocation
+ }
+
+ // Paper start - cook speed multiplier API
+diff --git a/src/main/java/net/minecraft/world/level/block/entity/BrushableBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BrushableBlockEntity.java
+index b5b1831631e233a96b6fd55972a8862b0f420da8..3f62e823bf9b5aa696e3c240613a0fb50340875e 100644
+--- a/src/main/java/net/minecraft/world/level/block/entity/BrushableBlockEntity.java
++++ b/src/main/java/net/minecraft/world/level/block/entity/BrushableBlockEntity.java
+@@ -199,7 +199,7 @@ public class BrushableBlockEntity extends BlockEntity {
+
+ private boolean tryLoadLootTable(CompoundTag nbt) {
+ if (nbt.contains("LootTable", 8)) {
+- this.lootTable = new ResourceLocation(nbt.getString("LootTable"));
++ this.lootTable = ResourceLocation.tryParse(nbt.getString("LootTable")); // Paper - Validate ResourceLocation
+ this.lootTableSeed = nbt.getLong("LootTableSeed");
+ return true;
+ } else {
diff --git a/patches/server/1039-Improve-tag-parser-handling.patch b/patches/server/1039-Improve-tag-parser-handling.patch
index 2dabc48078..e57cd51b7b 100644
--- a/patches/server/1039-Improve-tag-parser-handling.patch
+++ b/patches/server/1039-Improve-tag-parser-handling.patch
@@ -5,22 +5,54 @@ Subject: [PATCH] Improve tag parser handling
diff --git a/src/main/java/com/mojang/brigadier/CommandDispatcher.java b/src/main/java/com/mojang/brigadier/CommandDispatcher.java
-index 92848b64a78fce7a92e1657c2da6fc5ee53eea44..5d0e8f4f3ad61a27452675277380e27d3d28d133 100644
+index 92848b64a78fce7a92e1657c2da6fc5ee53eea44..5d5562676a77259b875e15b744b53258533851a7 100644
--- a/src/main/java/com/mojang/brigadier/CommandDispatcher.java
+++ b/src/main/java/com/mojang/brigadier/CommandDispatcher.java
-@@ -307,6 +307,10 @@ public class CommandDispatcher<S> {
+@@ -304,9 +304,15 @@ public class CommandDispatcher<S> {
+ }
+ final CommandContextBuilder<S> context = contextSoFar.copy();
+ final StringReader reader = new StringReader(originalReader);
++ boolean stop = false; // Paper - Handle non-recoverable exceptions
try {
try {
child.parse(reader, context);
-+ // Paper start - Handle non-reoverable exceptions; Rethrow NbtAccounterException so it can be caught properly and immediately
-+ } catch (final net.minecraft.nbt.NbtAccounterException e) {
++ // Paper start - Handle non-recoverable exceptions
++ } catch (final com.mojang.brigadier.exceptions.TagParseCommandSyntaxException e) {
++ stop = true;
+ throw e;
-+ // Paper end - Handle non-reoverable exceptions
++ // Paper end - Handle non-recoverable exceptions
} catch (final RuntimeException ex) {
throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherParseException().createWithContext(reader, ex.getMessage());
}
+@@ -321,6 +327,7 @@ public class CommandDispatcher<S> {
+ }
+ errors.put(child, ex);
+ reader.setCursor(cursor);
++ if (stop) return new ParseResults<>(contextSoFar, originalReader, errors); // Paper - Handle non-recoverable exceptions
+ continue;
+ }
+
+diff --git a/src/main/java/com/mojang/brigadier/exceptions/TagParseCommandSyntaxException.java b/src/main/java/com/mojang/brigadier/exceptions/TagParseCommandSyntaxException.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..bf248a215dc69bb303c836112309471aab687e23
+--- /dev/null
++++ b/src/main/java/com/mojang/brigadier/exceptions/TagParseCommandSyntaxException.java
+@@ -0,0 +1,13 @@
++package com.mojang.brigadier.exceptions;
++
++import com.mojang.brigadier.LiteralMessage;
++import net.minecraft.network.chat.Component;
++
++public final class TagParseCommandSyntaxException extends CommandSyntaxException {
++
++ private static final SimpleCommandExceptionType EXCEPTION_TYPE = new SimpleCommandExceptionType(new LiteralMessage("Error parsing NBT"));
++
++ public TagParseCommandSyntaxException(final String message) {
++ super(EXCEPTION_TYPE, Component.literal(message));
++ }
++}
diff --git a/src/main/java/net/minecraft/nbt/TagParser.java b/src/main/java/net/minecraft/nbt/TagParser.java
-index 5bec54239a2b185284c10d58854e5a13e33daae5..9ecd0b7ddaa8376f3c1448f810f7757c9ba1b90a 100644
+index 5bec54239a2b185284c10d58854e5a13e33daae5..94cb73e7f60171aa57bd1dbe7e91ef4db94e70b7 100644
--- a/src/main/java/net/minecraft/nbt/TagParser.java
+++ b/src/main/java/net/minecraft/nbt/TagParser.java
@@ -48,6 +48,7 @@ public class TagParser {
@@ -83,10 +115,10 @@ index 5bec54239a2b185284c10d58854e5a13e33daae5..9ecd0b7ddaa8376f3c1448f810f7757c
this.reader.expect(c);
}
+
-+ private void increaseDepth() {
++ private void increaseDepth() throws CommandSyntaxException {
+ this.depth++;
+ if (this.depth > 512) {
-+ throw new net.minecraft.nbt.NbtAccounterException("NBT tag is too complex, depth > 512");
++ throw new com.mojang.brigadier.exceptions.TagParseCommandSyntaxException("NBT tag is too complex, depth > 512");
+ }
+ }
}
@@ -104,7 +136,7 @@ index a5e438a834826161c52ca9db57d234d9ff80a591..4766994cce060564370b0d24836a7da8
@Override
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
-index 2f9c62f2c4c4356a896f7004b77f12a595f9c6dc..6d943b5c38932de5fc3abb28618bf518c36edb47 100644
+index 2f9c62f2c4c4356a896f7004b77f12a595f9c6dc..ab5b259d8f72022c875cae73be25fe2da346c6b3 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -777,6 +777,13 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
@@ -121,23 +153,17 @@ index 2f9c62f2c4c4356a896f7004b77f12a595f9c6dc..6d943b5c38932de5fc3abb28618bf518
// Paper start - AsyncTabCompleteEvent
TAB_COMPLETE_EXECUTOR.execute(() -> this.handleCustomCommandSuggestions0(packet));
}
-@@ -823,7 +830,18 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
-
+@@ -824,6 +831,13 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
private void sendServerSuggestions(final ServerboundCommandSuggestionPacket packet, final StringReader stringreader) {
// Paper end - AsyncTabCompleteEvent
-- ParseResults<CommandSourceStack> parseresults = this.server.getCommands().getDispatcher().parse(stringreader, this.player.createCommandSourceStack());
-+ // Paper start - Handle non-reoverable exceptions
-+ ParseResults<CommandSourceStack> parseresults;
-+ try {
-+ parseresults = this.server.getCommands().getDispatcher().parse(stringreader, this.player.createCommandSourceStack());
-+ } catch (final Throwable e) { // This is fine:tm:
-+ if (LOGGER.isDebugEnabled()) {
-+ LOGGER.error("Exception parsing command", e);
-+ }
+ ParseResults<CommandSourceStack> parseresults = this.server.getCommands().getDispatcher().parse(stringreader, this.player.createCommandSourceStack());
++ // Paper start - Handle non-recoverable exceptions
++ if (!parseresults.getExceptions().isEmpty()
++ && parseresults.getExceptions().values().stream().anyMatch(e -> e instanceof com.mojang.brigadier.exceptions.TagParseCommandSyntaxException)) {
+ this.disconnect(Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM);
+ return;
+ }
-+ // Paper end - Handle non-reoverable exceptions
++ // Paper end - Handle non-recoverable exceptions
this.server.getCommands().getDispatcher().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> {
// Paper start - Don't tab-complete namespaced commands if send-namespaced is false