Skip to content

fix(gta-core-five): validate pool entry in target scoring function#3816

Open
st860923 wants to merge 1 commit intocitizenfx:masterfrom
st860923:fix/null-pool-entry-deref-crash
Open

fix(gta-core-five): validate pool entry in target scoring function#3816
st860923 wants to merge 1 commit intocitizenfx:masterfrom
st860923:fix/null-pool-entry-deref-crash

Conversation

@st860923
Copy link

@st860923 st860923 commented Feb 7, 2026

Goal of this PR

Prevent a client crash caused by a null pointer dereference in a scoring function that evaluates entities as potential targets. The function takes two entity pointers, switches on the entity type byte at +0x28 (handling types 3, 4, and 5), and accumulates a float score in XMM9 by multiplying various weight factors based on distance, flags, and task state. Its caller iterates up to 32 entities, collects scores, and performs a weighted random selection to pick a target.

In the type-4 branch, the function searches a linked list for a node matching a specific type, then uses the returned index to look up an entry from a pool. The pool lookup can return NULL when the slot has been freed (stale index), but the code dereferences the result at offset +0xDC without a null check, causing the crash.

How is this PR achieving the goal

Replaces the CALL to the pool lookup function at the specific crash site with a safe wrapper. When the pool lookup returns NULL, the wrapper returns a pointer to a static zeroed buffer instead, allowing the subsequent read at +0xDC to safely return 0. This causes the code to fall through the switch-case harmlessly and exit normally. Only the single call site inside the scoring function is patched — the pool lookup has 70 other callers which remain unaffected.

This PR applies to the following area(s)

FiveM

Successfully tested on

Game builds: 3258
Platforms: Windows

Checklist

  • Code compiles and has been tested successfully.
  • Code explains itself well and/or is documented.
  • My commit message explains what the changes do and what they are for.
  • No extra compilation warnings are added by these changes.

Fixes issues

@github-actions github-actions bot added the invalid Requires changes before it's considered valid and can be (re)triaged label Feb 7, 2026
@Ehbw
Copy link
Contributor

Ehbw commented Feb 7, 2026

I have a few questions with this PR and the supposed fix

  1. What crash does this PR claim to fix, I haven't seen any crashdumps related to this and you don't appear to have made mention to it in the PR or commit description.

  2. The patch can be done in a much better way then allocating a block of memory, you can patch the area after the call to sub_140C63EC8 (3258) (which will safely return NULL if an invalid index is passed to it) to check that rax is not null, if it is then jump out of the current execution to 0F 5C 8F ? ? ? ? 0F 59 4F - 7 which is where the code would jump to anyway saving patching that single call + allocating a block of memory.

@st860923
Copy link
Author

st860923 commented Feb 7, 2026

I have a few questions with this PR and the supposed fix

  1. What crash does this PR claim to fix, I haven't seen any crashdumps related to this and you don't appear to have made mention to it in the PR or commit description.
  2. The patch can be done in a much better way then allocating a block of memory, you can patch the area after the call to sub_140C63EC8 (3258) (which will safely return NULL if an invalid index is passed to it) to check that rax is not null, if it is then jump out of the current execution to 0F 5C 8F ? ? ? ? 0F 59 4F - 8 which is where the code would jump to anyway saving patching that single call + allocating a block of memory.

Thanks for the review.

  1. This fixes the crash at GTA5_b3258.exe!sub_140AF0A90 (0x70f). I encountered this on my server but unfortunately no longer have the crash dump on hand.
  2. Sure. I'm planning use jitasm to inject TEST RAX, RAX; JZ exit_path after the call, with nop+jump on the 8 bytes following the call, reproducing those two instructions in the stub on the non-null path.
    Is this what you had in mind?

Also for the exit path, the MOVAPS before the SUBPS is 7 bytes (0F 28 8B ? ? ? ?), so wouldn't the exit label be at pattern match - 7 instead of - 8? Just want to make sure.

@Ehbw
Copy link
Contributor

Ehbw commented Feb 7, 2026

  1. Sure. I'm planning use jitasm to inject TEST RAX, RAX; JZ exit_path after the call, with nop+jump on the 8 bytes following the call, reproducing those two instructions in the stub on the non-null path.
    Is this what you had in mind?

Yes

Also for the exit path, the MOVAPS before the SUBPS is 7 bytes (0F 28 8B ? ? ? ?), so wouldn't the exit label be at pattern match - 7 instead of - 8? Just want to make sure.

Yeah I miscounted the total number of instructions, 7 is correct (ends up at the start of the movaps instruction, otherwise you can always generate/craft a pattern for that movaps instruction).

@st860923 st860923 force-pushed the fix/null-pool-entry-deref-crash branch 2 times, most recently from 5b3c6dd to 0bcdf60 Compare February 12, 2026 09:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

invalid Requires changes before it's considered valid and can be (re)triaged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants