Mojira Archive
MC-276557

Server infinitely loops when a non-clipping trident attempts to collide with an entity

Not sure what else to say - a very special edge case causes the projectile collision loop to never terminate. This issue does not affect survival gameplay but can be reproduced by anyone with command access (specifically, /data).

This issue is unrelated to MC-276533 (that issue is a client infinite loop, while this one can affect the server, and existed prior to Minecraft snapshot 24w36a!)

Steps to reproduce

1. Run the following command to spawn a loyalty trident-wielding drowned:

/summon minecraft:drowned ~ ~ ~ {HandItems:[{id:trident,count:1,components:{enchantments:{loyalty:1}}}]}

2. Place the following command in a repeating command block to get the state where a trident is non-clipping but still will attempt to collide with entities:

/execute as @e[type=minecraft:trident] run data merge entity @s {PierceLevel:2b,DealtDamage:0b}

3. Place an entity in between the player the drowned targets and the drowned, such that the trident will intersect that entity on the way back. This may take a couple of tries.

Code analysis (Yarn mappings)

I will say that it's good blog post material.

While looking for some while-loops to exploit (a bit after MC-267937 and long before MC-276533, sorry about the delay to report...), I noticed a suspicious-looking while (this.isAlive()) loop. In Minecraft snapshot 24w36a, this loop only terminates each tick if the projectile is removed from the world, if it collides with a block, if it doesn't collide, or if it collides with an entity while not being no-clip.

That being said, if an entity happens to be no-clip and collide with an entity, the loop will not terminate. The only state in which a projectile can be no-clip is from a trident hitting an entity and entering the loyalty return phase. However, this phase also prevents further collisions by setting the TridentEntity#dealtDamage field to true, which causes the TridentEntity#getEntityCollision override to not provide an entity collision.

My initial assumption was that the no-clip state was always paired with disabling entity collisions, but I was incorrect; there is in fact a way to have the no-clip state with entity collisions! Simply deserialize entity NBT of the trident by setting the DealtDamage NBT field to false.

Now, the conditions are right and the server freeze will occur once the trident lands and starts returning to the drowned and passes through.

Unresolved

haykam

2024-09-10, 04:28 AM

2024-09-11, 10:39 PM

0

0

Plausible

Normal

Platform

Commands, Entities

1.21.1, 24w36a

-