Skip to content

Commit 41b6576

Browse files
committed
CFileLoaderSA fixes to reduce crashes even further
1 parent 810b33e commit 41b6576

File tree

2 files changed

+54
-11
lines changed

2 files changed

+54
-11
lines changed

Client/game_sa/CFileLoaderSA.cpp

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,18 @@ CEntitySAInterface* CFileLoaderSA::LoadObjectInstance(SFileObjectInstance* obj)
3434
return ((CEntitySAInterface * (__cdecl*)(SFileObjectInstance*, const char*))0x538090)(obj, nullptr);
3535
}
3636

37+
CEntitySAInterface* CFileLoaderSA::LoadObjectInstance(const char* szLine)
38+
{
39+
// Delegate to the global function that does the actual work
40+
return CFileLoader_LoadObjectInstance(szLine);
41+
}
42+
3743
class CAtomicModelInfo
3844
{
3945
public:
40-
void CAtomicModelInfo::DeleteRwObject() { ((void(__thiscall*)(CAtomicModelInfo*))(*(void***)this)[8])(this); }
46+
void DeleteRwObject() { ((void(__thiscall*)(CAtomicModelInfo*))(*(void***)this)[8])(this); }
4147

42-
void CAtomicModelInfo::SetAtomic(RpAtomic* atomic) { ((void(__thiscall*)(CAtomicModelInfo*, RpAtomic*))(*(void***)this)[15])(this, atomic); }
48+
void SetAtomic(RpAtomic* atomic) { ((void(__thiscall*)(CAtomicModelInfo*, RpAtomic*))(*(void***)this)[15])(this, atomic); }
4349
};
4450

4551
class CDamagableModelInfo
@@ -70,9 +76,10 @@ void GetNameAndDamage(const char* nodeName, char (&outName)[OutBuffSize], bool&
7076
// Copy `nodeName` into `outName` with `off` trimmed from the end
7177
// Eg.: `dmg_dam` with `off = 4` becomes `dmg`
7278
const auto TerminatedCopy = [&](size_t off) {
73-
dassert(nodeNameLen - off < OutBuffSize);
74-
strncpy_s(outName, nodeName,
75-
std::min(nodeNameLen - off, OutBuffSize - 1)); // By providing `OutBuffSize - 1` it is ensured the array will be null terminated
79+
dassert(nodeNameLen >= off && nodeNameLen - off < OutBuffSize);
80+
const size_t copyLen = std::min(nodeNameLen - off, OutBuffSize - 1);
81+
strncpy_s(outName, nodeName, copyLen);
82+
outName[copyLen] = '\0'; // Ensure null termination
7683
};
7784

7885
if (NodeNameEndsWith("_dam"))
@@ -90,7 +97,9 @@ void GetNameAndDamage(const char* nodeName, char (&outName)[OutBuffSize], bool&
9097
else
9198
{
9299
dassert(nodeNameLen < OutBuffSize);
93-
strncpy_s(outName, OutBuffSize, nodeName, OutBuffSize - 1);
100+
const size_t copyLen = std::min(nodeNameLen, OutBuffSize - 1);
101+
strncpy_s(outName, OutBuffSize, nodeName, copyLen);
102+
outName[copyLen] = '\0'; // Ensure null termination
94103
}
95104
}
96105
}
@@ -172,7 +181,19 @@ RpAtomic* CFileLoader_SetRelatedModelInfoCB(RpAtomic* atomic, SRelatedModelInfo*
172181
RwFrame* pOldFrame = reinterpret_cast<RwFrame*>(atomic->object.object.parent);
173182
char* frameNodeName = GetFrameNodeName(pOldFrame);
174183
bool bDamage = false;
175-
GetNameAndDamage(frameNodeName, name, bDamage);
184+
185+
// Check for null pointers before using them
186+
if (!frameNodeName)
187+
{
188+
// Handle case where frame node name is null
189+
strcpy_s(name, sizeof(name), "unknown");
190+
bDamage = false;
191+
}
192+
else
193+
{
194+
GetNameAndDamage(frameNodeName, name, bDamage);
195+
}
196+
176197
CVisibilityPlugins_SetAtomicRenderCallback(atomic, 0);
177198

178199
RpAtomic* pOldAtomic = reinterpret_cast<RpAtomic*>(pBaseModelInfo->pRwObject);
@@ -212,16 +233,34 @@ CEntitySAInterface* CFileLoader_LoadObjectInstance(const char* szLine)
212233
char szModelName[24];
213234
SFileObjectInstance inst;
214235

215-
sscanf(szLine, "%d %s %d %f %f %f %f %f %f %f %d", &inst.modelID, szModelName, &inst.interiorID, &inst.position.fX, &inst.position.fY, &inst.position.fZ,
236+
// Use safer scanf with width specifier to prevent buffer overflow
237+
int result = sscanf(szLine, "%d %23s %d %f %f %f %f %f %f %f %d", &inst.modelID, szModelName, &inst.interiorID, &inst.position.fX, &inst.position.fY, &inst.position.fZ,
216238
&inst.rotation.fX, &inst.rotation.fY, &inst.rotation.fZ, &inst.rotation.fW, &inst.lod);
239+
240+
// Check if all expected fields were parsed
241+
if (result != 11) {
242+
// Return null or handle error appropriately
243+
return nullptr;
244+
}
217245

218246
/*
219-
A quaternion is must be normalized. GTA is relying on an internal R* exporter and everything is OK,
247+
A quaternion must be normalized. GTA is relying on an internal R* exporter and everything is OK,
220248
but custom exporters might not contain the normalization. And we must do it instead.
221249
*/
222250
const float fLenSq = inst.rotation.LengthSquared();
223251
if (fLenSq > 0.0f && std::fabs(fLenSq - 1.0f) > std::numeric_limits<float>::epsilon())
224-
inst.rotation /= std::sqrt(fLenSq);
252+
{
253+
const float fLength = std::sqrt(fLenSq);
254+
inst.rotation /= fLength;
255+
}
256+
else if (fLenSq <= 0.0f)
257+
{
258+
// Handle degenerate case: set to identity quaternion
259+
inst.rotation.fX = 0.0f;
260+
inst.rotation.fY = 0.0f;
261+
inst.rotation.fZ = 0.0f;
262+
inst.rotation.fW = 1.0f;
263+
}
225264

226265
return ((CEntitySAInterface * (__cdecl*)(SFileObjectInstance*))0x538090)(&inst);
227266
}

Client/game_sa/CFileLoaderSA.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "CVector.h"
44
#include "CVector4D.h"
55

6+
// Forward declarations
67
class CEntitySAInterface;
78
struct RpAtomic;
89
struct RpClump;
@@ -29,11 +30,14 @@ class CFileLoaderSA
2930
CFileLoaderSA();
3031
~CFileLoaderSA();
3132

32-
static CEntitySAInterface* LoadObjectInstance(SFileObjectInstance*);
33+
// Two overloads for different use cases
34+
static CEntitySAInterface* LoadObjectInstance(SFileObjectInstance* obj);
35+
static CEntitySAInterface* LoadObjectInstance(const char* szLine);
3336

3437
static void StaticSetHooks();
3538
};
3639

40+
// Global functions that are hooked/called by the game
3741
bool CFileLoader_LoadAtomicFile(RwStream* stream, unsigned int modelId);
3842
RpAtomic* CFileLoader_SetRelatedModelInfoCB(RpAtomic* atomic, SRelatedModelInfo* pRelatedModelInfo);
3943
CEntitySAInterface* CFileLoader_LoadObjectInstance(const char* szLine);

0 commit comments

Comments
 (0)