aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/0976-Fix-possible-StackOverflowError-for-some-dispenses.patch
blob: 21910b922fe0482a437f7e1c25348f2d9a722bb3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
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;
                 }