Skip to content

fix(patternfinder): don't follow a JMP thunk out of the game module - #17

Merged
TrackAndTruckDevs merged 1 commit into
TrackAndTruckDevs:mainfrom
aefly:fix/pattern-finder-foreign-jmp
Oct 5, 2026
Merged

TrackAndTruckDevs merged 1 commit into
TrackAndTruckDevs:mainfrom
aefly:fix/pattern-finder-foreign-jmp

Conversation

@aefly

@aefly aefly commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes FileSystemDataFinder failing with PatternFinder: Find(block): memory access exception (code 0xC0000005) for users who run a third-party tool that inline-hooks a game function.

Root cause

PatternFinder::Find(block) starts its scan at a function address. If the first byte is 0xE9 (a JMP rel32), it assumes a compiler thunk and follows the jump before scanning.

A third-party inline hook (MinHook, as used by TruckersMP and others) overwrites a function's entry with exactly such a JMP, pointing into its own trampoline allocation. Find(block) followed it and scanned 512 bytes of that foreign allocation instead of the game function. The trampoline sits near the end of a small committed page, so the scan read past the page boundary and raised 0xC0000005.

The SEH guard catches the exception, so it is logged rather than crashing, but every dependent step is lost:

[FileSystemDataFinder] 1. UFS_RegisterMount → 0x...159A60 ("eurotrucks2.exe"+159A60)
[PatternFinder] Find: Following JMP thunk from 0x...159A60 to 0x...
[PatternFinder] Find(block): memory access exception (code 0xC0000005)
[FileSystemDataFinder] 2. [NODE] Node structure → INVALID [x]
[FileSystemDataFinder] 3. [STR] StringBuffer → INVALID [x]
[FileSystemDataFinder] 4. [CNT] Mount list head → INVALID [x]
[FileSystemDataFinder] 5. [PATH] Physical path → INVALID [x]
[FileSystemDataFinder] ── Finished FileSystemDataFinder search: [x]FAILED (13/17) ──

Fix

Only follow the JMP thunk when its target stays inside the main module. A real thunk resolves within the .exe; a third-party hook jumps out to its own allocation. When the target is outside the module, scan the original function instead. The signatures sit past the few bytes the hook overwrites at the entry, so they still resolve.

Changes in src/Utils/PatternFinder.cpp:

  • Added IsAddressInMainModule(), which tests an address against the main module's mapped section range (cached).
  • Find(block) follows the thunk only when the target is in-module; otherwise it scans the original bytes.

Testing

Reproduced the exact failure in-game by simulating an inline hook on UFS_RegisterMount (a JMP into a trampoline at the end of a single committed page), without TruckersMP. Verified both before and after the fix on an MSVC build (before: exception caught and logged, as users see it).

With the fix, the same simulated hook no longer traps SPF:

[FileSystemDataFinder] 1. UFS_RegisterMount → 0x...159A60 ("eurotrucks2.exe"+159A60)
[PatternFinder] Find: NOT following JMP thunk from 0x...159A60 to 0x... (outside module, likely hook); scanning original bytes
[FileSystemDataFinder] 2. [NODE] Device offset → 0x10
[FileSystemDataFinder] 3. [NODE] VirtualPath → 0x18
...
[FileSystemDataFinder] ── Finished FileSystemDataFinder search: [✓]READY (21/21) ──

No memory access exception, and FileSystemDataFinder resolves fully.

@TrackAndTruckDevs
TrackAndTruckDevs merged commit 2739451 into TrackAndTruckDevs:main Oct 5, 2026
1 check passed
@TrackAndTruckDevs

Copy link
Copy Markdown
Owner

merging :)

@aefly
aefly deleted the fix/pattern-finder-foreign-jmp branch October 5, 2026 20:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants