@@ -241,6 +241,9 @@ void OpenContain::addOrRemoveObjFromWorld(Object* obj, Bool add)
241241 }
242242 else
243243 {
244+ DEBUG_ASSERTCRASH (!getObject ()->isEffectivelyDead () && !getObject ()->isDestroyed (),
245+ (" object shouldn't become an occupant of a dead or destroyed container object" ));
246+
244247 // remove object from its group (if any)
245248 obj->leaveGroup ();
246249
@@ -292,11 +295,26 @@ void OpenContain::addToContain( Object *rider )
292295 if ( rider == nullptr )
293296 return ;
294297
298+ #if !RETAIL_COMPATIBLE_CRC
299+ // TheSuperHackers @bugfix Caball009 25/05/2026 Ensure the occupant is only added to a non-destroyed
300+ // container to avoid an invalid state and use-after-free bugs when accessing the contained by pointer.
301+ if (getObject ()->isDestroyed ())
302+ {
303+ DEBUG_CRASH ((" '%s' is about to be added to '%s', which is destroyed" ,
304+ rider->getTemplate ()->getName ().str (), getObject ()->getTemplate ()->getName ().str ()));
305+ return ;
306+ }
307+ #endif
308+
295309 // TheSuperHackers @bugfix Stubbjax 06/02/2026 Ensure the rider is not destroyed to prevent a
296310 // likely crash if it enters the container on the same frame. If this occurs with an unpatched
297311 // client present in a match, the game has a small chance to mismatch.
298312 if (rider->isDestroyed ())
313+ {
314+ DEBUG_CRASH ((" '%s', which is destroyed, is about to be added to '%s'" ,
315+ rider->getTemplate ()->getName ().str (), getObject ()->getTemplate ()->getName ().str ()));
299316 return ;
317+ }
300318
301319 Drawable *riderDraw = rider->getDrawable ();
302320 Bool wasSelected = FALSE ;
0 commit comments