Skip to content
Permalink
Browse files

Fix crash in CWorldSA::FindClosestRailTrackNode

In the crash, `ucDesiredTrackId` has the value of `0xC1` (193), which is bigger than NUM_RAILTRACKS (= 4). `iNodeId` wasn't set properly (= -1) and then the code crashed at `aTrackNodes[ucOutTrackId][iNodeId]`.
  • Loading branch information...
botder committed Sep 9, 2019
1 parent 1d4c2a2 commit 34f49b3e2a3292dfa381a8df11de4c31a00d29ce
Showing with 6 additions and 20 deletions.
  1. +6 −20 Client/game_sa/CWorldSA.cpp
@@ -611,6 +611,9 @@ int CWorldSA::FindClosestRailTrackNode(const CVector& vecPosition, uchar& ucOutT
SRailNodeSA** aTrackNodes = (SRailNodeSA**)ARRAY_RailTrackNodePointers;
uchar ucDesiredTrackId = ucOutTrackId;

if (ucDesiredTrackId >= NUM_RAILTRACKS)
ucDesiredTrackId = 0xFF;

for (uchar ucTrackId = 0; ucTrackId < NUM_RAILTRACKS; ++ucTrackId)
{
if ((ucDesiredTrackId == 0xFF || ucTrackId == ucDesiredTrackId) && aNumTrackNodes[ucTrackId] > 0)
@@ -632,29 +635,12 @@ int CWorldSA::FindClosestRailTrackNode(const CVector& vecPosition, uchar& ucOutT
}

// Read rail distance
fOutRailDistance = aTrackNodes[ucOutTrackId][iNodeId].sRailDistance * 3.33333334f;

return iNodeId;

/*DWORD dwFunc = FUNC_GetTrainNodeNearPoint; // __cdecl
int iNodeId;
*pOutTrackId = 0;
float fX = vecPosition.fX;
float fY = vecPosition.fY;
float fZ = vecPosition.fZ;
_asm
if (iNodeId != -1)
{
push pOutTrackId
push fZ
push fY
push fZ
call dwFunc
mov iNodeId, eax
add esp, 4*4
fOutRailDistance = aTrackNodes[ucOutTrackId][iNodeId].sRailDistance * 3.33333334f;
}

return iNodeId;*/
return iNodeId;
}

void CWorldSA::RemoveBuilding(unsigned short usModelToRemove, float fRange, float fX, float fY, float fZ, char cInterior, uint* pOutAmount)

2 comments on commit 34f49b3

@qaisjp

This comment has been minimized.

Copy link
Member

replied Sep 12, 2019

How do you reproduce this?

@botder

This comment has been minimized.

Copy link
Member Author

replied Sep 13, 2019

How do you reproduce this?

By manually setting the invalid track ID in CClientVehicle::Create() before this line:

m_pVehicle = g_pGame->GetPools()->AddTrain(this, &m_Matrix.vPos, dwModels, 1, m_bTrainDirection, m_ucTrackID);

AddTrain then calls
int iNodeId = pGame->GetWorld()->FindClosestRailTrackNode(*vecPosition, ucTrackId, fRailDistance);

I don't know where that invalid track ID came from, I only fixed the follow-up crash.

Please sign in to comment.
You can’t perform that action at this time.