Skip to content

Commit 1a105c3

Browse files
committed
Addendum to 9ff02d5
1 parent 9ff02d5 commit 1a105c3

File tree

4 files changed

+226
-26
lines changed

4 files changed

+226
-26
lines changed

Client/game_sa/CCamSA.cpp

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,19 @@
1212
#include "StdInc.h"
1313
#include "CCamSA.h"
1414
#include "CGameSA.h"
15+
#include <cmath>
1516

1617
extern CGameSA* pGame;
1718

1819
CEntity* CCamSA::GetTargetEntity() const
1920
{
21+
22+
if (!m_pInterface)
23+
return nullptr;
24+
2025
CEntitySAInterface* pInterface = m_pInterface->CamTargetEntity;
2126
if (pInterface)
22-
{
27+
{
2328
CPools* pPools = pGame->GetPools();
2429
return pPools->GetEntity((DWORD*)pInterface);
2530
}
@@ -28,9 +33,16 @@ CEntity* CCamSA::GetTargetEntity() const
2833

2934
void CCamSA::SetTargetEntity(CEntity* pEntity)
3035
{
36+
if (!m_pInterface)
37+
return;
38+
3139
if (pEntity)
3240
{
33-
m_pInterface->CamTargetEntity = pEntity->GetInterface();
41+
auto pEntityInterface = pEntity->GetInterface();
42+
if (!pEntityInterface)
43+
return;
44+
45+
m_pInterface->CamTargetEntity = pEntityInterface;
3446
}
3547
else
3648
{
@@ -40,13 +52,45 @@ void CCamSA::SetTargetEntity(CEntity* pEntity)
4052

4153
void CCamSA::GetDirection(float& fHorizontal, float& fVertical)
4254
{
43-
fHorizontal = m_pInterface->m_fHorizontalAngle;
44-
fVertical = m_pInterface->m_fVerticalAngle;
55+
if (!m_pInterface)
56+
{
57+
fHorizontal = 0.0f;
58+
fVertical = 0.0f;
59+
return;
60+
}
61+
62+
float fHoriz = m_pInterface->m_fHorizontalAngle;
63+
float fVert = m_pInterface->m_fVerticalAngle;
64+
65+
if (!std::isfinite(fHoriz) || !std::isfinite(fVert))
66+
{
67+
fHorizontal = 0.0f;
68+
fVertical = 0.0f;
69+
return;
70+
}
71+
72+
fHorizontal = fHoriz;
73+
fVertical = fVert;
4574
}
4675

4776
void CCamSA::SetDirection(float fHorizontal, float fVertical)
4877
{
78+
if (!m_pInterface)
79+
return;
80+
81+
// Validate input float values
82+
if (!std::isfinite(fHorizontal) || !std::isfinite(fVertical))
83+
return;
84+
85+
// Clamp angle values to prevent overflow
86+
constexpr float MIN_ANGLE = -360.0f;
87+
constexpr float MAX_ANGLE = 360.0f;
88+
89+
if (fHorizontal < MIN_ANGLE || fHorizontal > MAX_ANGLE ||
90+
fVertical < MIN_ANGLE || fVertical > MAX_ANGLE)
91+
return;
92+
4993
// Calculation @ sub 0x50F970
5094
m_pInterface->m_fHorizontalAngle = fHorizontal;
5195
m_pInterface->m_fVerticalAngle = fVertical;
52-
}
96+
}

Client/game_sa/CCamSA.h

Lines changed: 67 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -162,22 +162,75 @@ class CCamSA : public CCam
162162
CCamSAInterface* m_pInterface;
163163

164164
public:
165-
CCamSA(CCamSAInterface* pInterface) { m_pInterface = pInterface; }
165+
CCamSA(CCamSAInterface* pInterface) : m_pInterface(pInterface)
166+
{
167+
if (!pInterface)
168+
{
169+
m_pInterface = nullptr;
170+
}
171+
}
172+
166173
CCamSAInterface* GetInterface() { return m_pInterface; }
167174

168-
CVector* GetFront() const override { return &m_pInterface->Front; }
169-
CVector* GetUp() const override { return &m_pInterface->Up; }
170-
CVector* GetSource() const override { return &m_pInterface->Source; }
171-
unsigned int GetMode() const override { return m_pInterface->Mode; }
172-
float GetFOV() const override { return m_pInterface->FOV; }
173-
void SetFOV(float fFOV) override { m_pInterface->FOV = fFOV; }
174-
void GetDirection(float& fHorizontal, float& fVertical) override;
175-
void SetDirection(float fHorizontal, float fVertical) override;
176-
177-
CVector* GetFixedModeSource() const override { return &m_pInterface->m_cvecCamFixedModeSource; }
178-
CVector* GetFixedModeVector() const override { return &m_pInterface->m_cvecCamFixedModeVector; }
179-
CVector* GetTargetHistoryPos() const override { return m_pInterface->m_aTargetHistoryPos; }
175+
CVector* GetFront() const override
176+
{
177+
return m_pInterface ? &m_pInterface->Front : nullptr;
178+
}
179+
180+
CVector* GetUp() const override
181+
{
182+
return m_pInterface ? &m_pInterface->Up : nullptr;
183+
}
184+
185+
CVector* GetSource() const override
186+
{
187+
return m_pInterface ? &m_pInterface->Source : nullptr;
188+
}
189+
190+
unsigned int GetMode() const override
191+
{
192+
return m_pInterface ? static_cast<unsigned int>(m_pInterface->Mode) : 0;
193+
}
194+
195+
float GetFOV() const override
196+
{
197+
if (!m_pInterface)
198+
return 70.0f; // Default FOV
199+
200+
float fov = m_pInterface->FOV;
201+
return std::isfinite(fov) ? fov : 70.0f;
202+
}
203+
204+
void SetFOV(float fFOV) override
205+
{
206+
if (!m_pInterface)
207+
return;
208+
209+
// Validate FOV range
210+
if (!std::isfinite(fFOV) || fFOV <= 0.0f || fFOV >= 180.0f)
211+
return;
212+
213+
m_pInterface->FOV = fFOV;
214+
}
215+
216+
void GetDirection(float& fHorizontal, float& fVertical) override;
217+
void SetDirection(float fHorizontal, float fVertical) override;
218+
219+
CVector* GetFixedModeSource() const override
220+
{
221+
return m_pInterface ? &m_pInterface->m_cvecCamFixedModeSource : nullptr;
222+
}
223+
224+
CVector* GetFixedModeVector() const override
225+
{
226+
return m_pInterface ? &m_pInterface->m_cvecCamFixedModeVector : nullptr;
227+
}
228+
229+
CVector* GetTargetHistoryPos() const override
230+
{
231+
return m_pInterface ? m_pInterface->m_aTargetHistoryPos : nullptr;
232+
}
180233

181234
CEntity* GetTargetEntity() const override;
182235
void SetTargetEntity(CEntity* pEntity) override;
183-
};
236+
};

Client/game_sa/CCameraSA.cpp

Lines changed: 98 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,12 @@
1212
#include "StdInc.h"
1313
#include "CCameraSA.h"
1414
#include "CGameSA.h"
15+
#include <mutex>
16+
#include <cmath>
1517

1618
extern CGameSA* pGame;
1719

20+
static std::mutex s_cameraClipMutex;
1821
static bool bCameraClipObjects;
1922
static bool bCameraClipVehicles;
2023

@@ -28,19 +31,54 @@ void HOOK_Camera_CollisionDetection();
2831

2932
CCameraSA::CCameraSA(CCameraSAInterface* cameraInterface)
3033
{
34+
if (!cameraInterface)
35+
{
36+
internalInterface = nullptr;
37+
// Initialize all camera pointers to null
38+
for (int i = 0; i < MAX_CAMS; i++)
39+
Cams[i] = nullptr;
40+
return;
41+
}
42+
3143
internalInterface = cameraInterface;
44+
3245
for (int i = 0; i < MAX_CAMS; i++)
33-
Cams[i] = new CCamSA(&internalInterface->Cams[i]);
34-
bCameraClipObjects = true;
35-
bCameraClipVehicles = true;
46+
{
47+
try {
48+
Cams[i] = new CCamSA(&internalInterface->Cams[i]);
49+
}
50+
catch (...)
51+
{
52+
// Clean up on failure
53+
for (int j = 0; j < i; j++)
54+
{
55+
delete Cams[j];
56+
Cams[j] = nullptr;
57+
}
58+
internalInterface = nullptr;
59+
throw;
60+
}
61+
}
62+
63+
// Thread-safe initialization
64+
{
65+
std::lock_guard<std::mutex> lock(s_cameraClipMutex);
66+
bCameraClipObjects = true;
67+
bCameraClipVehicles = true;
68+
}
69+
3670
HookInstall(HOOKPOS_Camera_CollisionDetection, (DWORD)HOOK_Camera_CollisionDetection, 5);
3771
}
3872

3973
CCameraSA::~CCameraSA()
4074
{
4175
for (int i = 0; i < MAX_CAMS; i++)
4276
{
43-
delete Cams[i];
77+
if (Cams[i])
78+
{
79+
delete Cams[i];
80+
Cams[i] = nullptr;
81+
}
4482
}
4583
}
4684

@@ -89,7 +127,11 @@ void CCameraSA::TakeControl(CEntity* entity, eCamMode CamMode, int CamSwitchStyl
89127
return;
90128

91129
CCameraSAInterface* cameraInterface = GetInterface();
92-
// __thiscall
130+
if (!cameraInterface)
131+
return;
132+
133+
if (CamSwitchStyle < 0 || CamSwitchStyle > 10)
134+
return;
93135

94136
DWORD CCamera__TakeControl = FUNC_TakeControl;
95137
_asm
@@ -196,7 +238,17 @@ void CCameraSA::RestoreLastGoodState()
196238

197239
CMatrix* CCameraSA::GetMatrix(CMatrix* matrix)
198240
{
199-
CMatrix_Padded* pCamMatrix = &GetInterface()->m_cameraMatrix; // ->matrix;
241+
if (!matrix)
242+
return nullptr;
243+
244+
CCameraSAInterface* cameraInterface = GetInterface();
245+
if (!cameraInterface)
246+
{
247+
*matrix = CMatrix();
248+
return matrix;
249+
}
250+
251+
CMatrix_Padded* pCamMatrix = &cameraInterface->m_cameraMatrix;
200252
if (pCamMatrix)
201253
{
202254
matrix->vFront = pCamMatrix->vFront;
@@ -234,11 +286,26 @@ void CCameraSA::SetMatrix(CMatrix* matrix)
234286

235287
void CCameraSA::Find3rdPersonCamTargetVector(float fDistance, CVector* vecGunMuzzle, CVector* vecSource, CVector* vecTarget)
236288
{
289+
if (!vecGunMuzzle || !vecSource || !vecTarget)
290+
return;
291+
292+
// Validate float parameter to prevent NaN/infinity issues
293+
if (!std::isfinite(fDistance) || fDistance < 0.0f)
294+
return;
295+
237296
float fOriginX = vecGunMuzzle->fX;
238297
float fOriginY = vecGunMuzzle->fY;
239298
float fOriginZ = vecGunMuzzle->fZ;
299+
300+
if (!std::isfinite(fOriginX) || !std::isfinite(fOriginY) || !std::isfinite(fOriginZ))
301+
return;
302+
240303
DWORD dwFunc = FUNC_Find3rdPersonCamTargetVector;
241304
CCameraSAInterface* cameraInterface = GetInterface();
305+
306+
if (!cameraInterface)
307+
return;
308+
242309
_asm
243310
{
244311
mov ecx, cameraInterface
@@ -334,8 +401,18 @@ int CCameraSA::GetFadingDirection()
334401

335402
void CCameraSA::Fade(float fFadeOutTime, int iOutOrIn)
336403
{
404+
if (!std::isfinite(fFadeOutTime) || fFadeOutTime < 0.0f || fFadeOutTime > 60.0f)
405+
return;
406+
407+
if (iOutOrIn < 0 || iOutOrIn > 1)
408+
return;
409+
337410
DWORD dwFunc = FUNC_Fade;
338411
CCameraSAInterface* cameraInterface = GetInterface();
412+
413+
if (!cameraInterface)
414+
return;
415+
339416
_asm
340417
{
341418
mov ecx, cameraInterface
@@ -369,8 +446,18 @@ float CCameraSA::GetCameraRotation()
369446

370447
RwMatrix* CCameraSA::GetLTM()
371448
{
449+
CCameraSAInterface* cameraInterface = GetInterface();
450+
if (!cameraInterface)
451+
return nullptr;
452+
453+
if (!cameraInterface->m_pRwCamera)
454+
return nullptr;
455+
456+
if (!cameraInterface->m_pRwCamera->object.object.parent)
457+
return nullptr;
458+
372459
// RwFrameGetLTM
373-
return ((RwMatrix*(_cdecl*)(void*))0x7F0990)(GetInterface()->m_pRwCamera->object.object.parent);
460+
return ((RwMatrix*(_cdecl*)(void*))0x7F0990)(cameraInterface->m_pRwCamera->object.object.parent);
374461
}
375462

376463
CEntity* CCameraSA::GetTargetEntity()
@@ -386,12 +473,16 @@ CEntity* CCameraSA::GetTargetEntity()
386473

387474
void CCameraSA::SetCameraClip(bool bObjects, bool bVehicles)
388475
{
476+
// Thread-safe access to static variables
477+
std::lock_guard<std::mutex> lock(s_cameraClipMutex);
389478
bCameraClipObjects = bObjects;
390479
bCameraClipVehicles = bVehicles;
391480
}
392481

393482
void CCameraSA::GetCameraClip(bool& bObjects, bool& bVehicles)
394483
{
484+
// Thread-safe access to static variables
485+
std::lock_guard<std::mutex> lock(s_cameraClipMutex);
395486
bObjects = bCameraClipObjects;
396487
bVehicles = bCameraClipVehicles;
397488
}

Client/mods/deathmatch/logic/rpc/CCameraRPCs.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,14 @@ void CCameraRPCs::SetCameraMatrix(NetBitStreamInterface& bitStream)
4242
bitStream.Read(fRoll);
4343
bitStream.Read(fFOV);
4444

45+
// Validate float values to prevent potential issues
46+
if (!std::isfinite(fRoll) || !std::isfinite(fFOV) ||
47+
!std::isfinite(vecPosition.fX) || !std::isfinite(vecPosition.fY) || !std::isfinite(vecPosition.fZ) ||
48+
!std::isfinite(vecLookAt.fX) || !std::isfinite(vecLookAt.fY) || !std::isfinite(vecLookAt.fZ))
49+
{
50+
return; // Invalid float values (NaN, infinity, etc.)
51+
}
52+
4553
// Validate camera pointer before use
4654
if (!m_pCamera)
4755
return;
@@ -76,6 +84,10 @@ void CCameraRPCs::SetCameraTarget(NetBitStreamInterface& bitStream)
7684
if (!pEntity)
7785
return;
7886

87+
// Check if entity is being deleted - critical memory safety check
88+
if (pEntity->IsBeingDeleted())
89+
return;
90+
7991
switch (pEntity->GetType())
8092
{
8193
case CCLIENTPLAYER:

0 commit comments

Comments
 (0)