mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-26 14:30:17 +01:00
173 lines
12 KiB
Diff
173 lines
12 KiB
Diff
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
|
|
index 4929bac8e476664086470f078efce6c0a6164413..f88dd37783b3c155c23b547c360b8d3c16e030c0 100644
|
|
--- a/src/main/java/net/minecraft/nbt/NbtUtils.java
|
|
+++ b/src/main/java/net/minecraft/nbt/NbtUtils.java
|
|
@@ -149,8 +149,10 @@ public final class NbtUtils {
|
|
if (!nbt.contains("Name", 8)) {
|
|
return Blocks.AIR.defaultBlockState();
|
|
} else {
|
|
- ResourceLocation resourceLocation = ResourceLocation.parse(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();
|
|
+ // 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 87afe84791af2d5e9f869cd4c09eed4bb5fee75b..1967c43ee3a12e63365cc40ee6565307e2fd73cf 100644
|
|
--- a/src/main/java/net/minecraft/resources/ResourceLocation.java
|
|
+++ b/src/main/java/net/minecraft/resources/ResourceLocation.java
|
|
@@ -41,6 +41,13 @@ public final class ResourceLocation implements Comparable<ResourceLocation> {
|
|
|
|
assert isValidPath(path);
|
|
|
|
+ // 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/RandomizableContainer.java b/src/main/java/net/minecraft/world/RandomizableContainer.java
|
|
index 084935138b1484f3d96e99f4e5655a6c04931907..9e357abe13f55bd9ce3a1d5348bcf19a15ea5433 100644
|
|
--- 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, ResourceLocation.parse(nbt.getString("LootTable"))));
|
|
+ this.setLootTable(net.minecraft.Optionull.map(ResourceLocation.tryParse(nbt.getString("LootTable")), rl -> ResourceKey.create(Registries.LOOT_TABLE, rl))); // Paper - Validate ResourceLocation
|
|
if (this.lootableData() != null && this.getLootTable() != null) this.lootableData().loadNbt(nbt); // Paper - LootTable API
|
|
if (nbt.contains("LootTableSeed", 4)) {
|
|
this.setLootTableSeed(nbt.getLong("LootTableSeed"));
|
|
diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java
|
|
index 2cd74db8e3c51c97a2abcb801bb5c15cd55ca8f9..0ec3e1837e36d17e9ff33e7d50c66353aa7539db 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/EntityType.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/EntityType.java
|
|
@@ -690,7 +690,7 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT
|
|
}
|
|
|
|
public static Optional<EntityType<?>> by(CompoundTag nbt) {
|
|
- return BuiltInRegistries.ENTITY_TYPE.getOptional(ResourceLocation.parse(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/Leashable.java b/src/main/java/net/minecraft/world/entity/Leashable.java
|
|
index 68b869c5d76aeb390a05b053eef70486bd4126fd..48f89ec0f02b85092d03fddeec961f1eba5d4a2a 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/Leashable.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/Leashable.java
|
|
@@ -65,7 +65,13 @@ public interface Leashable {
|
|
@Nullable
|
|
private static Leashable.LeashData readLeashDataInternal(CompoundTag nbt) {
|
|
if (nbt.contains("leash", 10)) {
|
|
- return new Leashable.LeashData(Either.left(nbt.getCompound("leash").getUUID("UUID")));
|
|
+ // Paper start
|
|
+ final CompoundTag leashTag = nbt.getCompound("leash");
|
|
+ if (!leashTag.hasUUID("UUID")) {
|
|
+ return null;
|
|
+ }
|
|
+ return new Leashable.LeashData(Either.left(leashTag.getUUID("UUID")));
|
|
+ // Paper end
|
|
} else {
|
|
if (nbt.contains("leash", 11)) {
|
|
Either<UUID, BlockPos> either = (Either) NbtUtils.readBlockPos(nbt, "leash").map(Either::right).orElse(null); // CraftBukkit - decompile error
|
|
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
|
index 2715ba6325ecf82dee237bb53372e3aac3972112..95c2e2d73aefcf7c436fad3066e1fedc7299faa1 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
|
@@ -909,11 +909,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 13064a73a9e3b45d32a098c4179cd980be508abc..a66ed6527d95b9c40b6c5983455fc078fd9eb2bf 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/Mob.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/Mob.java
|
|
@@ -609,7 +609,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
|
|
this.readLeashData(nbt);
|
|
this.setLeftHanded(nbt.getBoolean("LeftHanded"));
|
|
if (nbt.contains("DeathLootTable", 8)) {
|
|
- this.lootTable = Optional.of(ResourceKey.create(Registries.LOOT_TABLE, ResourceLocation.parse(nbt.getString("DeathLootTable"))));
|
|
+ this.lootTable = Optional.ofNullable(ResourceLocation.tryParse(nbt.getString("DeathLootTable"))).map((rs) -> ResourceKey.create(Registries.LOOT_TABLE, rs)); // Paper - Validate ResourceLocation
|
|
} else {
|
|
this.lootTable = Optional.empty();
|
|
}
|
|
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 758fa49f9b420fdbb583ca3443b81ca151478ea8..6edb5a76a503242a6528875184ccd62d6499205f 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java
|
|
@@ -710,7 +710,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(ResourceLocation.parse(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
|
|
}
|
|
|
|
if (nbt.contains("item", 10)) {
|
|
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 874a44ab77248665c2db243764e8542bfc0d6514..cc7826a10f22e3307231d887db2fee98063b1f46 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/vehicle/ContainerEntity.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/vehicle/ContainerEntity.java
|
|
@@ -73,7 +73,7 @@ public interface ContainerEntity extends Container, MenuProvider {
|
|
default void readChestVehicleSaveData(CompoundTag nbt, HolderLookup.Provider registries) {
|
|
this.clearItemStacks();
|
|
if (nbt.contains("LootTable", 8)) {
|
|
- this.setContainerLootTable(ResourceKey.create(Registries.LOOT_TABLE, ResourceLocation.parse(nbt.getString("LootTable"))));
|
|
+ this.setContainerLootTable(net.minecraft.Optionull.map(ResourceLocation.tryParse(nbt.getString("LootTable")), rl -> ResourceKey.create(Registries.LOOT_TABLE, rl))); // Paper - Validate ResourceLocation
|
|
// Paper start - LootTable API
|
|
if (this.getContainerLootTable() != null) {
|
|
this.lootableData().loadNbt(nbt);
|
|
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 5fe0879efb35970e49d0654c4cb27195c6cc88a4..a9809c18233d82f910735e59363a49de488defcd 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
|
|
@@ -178,7 +178,11 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit
|
|
while (iterator.hasNext()) {
|
|
String s = (String) iterator.next();
|
|
|
|
- this.recipesUsed.put(ResourceKey.create(Registries.RECIPE, ResourceLocation.parse(s)), nbttagcompound1.getInt(s));
|
|
+ // Paper start - Validate ResourceLocation
|
|
+ final ResourceLocation resourceLocation = ResourceLocation.tryParse(s);
|
|
+ if (resourceLocation != null) {
|
|
+ this.recipesUsed.put(ResourceKey.create(Registries.RECIPE, resourceLocation), nbttagcompound1.getInt(s));
|
|
+ }
|
|
}
|
|
|
|
// 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 1bfffbf54b1b440c6e19a908ea2bd70387d06b5c..b08867878e56f88569d547765f29cab018a9e791 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
|
|
@@ -194,7 +194,7 @@ public class BrushableBlockEntity extends BlockEntity {
|
|
|
|
private boolean tryLoadLootTable(CompoundTag nbt) {
|
|
if (nbt.contains("LootTable", 8)) {
|
|
- this.lootTable = ResourceKey.create(Registries.LOOT_TABLE, ResourceLocation.parse(nbt.getString("LootTable")));
|
|
+ this.lootTable = net.minecraft.Optionull.map(ResourceLocation.tryParse(nbt.getString("LootTable")), rl -> ResourceKey.create(Registries.LOOT_TABLE, rl)); // Paper - Validate ResourceLocation
|
|
this.lootTableSeed = nbt.getLong("LootTableSeed");
|
|
return true;
|
|
} else {
|