fix: crash from invalid weapon access and fixes ValveSoftware#3819 #3820
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Description
This pull request fixes a crash that was introduced in the 25th Anniversary Update of Half-Life, which occurs when a player dies while switching to a weapon that has run out of ammo. The crash stems from an invalid dereference of a null pointer when attempting to pack the dead player's weapons into a weapon box. Specifically,
rgpPackWeapons[0]
is null, leading to an invalid pev access.After extensive tracing, the root cause of the issue has been identified when switching back to a weapon with zero ammo, the weapon's
Holster()
function calls the following chain of events:DestroyItem()
->RemovePlayerItem()
->m_pActiveItem = NULL
Related Issue
Fixes issue #3819
Explanation of Changes
Added a check for
m_pActiveItem
to prevent dereferencing a null pointer when packing dead player's weaponsThe crash occurs due to an invalid
pev
pointer, wherergpPackWeapons[0]
isNULL
while attempting to dereference it. Upon death,rgpPackWeapons[nIndex] = pWeapon
is never assigned because it is inside a condition that checks whetherm_pActiveItem
is notNULL
.The chain leading to
m_pActiveItem
beingNULL
starts when a weapon is switched back to with0
ammo. When this happens, the weapon'sHolster()
function callsDestroyItem()
, which in turn callsRemovePlayerItem()
. This function setsm_pActiveItem = NULL
, meaning that when the player dies or kills themselves, thePackDeadPlayerItems()
function doesn't assignpWeapon
torgpPackWeapons[nIndex]
. As a result,rgpPackWeapons[0]
remainsNULL
, leading to the crash when trying to dereferencergpPackWeapons[0]->pev
.Added a validation in
CBasePlayer::SelectItem
andCBasePlayer::SelectLastItem
to ensure the selected weapon can be deployed before switching to it.The issue is also caused by players switching to unusable weapons (such as one with no ammo or one that has been destroyed), leading to crashes and unexpected behavior described in issue [HL25] Weapon model desync when switching while +attack held #3819. Adding
CanDeploy()
validation ensures that the player only switches to valid, deployable weapons. This prevents crashes due to switching to weapons that cannot be used (e.g., no ammo or destroyed weapons), avoiding invalid weapon access issues.