EIP in the crash report points to p_mobj.c, line 2596:
// Don't explode on the sky!> if (!(mo->eflags & MFE_VERTICALFLIP) && mo->subsector->sector->floorpic == skyflatnum && mo->subsector->sector->floorheight == mo->floorz) P_RemoveMobj(mo);
This is from the code handling MF_MISSILE objects in P_ZMovement.
This crash line doesn't make a lot of sense to me at the moment, since mo being invalid would surely have crashed earlier in the function. Maybe gdb is giving me slightly the wrong thing, however.
What if mo is valid, but mo->subsector->sector is invalid?
(The two lines under the if are part of the same condition, so the RPT might point to the starting line instead of the exact line? 🤷)
Well, converting our debug file into a text file and making sense of the ASM, I actually find that it's trying to dereference mo->subsector when it actually has a value of NULL:
Looking at the code surrounding this, I have a hunch that this crash has to do with #561.
My guess is that, somehow, an object was removed via P_RemoveMobj, and its subsector value was set to NULL via that function. However, the object was not removed properly, and as such P_MobjWasRemoved still returns false. When it finally reaches this code, it tries to access a subsector value that does not exist, and crashes.
As for why this would happen, I have no idea, but the evidence seems to suggest this course of action. No other function in the game aside from P_RemoveMobj sets an object's subsector value to NULL. Plus, the fact that #561 even happens in the first place suggests that something is definitely getting past the game's radar somehow.