From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Nassim Jahnke Date: Thu, 4 Jan 2024 13:49:14 +0100 Subject: [PATCH] Validate ResourceLocation in NBT reading diff --git a/src/main/java/net/minecraft/nbt/NbtUtils.java b/src/main/java/net/minecraft/nbt/NbtUtils.java index ba0726157417cdde1c9bca93a9e37e68d9b2286d..e3a3f19a6e63fd42e29c418e5a7439972484d492 100644 --- a/src/main/java/net/minecraft/nbt/NbtUtils.java +++ b/src/main/java/net/minecraft/nbt/NbtUtils.java @@ -230,8 +230,10 @@ public final class NbtUtils { if (!nbt.contains("Name", 8)) { return Blocks.AIR.defaultBlockState(); } else { - ResourceLocation resourceLocation = new ResourceLocation(nbt.getString("Name")); - Optional> optional = blockLookup.get(ResourceKey.create(Registries.BLOCK, resourceLocation)); + // Paper start - Validate resource location + ResourceLocation resourceLocation = ResourceLocation.tryParse(nbt.getString("Name")); + Optional> optional = resourceLocation != null ? blockLookup.get(ResourceKey.create(Registries.BLOCK, resourceLocation)) : Optional.empty(); + // Paper end - Validate resource location if (optional.isEmpty()) { return Blocks.AIR.defaultBlockState(); } else { diff --git a/src/main/java/net/minecraft/resources/ResourceLocation.java b/src/main/java/net/minecraft/resources/ResourceLocation.java index 5f9dcab27a07969c93555ad0892683c62cbebc8c..a4d875df936b6de16f0233482b03af05b427a79f 100644 --- a/src/main/java/net/minecraft/resources/ResourceLocation.java +++ b/src/main/java/net/minecraft/resources/ResourceLocation.java @@ -31,6 +31,13 @@ public class ResourceLocation implements Comparable { private final String path; protected ResourceLocation(String namespace, String path, @Nullable ResourceLocation.Dummy extraData) { + // Paper start - Validate ResourceLocation + // Check for the max network string length (capped at Short.MAX_VALUE) as well as the max bytes of a StringTag (length written as an unsigned short) + final String resourceLocation = namespace + ":" + path; + if (resourceLocation.length() > Short.MAX_VALUE || io.netty.buffer.ByteBufUtil.utf8MaxBytes(resourceLocation) > 2 * Short.MAX_VALUE + 1) { + throw new ResourceLocationException("Resource location too long: " + resourceLocation); + } + // Paper end - Validate ResourceLocation this.namespace = namespace; this.path = path; } diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java index 8ba573bb4099ee5b27b61f333e72d794c48d5f29..69bdf3f2ee731e59e8d454816a9ca72cb49c0fe0 100644 --- a/src/main/java/net/minecraft/world/entity/EntityType.java +++ b/src/main/java/net/minecraft/world/entity/EntityType.java @@ -614,7 +614,7 @@ public class EntityType implements FeatureElement, EntityTypeT } public static Optional> by(CompoundTag nbt) { - return BuiltInRegistries.ENTITY_TYPE.getOptional(new ResourceLocation(nbt.getString("id"))); + return BuiltInRegistries.ENTITY_TYPE.getOptional(ResourceLocation.tryParse(nbt.getString("id"))); // Paper - Validate ResourceLocation } @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 --- 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 { if (nbt.contains("SleepingX", 99) && nbt.contains("SleepingY", 99) && nbt.contains("SleepingZ", 99)) { BlockPos blockposition = new BlockPos(nbt.getInt("SleepingX"), nbt.getInt("SleepingY"), nbt.getInt("SleepingZ")); - + if (this.position().distanceToSqr(blockposition.getX(), blockposition.getY(), blockposition.getZ()) < 16 * 16) { // Paper - The sleeping pos will always also set the actual pos, so a desync suggests something is wrong this.setSleepingPos(blockposition); this.entityData.set(LivingEntity.DATA_POSE, Pose.SLEEPING); if (!this.firstTick) { this.setPosToBed(blockposition); } + } // Paper - The sleeping pos will always also set the actual pos, so a desync suggests something is wrong } if (nbt.contains("Brain", 10)) { diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java index 9ecabac9e95bb0b550260770fcc713ad82070d0b..fd093e5bc79a44e02f57bacd8273dc87342f5709 100644 --- a/src/main/java/net/minecraft/world/entity/Mob.java +++ b/src/main/java/net/minecraft/world/entity/Mob.java @@ -607,7 +607,7 @@ public abstract class Mob extends LivingEntity implements Targeting { this.setLeftHanded(nbt.getBoolean("LeftHanded")); if (nbt.contains("DeathLootTable", 8)) { - this.lootTable = new ResourceLocation(nbt.getString("DeathLootTable")); + this.lootTable = ResourceLocation.tryParse(nbt.getString("DeathLootTable")); // Paper - Validate ResourceLocation this.lootTableSeed = nbt.getLong("DeathLootTableSeed"); } diff --git a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java index 618de60680de015bc68bf95a68eda98db7bab3c5..d14eab0d83d629a4522bf3f7d789d2853eb84f06 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java +++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java @@ -560,7 +560,7 @@ public abstract class AbstractArrow extends Projectile { this.setCritArrow(nbt.getBoolean("crit")); this.setPierceLevel(nbt.getByte("PierceLevel")); if (nbt.contains("SoundEvent", 8)) { - this.soundEvent = (SoundEvent) BuiltInRegistries.SOUND_EVENT.getOptional(new ResourceLocation(nbt.getString("SoundEvent"))).orElse(this.getDefaultHitGroundSoundEvent()); + this.soundEvent = (SoundEvent) BuiltInRegistries.SOUND_EVENT.getOptional(ResourceLocation.tryParse(nbt.getString("SoundEvent"))).orElse(this.getDefaultHitGroundSoundEvent()); // Paper - Validate resource location } this.setShotFromCrossbow(nbt.getBoolean("ShotFromCrossbow")); diff --git a/src/main/java/net/minecraft/world/entity/vehicle/ContainerEntity.java b/src/main/java/net/minecraft/world/entity/vehicle/ContainerEntity.java index 7529751afa2932fd16bc4591189b0358268a7b14..e2e1c7a017e82dc7299e5cd1783818e4f0319c0b 100644 --- a/src/main/java/net/minecraft/world/entity/vehicle/ContainerEntity.java +++ b/src/main/java/net/minecraft/world/entity/vehicle/ContainerEntity.java @@ -67,7 +67,7 @@ public interface ContainerEntity extends Container, MenuProvider { default void readChestVehicleSaveData(CompoundTag nbt) { this.clearItemStacks(); if (nbt.contains("LootTable", 8)) { - this.setLootTable(new ResourceLocation(nbt.getString("LootTable"))); + this.setLootTable(ResourceLocation.tryParse(nbt.getString("LootTable"))); // Paper - Validate ResourceLocation this.setLootTableSeed(nbt.getLong("LootTableSeed")); }