[GH-ISSUE #8233] [Bug] Byte-search coverage labels loaded overlays as not loaded #6503

Open
opened 2026-11-01 21:11:43 +00:00 by bsakaguchi · 1 comment
Owner

Originally created by @morluto on GitHub (Oct 30, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/8233

Originally assigned to: @kaoru0822-kitauji on GitHub.

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Native analysis or decompilation

Observed behavior

An unbounded Ghidra search_bytes reports a loaded overlay in searched.skipped_not_loaded, although inspect_native_load_image reports the same block as loaded: true, overlay: true. The search intentionally excludes overlays without explicit bounds, and the Ghidra guide documents that policy, but the field name attributes the wrong reason to this block and the advertised tool description does not mention the overlay exclusion or how to include it.

Reproduction

  1. In a new owned Ghidra project, import a self-built arm64 Mach-O and create an initialized overlay AUDIT_OVERLAY of sixteen 0x42 bytes at numeric address 0x1000002d8. Save the project. Select it through REA's existing Ghidra project settings and open the original Mach-O via stdio MCP.
  2. Call inspect_native_load_image and page mappings: the overlay row is loaded: true, overlay: true, source_file_index: null, file_offset: null.
  3. Call search_bytes({"pattern":"4242424242424242","limit":8}): it returns no matches, complete: true and lists the overlay in skipped_not_loaded. This is completion over its actual search scope, not evidence that the pattern is absent from all initialized program memory.
  4. Add explicit bounds start: "AUDIT_OVERLAY:0x1000002d8", end: "AUDIT_OVERLAY:0x1000002e7". The overlay is searched and matches have null file offsets. At limit 3, following the returned cursors produced all nine overlapping eight-byte matches across three pages.

read_bytes separately returned original bytes from the default address and 4242424242424242 from the overlay address. A read crossing the overlay end returned four bytes and complete: false; address_to_file_offset refused the overlay with zero authoritative file mappings. Source binary and the selected project's ten regular-file digests stayed unchanged during REA sessions. The target was not executed. NOT_ENOUGH_INFO: the standalone fixture and creation script are not attached.

Expected behavior

Expose skipped overlay coverage without describing loaded overlays as not loaded. Advertise the default search scope and explicit-address-space recovery near the tool contract. Preserve the distinction between page completion, examined coverage, omitted blocks and unknown provider/runtime state; do not silently include every address space without a scope decision.

Impact and scope

An agent reading the MCP schema/result may infer that a loaded overlay was excluded for the wrong reason or miss that it can search it with explicit bounds. The provider guide does document the current combined field, so this is a contract/coverage clarity issue, not an undocumented absence of a recovery path. One authored Ghidra overlay on macOS was tested; non-loaded non-overlay blocks, overlays with backing files, other providers, CLI and autonomous-agent decisions were not tested.

REA version

53a4ab78451a0654e9c3beb3d43a5e371a288fcc

Runtime and platform

Node 24.22.1, macOS 26.3 arm64, Ghidra 12.1.4.

Target and artifact context

Owned arm64 Mach-O, SHA-256 a6bd938bf4ae8031a33d270ca7698ee1ced5b78347a9c4fa3750b0e57f6b126c, plus an independently authored disposable project.

Interface

MCP

Earliest failure stage

Transport or result projection

Relevant output or evidence

The inspect_native_load_image mapping contains { "block": "AUDIT_OVERLAY", "loaded": true, "overlay": true, "file_offset": null }; unbounded search puts the same block under searched.skipped_not_loaded. The current Ghidra provider guide describes the combined omission and explicit-bound alternative.

Typed outcome or recovery expected

A structurally honest omitted-block reason, or a clearly specified combined category and recovery discoverable in the advertised contract. Any schema change needs client compatibility and coverage validation.

Analysis or suspected cause

Source-derived: the unbounded-search branch groups !block.isLoaded() and block.isOverlay() into the same notLoaded collection. This is intentional exclusion but conflates distinct facts in the structured name.

Additional context

Related #8232 addresses comparisons between project memory and original bytes. Last known good version: NOT_ENOUGH_INFO.

Originally created by @morluto on GitHub (Oct 30, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/8233 Originally assigned to: @kaoru0822-kitauji on GitHub. ### Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ### Area Native analysis or decompilation ### Observed behavior An unbounded Ghidra `search_bytes` reports a loaded overlay in `searched.skipped_not_loaded`, although `inspect_native_load_image` reports the same block as `loaded: true, overlay: true`. The search intentionally excludes overlays without explicit bounds, and the Ghidra guide documents that policy, but the field name attributes the wrong reason to this block and the advertised tool description does not mention the overlay exclusion or how to include it. ### Reproduction 1. In a new owned Ghidra project, import a self-built arm64 Mach-O and create an initialized overlay `AUDIT_OVERLAY` of sixteen `0x42` bytes at numeric address `0x1000002d8`. Save the project. Select it through REA's existing Ghidra project settings and open the original Mach-O via stdio MCP. 2. Call `inspect_native_load_image` and page `mappings`: the overlay row is `loaded: true`, `overlay: true`, `source_file_index: null`, `file_offset: null`. 3. Call `search_bytes({"pattern":"4242424242424242","limit":8})`: it returns no matches, `complete: true` and lists the overlay in `skipped_not_loaded`. This is completion over its actual search scope, not evidence that the pattern is absent from all initialized program memory. 4. Add explicit bounds `start: "AUDIT_OVERLAY:0x1000002d8"`, `end: "AUDIT_OVERLAY:0x1000002e7"`. The overlay is searched and matches have null file offsets. At limit 3, following the returned cursors produced all nine overlapping eight-byte matches across three pages. `read_bytes` separately returned original bytes from the default address and `4242424242424242` from the overlay address. A read crossing the overlay end returned four bytes and `complete: false`; `address_to_file_offset` refused the overlay with zero authoritative file mappings. Source binary and the selected project's ten regular-file digests stayed unchanged during REA sessions. The target was not executed. NOT_ENOUGH_INFO: the standalone fixture and creation script are not attached. ### Expected behavior Expose skipped overlay coverage without describing loaded overlays as not loaded. Advertise the default search scope and explicit-address-space recovery near the tool contract. Preserve the distinction between page completion, examined coverage, omitted blocks and unknown provider/runtime state; do not silently include every address space without a scope decision. ### Impact and scope An agent reading the MCP schema/result may infer that a loaded overlay was excluded for the wrong reason or miss that it can search it with explicit bounds. The provider guide does document the current combined field, so this is a contract/coverage clarity issue, not an undocumented absence of a recovery path. One authored Ghidra overlay on macOS was tested; non-loaded non-overlay blocks, overlays with backing files, other providers, CLI and autonomous-agent decisions were not tested. ### REA version `53a4ab78451a0654e9c3beb3d43a5e371a288fcc` ### Runtime and platform Node 24.22.1, macOS 26.3 arm64, Ghidra 12.1.4. ### Target and artifact context Owned arm64 Mach-O, SHA-256 `a6bd938bf4ae8031a33d270ca7698ee1ced5b78347a9c4fa3750b0e57f6b126c`, plus an independently authored disposable project. ### Interface MCP ### Earliest failure stage Transport or result projection ### Relevant output or evidence The `inspect_native_load_image` mapping contains `{ "block": "AUDIT_OVERLAY", "loaded": true, "overlay": true, "file_offset": null }`; unbounded search puts the same block under `searched.skipped_not_loaded`. The current [Ghidra provider guide](https://github.com/morluto/rea/blob/53a4ab78451a0654e9c3beb3d43a5e371a288fcc/docs/ghidra-provider.md#byte-search) describes the combined omission and explicit-bound alternative. ### Typed outcome or recovery expected A structurally honest omitted-block reason, or a clearly specified combined category and recovery discoverable in the advertised contract. Any schema change needs client compatibility and coverage validation. ### Analysis or suspected cause Source-derived: [the unbounded-search branch](https://github.com/morluto/rea/blob/53a4ab78451a0654e9c3beb3d43a5e371a288fcc/bridge/ghidra/ReaGhidraBridge.java#L834) groups `!block.isLoaded()` and `block.isOverlay()` into the same `notLoaded` collection. This is intentional exclusion but conflates distinct facts in the structured name. ### Additional context Related #8232 addresses comparisons between project memory and original bytes. Last known good version: NOT_ENOUGH_INFO.
Author
Owner

@morluto commented on GitHub (Oct 31, 2026):

Looping in @gensokyo-dev @kaoru0822-kitauji @N0zoM1z0 for visibility on the Ghidra, Kuna, and REA tool-design investigation.

<!-- gh-comment-id:6538804552 --> @morluto commented on GitHub (Oct 31, 2026): Looping in @gensokyo-dev @kaoru0822-kitauji @N0zoM1z0 for visibility on the Ghidra, Kuna, and REA tool-design investigation.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#6503
No description provided.