Skip to content

Commit feb7e65

Browse files
committed
Fix crashes introduced by PR #3845
Like a common one at gta_sa 0x0116112B
1 parent 9f79d78 commit feb7e65

File tree

3 files changed

+74
-45
lines changed

3 files changed

+74
-45
lines changed

Client/game_sa/CGameSA.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -896,12 +896,13 @@ void CGameSA::SetIgnoreFireStateEnabled(bool isEnabled)
896896

897897
if (isEnabled)
898898
{
899-
MemSet((void*)0x6511B9, 0x90, 10); // CCarEnterExit::IsVehicleStealable
900-
MemSet((void*)0x643A95, 0x90, 14); // CTaskComplexEnterCar::CreateFirstSubTask
901-
MemSet((void*)0x6900B5, 0x90, 14); // CTaskComplexCopInCar::ControlSubTask
902-
MemSet((void*)0x64F3DB, 0x90, 14); // CCarEnterExit::IsPlayerToQuitCarEnter
903-
904-
MemSet((void*)0x685A7F, 0x90, 14); // CTaskSimplePlayerOnFoot::ProcessPlayerWeapon
899+
// All these patches disable fire state checks (m_pFire != nullptr)
900+
// Related crash protection is handled by checks in TaskSA.cpp and CTaskManagementSystemSA.cpp
901+
MemSet((void*)0x6511B9, 0x90, 10); // CCarEnterExit::IsVehicleStealable - fire check
902+
MemSet((void*)0x643A95, 0x90, 14); // CTaskComplexEnterCar::CreateFirstSubTask - fire check
903+
MemSet((void*)0x6900B5, 0x90, 14); // CTaskComplexCopInCar::ControlSubTask - fire check
904+
MemSet((void*)0x64F3DB, 0x90, 14); // CCarEnterExit::IsPlayerToQuitCarEnter - fire check
905+
MemSet((void*)0x685A7F, 0x90, 14); // CTaskSimplePlayerOnFoot::ProcessPlayerWeapon - fire check
905906

906907
MemSet((void*)0x53A899, 0x90, 5); // CFire::ProcessFire
907908
MemSet((void*)0x53A990, 0x90, 5); // CFire::ProcessFire

Client/game_sa/CTaskManagementSystemSA.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,21 @@ void CTaskManagementSystemSA::RemoveTask(CTaskSAInterface* pTaskInterface)
103103
CTaskSA* CTaskManagementSystemSA::GetTask(CTaskSAInterface* pTaskInterface)
104104
{
105105
// Return NULL if we got passed NULL
106-
if (pTaskInterface == 0)
107-
return NULL;
106+
if (!pTaskInterface)
107+
return nullptr;
108+
109+
// Check vtable pointer to prevent crash from corrupted task objects
110+
TaskVTBL* pVTBL = pTaskInterface->VTBL;
111+
if (!pVTBL)
112+
return nullptr;
113+
114+
// Vtable should be in executable memory range (.text/.rdata sections)
115+
// GTA SA base is around 0x400000-0x900000 range
116+
constexpr DWORD GTA_BASE_MIN = 0x400000;
117+
constexpr DWORD GTA_BASE_MAX = 0x900000;
118+
DWORD dwVTableAddr = reinterpret_cast<DWORD>(pVTBL);
119+
if (dwVTableAddr < GTA_BASE_MIN || dwVTableAddr > GTA_BASE_MAX)
120+
return nullptr;
108121

109122
// Find it in our list
110123
STaskListItem* pListItem;
@@ -123,7 +136,7 @@ CTaskSA* CTaskManagementSystemSA::GetTask(CTaskSAInterface* pTaskInterface)
123136
// its not existed before, lets create the task
124137
// First, we create a temp task
125138
int iTaskType = 9999;
126-
DWORD dwFunc = pTaskInterface->VTBL->GetTaskType;
139+
DWORD dwFunc = pVTBL->GetTaskType;
127140
if (dwFunc && dwFunc != 0x82263A)
128141
{
129142
_asm

Client/game_sa/TaskSA.cpp

Lines changed: 51 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,18 @@ CTask* CTaskSA::GetSubTask()
8484
{
8585
static CTaskManagementSystemSA* s_pTaskManagementSystem = pGame->GetTaskManagementSystem();
8686

87-
DWORD dwThisInterface = (DWORD)GetInterface();
88-
DWORD dwFunc = GetInterface()->VTBL->GetSubTask;
87+
CTaskSAInterface* pTaskInterface = GetInterface();
88+
if (!pTaskInterface)
89+
return nullptr;
90+
91+
DWORD dwFunc = pTaskInterface->VTBL->GetSubTask;
92+
if (!dwFunc || dwFunc == 0x82263A)
93+
return nullptr;
94+
8995
DWORD dwReturn = 0;
9096
_asm
9197
{
92-
mov ecx, dwThisInterface
98+
mov ecx, pTaskInterface
9399
call dwFunc
94100
mov dwReturn, eax
95101
}
@@ -326,21 +332,24 @@ CTask* CTaskComplexSA::CreateNextSubTask(CPed* pPed)
326332
{
327333
CPedSA* pPedSA = dynamic_cast<CPedSA*>(pPed);
328334
if (!pPedSA)
329-
return NULL;
335+
return nullptr;
336+
337+
CTaskSAInterface* pTaskInterface = GetInterface();
338+
if (!pTaskInterface)
339+
return nullptr;
340+
341+
DWORD dwFunc = ((TaskComplexVTBL*)pTaskInterface->VTBL)->CreateNextSubTask;
342+
if (!dwFunc || dwFunc == 0x82263A)
343+
return nullptr;
330344

331345
DWORD dwPedInterface = (DWORD)pPedSA->GetInterface();
332-
DWORD dwThisInterface = (DWORD)GetInterface();
333-
DWORD dwFunc = ((TaskComplexVTBL*)GetInterface()->VTBL)->CreateNextSubTask;
334346
DWORD dwReturn = 0;
335-
if (dwFunc != 0x82263A && dwFunc)
347+
_asm
336348
{
337-
_asm
338-
{
339-
mov ecx, dwThisInterface
340-
push dwPedInterface
341-
call dwFunc
342-
mov dwReturn, eax
343-
}
349+
mov ecx, pTaskInterface
350+
push dwPedInterface
351+
call dwFunc
352+
mov dwReturn, eax
344353
}
345354
return pGame->GetTaskManagementSystem()->GetTask((CTaskSAInterface*)dwReturn);
346355
}
@@ -349,21 +358,24 @@ CTask* CTaskComplexSA::CreateFirstSubTask(CPed* pPed)
349358
{
350359
CPedSA* pPedSA = dynamic_cast<CPedSA*>(pPed);
351360
if (!pPedSA)
352-
return NULL;
361+
return nullptr;
362+
363+
CTaskSAInterface* pTaskInterface = GetInterface();
364+
if (!pTaskInterface)
365+
return nullptr;
366+
367+
DWORD dwFunc = ((TaskComplexVTBL*)pTaskInterface->VTBL)->CreateFirstSubTask;
368+
if (!dwFunc || dwFunc == 0x82263A)
369+
return nullptr;
353370

354371
DWORD dwPedInterface = (DWORD)pPedSA->GetInterface();
355-
DWORD dwThisInterface = (DWORD)GetInterface();
356-
DWORD dwFunc = ((TaskComplexVTBL*)GetInterface()->VTBL)->CreateFirstSubTask;
357372
DWORD dwReturn = 0;
358-
if (dwFunc != 0x82263A && dwFunc)
373+
_asm
359374
{
360-
_asm
361-
{
362-
mov ecx, dwThisInterface
363-
push dwPedInterface
364-
call dwFunc
365-
mov dwReturn, eax
366-
}
375+
mov ecx, pTaskInterface
376+
push dwPedInterface
377+
call dwFunc
378+
mov dwReturn, eax
367379
}
368380
return pGame->GetTaskManagementSystem()->GetTask((CTaskSAInterface*)dwReturn);
369381
}
@@ -372,21 +384,24 @@ CTask* CTaskComplexSA::ControlSubTask(CPed* pPed)
372384
{
373385
CPedSA* pPedSA = dynamic_cast<CPedSA*>(pPed);
374386
if (!pPedSA)
375-
return NULL;
387+
return nullptr;
388+
389+
CTaskSAInterface* pTaskInterface = GetInterface();
390+
if (!pTaskInterface)
391+
return nullptr;
392+
393+
DWORD dwFunc = ((TaskComplexVTBL*)pTaskInterface->VTBL)->ControlSubTask;
394+
if (!dwFunc || dwFunc == 0x82263A)
395+
return nullptr;
376396

377397
DWORD dwPedInterface = (DWORD)pPedSA->GetInterface();
378-
DWORD dwThisInterface = (DWORD)GetInterface();
379-
DWORD dwFunc = ((TaskComplexVTBL*)GetInterface()->VTBL)->ControlSubTask;
380398
DWORD dwReturn = 0;
381-
if (dwFunc != 0x82263A && dwFunc)
399+
_asm
382400
{
383-
_asm
384-
{
385-
mov ecx, dwThisInterface
386-
push dwPedInterface
387-
call dwFunc
388-
mov dwReturn, eax
389-
}
401+
mov ecx, pTaskInterface
402+
push dwPedInterface
403+
call dwFunc
404+
mov dwReturn, eax
390405
}
391406
return pGame->GetTaskManagementSystem()->GetTask((CTaskSAInterface*)dwReturn);
392407
}

0 commit comments

Comments
 (0)