Skip to content

Commit 96dec18

Browse files
committed
Merge Validate SweepAim clip dictionary index (pr-3717)
5a68762 - fix(gta-core-five): validate SweepAim clip dictionary index
2 parents d4a1209 + 5a68762 commit 96dec18

File tree

1 file changed

+40
-0
lines changed

1 file changed

+40
-0
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#include "StdInc.h"
2+
3+
#include "Hooking.FlexStruct.h"
4+
#include "Hooking.Patterns.h"
5+
#include "Hooking.Stubs.h"
6+
7+
static hook::cdecl_stub<bool(int)> fwAnimManager_IsValidSlot([]()
8+
{
9+
return hook::get_call(hook::get_pattern("E8 ? ? ? ? 84 C0 74 ? 8B D3 48 8B CF E8 ? ? ? ? FF C3"));
10+
});
11+
12+
static int32_t clipDictIdOffset;
13+
14+
static int (*g_origTaskGeneralSweepOnUpdate)(hook::FlexStruct*);
15+
static int TaskGeneralSweepOnUpdate(hook::FlexStruct* task)
16+
{
17+
int clipDictId = task->Get<int>(clipDictIdOffset);
18+
19+
if (!fwAnimManager_IsValidSlot(clipDictId))
20+
{
21+
return 0x2; // FSM_QUIT
22+
}
23+
24+
return g_origTaskGeneralSweepOnUpdate(task);
25+
}
26+
27+
static HookFunction hookFunction([]()
28+
{
29+
// This hook prevents a client crash caused by invalid clip dictionary IDs in SweepAim tasks.
30+
// When a player triggers TaskSweepAimEntity using a clip dictionary that exists only on their
31+
// local client (e.g., a modded or unloaded anim dict), the task is replicated to remote clients.
32+
// During replication, the clipDictId may resolve to an invalid local index on other clients.
33+
// Later, the CTaskGeneralSweep task uses this invalid clipDictId inside fwAnimManager, which
34+
// eventually reaches fwClipDictionaryStore::GetNumRefs and tries to access:
35+
// m_aStorage[index * size]
36+
// If 'index' is invalid, this causes an out-of-range pointer dereference, leading to a client
37+
// crash.
38+
g_origTaskGeneralSweepOnUpdate = hook::trampoline(hook::get_pattern("EB ? 8B 93 ? ? ? ? 48 81 C1", -0x2F), TaskGeneralSweepOnUpdate);
39+
clipDictIdOffset = *hook::get_pattern<int32_t>("8B 93 ? ? ? ? 48 81 C1 ? ? ? ? E8 ? ? ? ? 84 C0", 0x2);
40+
});

0 commit comments

Comments
 (0)