Description
CKnife::Swing can crash with a null-pointer dereference when the melee trace hits an edict for which CBaseEntity::Instance(tr.pHit) returns NULL.
In the REGAMEDLL_FIXES build the defensive if (pEntity) guard is compiled out, so pEntity is dereferenced unconditionally right after the trace:
CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit);
SetPlayerShieldAnim();
m_pPlayer->SetAnimation(PLAYER_ATTACK1);
ClearMultiDamage();
pEntity->TraceAttack( ... ); // <-- pEntity may be NULL -> SIGSEGV
The #ifndef REGAMEDLL_FIXES / if (pEntity) // -V595 block that used to protect this path is disabled in fixes builds, and current master still has no null-check before pEntity->TraceAttack.
Crash backtrace (observed)
Crash: signal 11 errno 0 with code 1 at 0x4 (nil)
1: CKnife::Swing(int)+1289 (cs.so)
2: CKnife::PrimaryAttack()+13 (cs.so)
3: CBasePlayerWeapon::ItemPostFrame_OrigFunc()+873
4: CBasePlayerWeapon::ItemPostFrame()+128
5: CBasePlayer::PostThink_OrigFunc()+238
...
9: SV_RunCmd
10: SV_ParseClientMove
Fault address 0x4 is consistent with dereferencing a NULL CBaseEntity* (accessing an early member/pev).
How it is triggered (logic, engine-dependent)
The trigger is a stale/orphan player edict that is still SOLID (so the knife trace can hit it) but no longer has a valid private-data / CBaseEntity instance, so CBaseEntity::Instance(tr.pHit) returns NULL.
In our case the engine keeps such an edict around after a client leaves without a proper disconnect notification (the gamedll logs client_disconnected and client_remove forwards have been disabled). The orphan edict stays SOLID_SLIDEBOX for a short window; if another player swings a knife through that spot during the window, Swing crashes.
It is timing-dependent and hard to reproduce on demand, but the code path is clearly unsafe regardless of how pHit ends up pointing at an instance-less edict.
Environment
- Engine: Xash3D FWGS 0.21 (build 4142-18dddaf-master, linux-i386) — NOT ReHLDS
- GameDLL: ReGameDLL_CS 5.30.0.814-dev (build May 18 2026, commit 781a68a), REGAMEDLL_FIXES enabled
- Metamod: Metamod-FWGS 1.0.0.222+m (commit c0ad71a)
- AMXX: 1.10.0.5479
- OS: Ubuntu 24.04.4 LTS (x86_64 host, i386 binaries)
Suggested fix
Re-add a null guard in the REGAMEDLL_FIXES path before dereferencing pEntity:
CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit);
if (pEntity) // trace can hit an edict without a valid CBaseEntity instance
{
SetPlayerShieldAnim();
m_pPlayer->SetAnimation(PLAYER_ATTACK1);
ClearMultiDamage();
pEntity->TraceAttack( ... );
ApplyMultiDamage(...);
}
(We work around it plugin-side by forcing such orphan edicts to SOLID_NOT every frame so the knife trace can't hit them, but the DLL-side guard would fix the root cause.)
Description
CKnife::Swingcan crash with a null-pointer dereference when the melee trace hits an edict for whichCBaseEntity::Instance(tr.pHit)returnsNULL.In the
REGAMEDLL_FIXESbuild the defensiveif (pEntity)guard is compiled out, sopEntityis dereferenced unconditionally right after the trace:The
#ifndef REGAMEDLL_FIXES / if (pEntity) // -V595block that used to protect this path is disabled in fixes builds, and currentmasterstill has no null-check beforepEntity->TraceAttack.Crash backtrace (observed)
Fault address
0x4is consistent with dereferencing a NULLCBaseEntity*(accessing an early member/pev).How it is triggered (logic, engine-dependent)
The trigger is a stale/orphan player edict that is still
SOLID(so the knife trace can hit it) but no longer has a valid private-data /CBaseEntityinstance, soCBaseEntity::Instance(tr.pHit)returnsNULL.In our case the engine keeps such an edict around after a client leaves without a proper disconnect notification (the gamedll logs
client_disconnected and client_remove forwards have been disabled). The orphan edict staysSOLID_SLIDEBOXfor a short window; if another player swings a knife through that spot during the window,Swingcrashes.It is timing-dependent and hard to reproduce on demand, but the code path is clearly unsafe regardless of how
pHitends up pointing at an instance-less edict.Environment
Suggested fix
Re-add a null guard in the
REGAMEDLL_FIXESpath before dereferencingpEntity:(We work around it plugin-side by forcing such orphan edicts to
SOLID_NOTevery frame so the knife trace can't hit them, but the DLL-side guard would fix the root cause.)