diff options
Diffstat (limited to 'patches/server/0976-Fix-possible-StackOverflowError-for-some-dispenses.patch')
-rw-r--r-- | patches/server/0976-Fix-possible-StackOverflowError-for-some-dispenses.patch | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/patches/server/0976-Fix-possible-StackOverflowError-for-some-dispenses.patch b/patches/server/0976-Fix-possible-StackOverflowError-for-some-dispenses.patch new file mode 100644 index 0000000000..21910b922f --- /dev/null +++ b/patches/server/0976-Fix-possible-StackOverflowError-for-some-dispenses.patch @@ -0,0 +1,108 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic <[email protected]> +Date: Sat, 29 Oct 2022 17:02:42 -0700 +Subject: [PATCH] Fix possible StackOverflowError for some dispenses + +For saddles, carpets, horse armor, and chests for horse-likes +a BlockDispenseEvent handler that always mutated the item without +changing the type would result in a SO error because when it went +to find the replacement dispense behavior (since the item "changed") +it didn't properly handle if the replacement was the same instance +of dispense behavior. + +Additionally equippable mob heads, wither skulls, and carved pumpkins +are subject to the same possible error. + +diff --git a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java +index 4fa838bf97ede6e1c893ba64f53aa7af5db0405a..32084df594649d8da04052bbfa111896d8ea1f91 100644 +--- a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java ++++ b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java +@@ -238,7 +238,7 @@ public interface DispenseItemBehavior { + // Chain to handler for new item + ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); + DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); +- if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != ArmorItem.DISPENSE_ITEM_BEHAVIOR) { ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { // Paper - fix possible StackOverflowError + idispensebehavior.dispense(pointer, eventStack); + return stack; + } +@@ -294,7 +294,7 @@ public interface DispenseItemBehavior { + // Chain to handler for new item + ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); + DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); +- if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != ArmorItem.DISPENSE_ITEM_BEHAVIOR) { ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { // Paper - fix possible StackOverflowError + idispensebehavior.dispense(pointer, eventStack); + return stack; + } +@@ -368,7 +368,7 @@ public interface DispenseItemBehavior { + // Chain to handler for new item + ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); + DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); +- if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != ArmorItem.DISPENSE_ITEM_BEHAVIOR) { ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { // Paper - fix possible StackOverflowError + idispensebehavior.dispense(pointer, eventStack); + return stack; + } +@@ -710,7 +710,7 @@ public interface DispenseItemBehavior { + OptionalDispenseItemBehavior dispensebehaviormaybe1 = new OptionalDispenseItemBehavior() { + @Override + protected ItemStack execute(BlockSource pointer, ItemStack stack) { +- this.setSuccess(ArmorItem.dispenseArmor(pointer, stack)); ++ this.setSuccess(ArmorItem.dispenseArmor(pointer, stack, this)); // Paper - fix possible StackOverflowError + return stack; + } + }; +@@ -764,7 +764,7 @@ public interface DispenseItemBehavior { + stack.shrink(1); + this.setSuccess(true); + } else { +- this.setSuccess(ArmorItem.dispenseArmor(pointer, stack)); ++ this.setSuccess(ArmorItem.dispenseArmor(pointer, stack, this)); // Paper - fix possible StackOverflowError + } + + return stack; +@@ -810,7 +810,7 @@ public interface DispenseItemBehavior { + stack.shrink(1); + this.setSuccess(true); + } else { +- this.setSuccess(ArmorItem.dispenseArmor(pointer, stack)); ++ this.setSuccess(ArmorItem.dispenseArmor(pointer, stack, this)); // Paper - fix possible StackOverflowError + } + + return stack; +diff --git a/src/main/java/net/minecraft/world/item/ArmorItem.java b/src/main/java/net/minecraft/world/item/ArmorItem.java +index e766397aae3f73548b290b0809b9d1ca0967ea39..786e4a8700cb84b16dd9b8892a0d1d5803924d81 100644 +--- a/src/main/java/net/minecraft/world/item/ArmorItem.java ++++ b/src/main/java/net/minecraft/world/item/ArmorItem.java +@@ -48,14 +48,20 @@ public class ArmorItem extends Item implements Equipable { + public static final DispenseItemBehavior DISPENSE_ITEM_BEHAVIOR = new DefaultDispenseItemBehavior() { + @Override + protected ItemStack execute(BlockSource pointer, ItemStack stack) { +- return ArmorItem.dispenseArmor(pointer, stack) ? stack : super.execute(pointer, stack); ++ return ArmorItem.dispenseArmor(pointer, stack, this) ? stack : super.execute(pointer, stack); // Paper - fix possible StackOverflowError + } + }; + protected final ArmorItem.Type type; + protected final Holder<ArmorMaterial> material; + private final Supplier<ItemAttributeModifiers> defaultModifiers; + ++ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper + public static boolean dispenseArmor(BlockSource pointer, ItemStack armor) { ++ // Paper start ++ return dispenseArmor(pointer, armor, null); ++ } ++ public static boolean dispenseArmor(BlockSource pointer, ItemStack armor, @javax.annotation.Nullable DispenseItemBehavior currentBehavior) { ++ // Paper end + BlockPos blockposition = pointer.pos().relative((Direction) pointer.state().getValue(DispenserBlock.FACING)); + List<LivingEntity> list = pointer.level().getEntitiesOfClass(LivingEntity.class, new AABB(blockposition), EntitySelector.NO_SPECTATORS.and(new EntitySelector.MobCanWearArmorEntitySelector(armor))); + +@@ -86,7 +92,7 @@ public class ArmorItem extends Item implements Equipable { + // Chain to handler for new item + ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); + DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); +- if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != ArmorItem.DISPENSE_ITEM_BEHAVIOR) { ++ if (idispensebehavior != DispenseItemBehavior.NOOP && (currentBehavior == null || idispensebehavior != currentBehavior)) { // Paper - fix possible StackOverflowError + idispensebehavior.dispense(pointer, eventStack); + return true; + } |