2024-01-04 13:52:38 +01:00
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nassim Jahnke <nassim@njahnke.dev>
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
2024-04-25 01:25:57 +02:00
index 1d7c20fe14882fdeddf315a8923669e3385652f5..f88dd37783b3c155c23b547c360b8d3c16e030c0 100644
2024-01-04 13:52:38 +01:00
--- a/src/main/java/net/minecraft/nbt/NbtUtils.java
+++ b/src/main/java/net/minecraft/nbt/NbtUtils.java
2024-04-25 01:25:57 +02:00
@@ -149,8 +149,10 @@ public final class NbtUtils {
2024-01-04 13:52:38 +01:00
if (!nbt.contains("Name", 8)) {
return Blocks.AIR.defaultBlockState();
} else {
- ResourceLocation resourceLocation = new ResourceLocation(nbt.getString("Name"));
- Optional<? extends Holder<Block>> optional = blockLookup.get(ResourceKey.create(Registries.BLOCK, resourceLocation));
+ // Paper start - Validate resource location
+ ResourceLocation resourceLocation = ResourceLocation.tryParse(nbt.getString("Name"));
+ Optional<? extends Holder<Block>> optional = resourceLocation != null ? blockLookup.get(ResourceKey.create(Registries.BLOCK, resourceLocation)) : Optional.empty();
2024-01-13 16:35:59 +01:00
+ // Paper end - Validate resource location
2024-01-04 13:52:38 +01:00
if (optional.isEmpty()) {
return Blocks.AIR.defaultBlockState();
} else {
2024-01-12 19:33:17 +01:00
diff --git a/src/main/java/net/minecraft/resources/ResourceLocation.java b/src/main/java/net/minecraft/resources/ResourceLocation.java
2024-04-25 01:25:57 +02:00
index d93b623ce973b63d4f3a77bfe459f51af7cb3c1c..2c4553312f2f37f8613ac813708b4b95f9675e9f 100644
2024-01-12 19:33:17 +01:00
--- a/src/main/java/net/minecraft/resources/ResourceLocation.java
+++ b/src/main/java/net/minecraft/resources/ResourceLocation.java
2024-04-25 01:25:57 +02:00
@@ -37,6 +37,13 @@ public class ResourceLocation implements Comparable<ResourceLocation> {
2024-01-12 19:33:17 +01:00
private final String path;
protected ResourceLocation(String namespace, String path, @Nullable ResourceLocation.Dummy extraData) {
2024-01-12 23:08:19 +01:00
+ // 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
2024-01-12 19:33:17 +01:00
this.namespace = namespace;
this.path = path;
}
2024-05-26 21:51:15 +02:00
diff --git a/src/main/java/net/minecraft/world/RandomizableContainer.java b/src/main/java/net/minecraft/world/RandomizableContainer.java
2024-05-29 20:17:56 +02:00
index 68fadc351464dde459eb4cc86660cf9add40d04e..a9a80f8bc4a6f250fe3c20482c395058f024fabd 100644
2024-05-26 21:51:15 +02:00
--- a/src/main/java/net/minecraft/world/RandomizableContainer.java
+++ b/src/main/java/net/minecraft/world/RandomizableContainer.java
@@ -50,7 +50,7 @@ public interface RandomizableContainer extends Container {
default boolean tryLoadLootTable(CompoundTag nbt) {
if (nbt.contains("LootTable", 8)) {
- this.setLootTable(ResourceKey.create(Registries.LOOT_TABLE, new ResourceLocation(nbt.getString("LootTable"))));
2024-05-29 20:17:56 +02:00
+ this.setLootTable(net.minecraft.Optionull.map(ResourceLocation.tryParse(nbt.getString("LootTable")), rl -> ResourceKey.create(Registries.LOOT_TABLE, rl))); // Paper - Validate ResourceLocation
2024-05-26 21:51:15 +02:00
if (this.lootableData() != null && this.getLootTable() != null) this.lootableData().loadNbt(nbt); // Paper - LootTable API
if (nbt.contains("LootTableSeed", 4)) {
this.setLootTableSeed(nbt.getLong("LootTableSeed"));
2024-01-06 09:51:49 +01:00
diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java
2024-04-25 23:21:18 +02:00
index 8c7cc9c5af0b8d8bef9b6e2d3d3e723cd76f3212..56b51096ca4147363a843accf6ef2510f05e8f1a 100644
2024-01-06 09:51:49 +01:00
--- a/src/main/java/net/minecraft/world/entity/EntityType.java
+++ b/src/main/java/net/minecraft/world/entity/EntityType.java
2024-04-25 01:25:57 +02:00
@@ -623,7 +623,7 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT
2024-01-06 09:51:49 +01:00
}
public static Optional<EntityType<?>> 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
2024-02-01 10:53:15 +01:00
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
2024-08-24 11:07:12 +02:00
index b7af45eac986097ef53fa90bb4edd67f8829f13c..958b25e62b040943c346114ef19d56104ae0a844 100644
2024-02-01 10:53:15 +01:00
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
2024-04-25 01:25:57 +02:00
@@ -911,12 +911,13 @@ public abstract class LivingEntity extends Entity implements Attackable {
2024-02-01 10:53:15 +01:00
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)) {
2024-01-04 13:52:38 +01:00
diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java
2024-08-24 11:07:12 +02:00
index 5581fd6656fc13ea1d036d6caab2aba39c5320ac..748a6d81f409cf91a7aa2c88ded04f1d428cf0f6 100644
2024-01-04 13:52:38 +01:00
--- a/src/main/java/net/minecraft/world/entity/Mob.java
+++ b/src/main/java/net/minecraft/world/entity/Mob.java
2024-04-25 23:21:18 +02:00
@@ -645,7 +645,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Targeti
2024-01-04 13:52:38 +01:00
this.setLeftHanded(nbt.getBoolean("LeftHanded"));
if (nbt.contains("DeathLootTable", 8)) {
2024-04-25 01:25:57 +02:00
- this.lootTable = ResourceKey.create(Registries.LOOT_TABLE, new ResourceLocation(nbt.getString("DeathLootTable")));
+ this.lootTable = net.minecraft.Optionull.map(ResourceLocation.tryParse(nbt.getString("DeathLootTable")), rl -> ResourceKey.create(Registries.LOOT_TABLE, rl)); // Paper - Validate ResourceLocation
2024-01-04 13:52:38 +01:00
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
2024-08-24 11:07:12 +02:00
index a7626757597e5014b0d1190345f930cbaf8fec7e..72c48bf33a0b882e4c94f1a7c343a170b1db0f53 100644
2024-01-04 13:52:38 +01:00
--- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java
2024-04-25 19:42:24 +02:00
@@ -561,7 +561,7 @@ public abstract class AbstractArrow extends Projectile {
2024-01-04 13:52:38 +01:00
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
2024-05-26 21:51:15 +02:00
index d976a6e3a79a01392a5033b05864d82782a30916..845eff7401b811c179dc9dee70eca0d724be5c80 100644
2024-01-04 13:52:38 +01:00
--- a/src/main/java/net/minecraft/world/entity/vehicle/ContainerEntity.java
+++ b/src/main/java/net/minecraft/world/entity/vehicle/ContainerEntity.java
2024-05-26 21:51:15 +02:00
@@ -73,7 +73,7 @@ public interface ContainerEntity extends Container, MenuProvider {
2024-04-25 01:25:57 +02:00
default void readChestVehicleSaveData(CompoundTag nbt, HolderLookup.Provider registriesLookup) {
2024-01-04 13:52:38 +01:00
this.clearItemStacks();
if (nbt.contains("LootTable", 8)) {
2024-04-25 01:25:57 +02:00
- this.setLootTable(ResourceKey.create(Registries.LOOT_TABLE, new ResourceLocation(nbt.getString("LootTable"))));
+ this.setLootTable(net.minecraft.Optionull.map(ResourceLocation.tryParse(nbt.getString("LootTable")), rl -> ResourceKey.create(Registries.LOOT_TABLE, rl))); // Paper - Validate ResourceLocation
2024-05-26 21:51:15 +02:00
// Paper start - LootTable API
if (this.getLootTable() != null) {
this.lootableData().loadNbt(nbt);
2024-02-18 12:53:27 +01:00
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
2024-04-25 01:25:57 +02:00
index f40b2582d9087f9dbb5cab950304698f33fdd879..a99fe191c429bb528209dd0f31b509acf9cccbb5 100644
2024-02-18 12:53:27 +01:00
--- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
2024-04-25 01:25:57 +02:00
@@ -295,7 +295,12 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit
2024-02-18 12:53:27 +01:00
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
2024-04-25 01:25:57 +02:00
index f78a9698afc87408fc46de2d3d00c923500885f4..dc02a3d84b397f634f77f4df9c06e245cc4dcb75 100644
2024-02-18 12:53:27 +01:00
--- a/src/main/java/net/minecraft/world/level/block/entity/BrushableBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/BrushableBlockEntity.java
2024-04-25 01:25:57 +02:00
@@ -202,7 +202,7 @@ public class BrushableBlockEntity extends BlockEntity {
2024-02-18 12:53:27 +01:00
private boolean tryLoadLootTable(CompoundTag nbt) {
if (nbt.contains("LootTable", 8)) {
2024-04-25 01:25:57 +02:00
- this.lootTable = ResourceKey.create(Registries.LOOT_TABLE, new ResourceLocation(nbt.getString("LootTable")));
+ this.lootTable = net.minecraft.Optionull.map(ResourceLocation.tryParse(nbt.getString("LootTable")), rl -> ResourceKey.create(Registries.LOOT_TABLE, rl)); // Paper - Validate ResourceLocation
2024-02-18 12:53:27 +01:00
this.lootTableSeed = nbt.getLong("LootTableSeed");
return true;
} else {