Skip to content

fix(mcp): skip unreadable regions before splitting scans - #128

Merged
JeanExtreme002 merged 1 commit into
JeanExtreme002:mainfrom
StupidDev1337:fix/skip-unreadable-regions-before-splitting
Nov 13, 2026
Merged

JeanExtreme002 merged 1 commit into
JeanExtreme002:mainfrom
StupidDev1337:fix/skip-unreadable-regions-before-splitting

Conversation

@StupidDev1337

Copy link
Copy Markdown
Contributor

Why is this PR necessary, what does it do?

Fixes #127. On 64-bit Windows targets, scan_value and scan_pattern ran out of the 30 s budget before they reached the heap.

  • The Windows region walk reports the whole address space, MEM_FREE and MEM_RESERVE ranges included.
  • _run_batched_scan cut all of that into scan_batch_bytes pieces. At the 64 MiB default that is about 2 million batches for ~128 TiB.

This PR leaves unreadable regions out before split_regions / batch_regions:

  • _run_batched_scan filters the snapshot to readable regions first. Unreadable regions can never hold a match, and every backend's scan already drops them through default_scan_filter, so the results do not change.
  • find_pointer_paths applies the same filter before cutting regions for the pointer map. scan_pointer_paths already keeps only readable regions itself, so the map does not change. It just no longer builds millions of pieces first.

list_memory_regions and the session's region snapshot are untouched.

How it was tested

  • Two regression tests in tests/mcp_server/test_toolset.py (TestHugeRegionsAreScannedInPieces) use a fake target with a 1 MiB unreadable region below its two readable ones.
    • Without the fix, both fail: the unreadable region turns into extra batches or pointer-map pieces.
    • With the fix, both pass.
  • flake8 PyMemoryEditor tests and mypy PyMemoryEditor report no issues.
  • Full suite (pytest tests) on Windows 11 x64, Python 3.13.14, with the speed extra: 1832 passed, 28 skipped, 1 failed.
    • The failure is tests/process/test_foreign_process.py, and it fails the same way on unmodified main.
    • Cause: inside a Windows venv, sys.executable is the venv launcher, which starts the real interpreter as a child, so the test opens the launcher's pid (WinError 299).
    • It passes when run with the base interpreter.
  • Live check with the reproducer from MCP scan_value on 64-bit Windows targets hits the 30 s budget before reaching the heap: free/reserved address space is split into millions of pieces #127 against this branch, without --scan-batch-bytes:
    • this branch: scan_value returns the counter with count: 1, partial: false, elapsed_seconds: 0.002;
    • 3.4.1: count: 0, partial: true, elapsed_seconds: 30.122.

Checklist (complete all items):

  • Added tests as necessary.
  • There is no breaking change for existing features.

References:

Fixes #127

Notes:

  • The change only filters on MemoryRegion.is_readable, so it is platform-independent. I could only run it on Windows; CI will cover Linux and macOS.
  • Written with help from Claude (an AI assistant). I reviewed the change and ran the checks above locally.

🤖 Generated with Claude Code

On Windows the region snapshot spans the whole address space, MEM_FREE
and MEM_RESERVE ranges included (~128 TiB on a 64-bit target).
_run_batched_scan cut all of it into scan_batch_bytes pieces, about two
million batches at the 64 MiB default, so scan_value and scan_pattern
spent their whole budget before reaching the heap.

Leave unreadable regions out before split_regions/batch_regions in
_run_batched_scan and find_pointer_paths. Every backend's scan already
drops them through default_scan_filter, and scan_pointer_paths keeps
only readable regions, so results do not change.

Fixes JeanExtreme002#127

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added lib Library changes (PyMemoryEditor/) tests Test changes (tests/) mcp MCP changes (PyMemoryEditor/mcp) labels Nov 5, 2026
@JeanExtreme002
JeanExtreme002 requested a balanced review from Copilot November 13, 2026 01:07

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues are recorded for the change filtering unreadable memory regions before scan batching and pointer-map splitting.

No open issues 🎉

What changed in this PR

Fixes #127 by filtering unreadable memory regions before MCP scans split and batch them, preventing Windows free and reserved address space from consuming the scan budget before reaching readable memory.

Changes:

  • Filters unreadable regions before value/pattern scan batching and pointer-map splitting.
  • Adds regression tests confirming unreadable regions produce no scan batches or pointer-map pieces.
  • Leaves memory-region listings and session snapshots unchanged.
File Description
tests/​mcp_server/​test_toolset.py Adds regression coverage for large unreadable regions in scans and pointer maps.
PyMemoryEditor/​mcp/​toolset.py Filters unreadable regions before splitting and batching scan work.

Review effort: Balanced

@codecov

codecov Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.02%. Comparing base (88ee929) to head (acded00).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #128      +/-   ##
==========================================
- Coverage   93.04%   93.02%   -0.02%     
==========================================
  Files          43       43              
  Lines        4671     4672       +1     
==========================================
  Hits         4346     4346              
- Misses        325      326       +1     
Flag Coverage Δ
Linux-py3.10 68.21% <ø> (+0.03%) ⬆️
Linux-py3.11 68.17% <ø> (-0.04%) ⬇️
Linux-py3.12 68.17% <ø> (-0.04%) ⬇️
Linux-py3.13 68.17% <ø> (ø)
Linux-py3.14 68.08% <ø> (ø)
Linux-py3.15 68.08% <ø> (ø)
Windows-py3.10 69.83% <ø> (ø)
Windows-py3.11 69.83% <ø> (ø)
Windows-py3.12 69.83% <ø> (ø)
Windows-py3.13 69.83% <ø> (ø)
Windows-py3.14 69.74% <ø> (ø)
Windows-py3.15 69.74% <ø> (ø)
macOS-py3.10 91.47% <ø> (-0.05%) ⬇️
macOS-py3.12 91.47% <ø> (ø)
macOS-py3.14 91.44% <ø> (ø)
mcp-Linux-py3.12 92.16% <100.00%> (+<0.01%) ⬆️
mcp-Windows-py3.12 91.73% <100.00%> (+<0.01%) ⬆️
mcp-macOS-py3.12 93.14% <100.00%> (+<0.01%) ⬆️
speed-Linux-py3.12 70.27% <ø> (+0.03%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
PyMemoryEditor/mcp/toolset.py 94.88% <100.00%> (+<0.01%) ⬆️

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@JeanExtreme002

Copy link
Copy Markdown
Owner

Hi, @StupidDev1337. Thanks a lot for the contribution, and for the detailed write-up and the reproducer in #127! I went through the change and it looks good to me: the library already drops unreadable regions on every backend, so filtering them before splitting doesn't change any results, and it fixes the timeout on 64-bit Windows targets.

CI is green on Windows, Linux and macOS as well. I'm going to merge it. ❤️

@JeanExtreme002
JeanExtreme002 merged commit 16f0237 into JeanExtreme002:main Nov 13, 2026
29 checks passed
JeanExtreme002 added a commit that referenced this pull request Nov 13, 2026
Patch release carrying #128: the MCP server's scan_value, scan_pattern and
find_pointer_paths now leave unreadable regions out before cutting the
region snapshot into pieces. On a 64-bit Windows target the snapshot spans
the whole address space, so 3.4.1 spent its whole scan budget on about two
million empty batches and returned nothing (#127).

Co-authored-by: Claude Fable 5.2 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lib Library changes (PyMemoryEditor/) mcp MCP changes (PyMemoryEditor/mcp) tests Test changes (tests/)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MCP scan_value on 64-bit Windows targets hits the 30 s budget before reaching the heap: free/reserved address space is split into millions of pieces

3 participants