[GH-ISSUE #8607] [Bug] Byte search labels loaded overlays as not loaded #7495

Open
opened 2026-11-03 00:30:11 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @morluto on GitHub (Nov 1, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/8607

Before submitting

  • I searched open and closed issues for a related report.
  • I removed credentials and sensitive target data.

Area

Native analysis or decompilation

Observed behavior

Real REA/Ghidra search_bytes places a loaded, initialized Ghidra overlay in searched.skipped_not_loaded when no bounds are supplied. On the fixture below, an unbounded search returned no matches and complete: true, while the skipped row was segment_0:0x401000..segment_0:0x40100f. inspect_native_load_image separately reported that same block as loaded: true, initialized: true, overlay: true. An explicitly bounded overlay search found the pattern.

Reproduction

  1. Generate the overlapping-segment ELF ab.elf from the Python reproduction in Noelo-Lab/kuna#1426; do not execute it.
  2. Open it with REA/Ghidra and call inspect_native_load_image with detail: complete. The default block maps offset 0x2000, and loaded overlay segment_0 maps offset 0x1000 at the same numeric address.
  3. Call search_bytes with pattern: "11 22 33 44". It returns matches: [], complete: true and lists segment_0 in skipped_not_loaded.
  4. Call search_bytes with the same pattern, start: "segment_0:0x401000", end: "segment_0:0x40100f". It finds segment_0:0x401000, file offset 4096.

Both compact and full stdio MCP profiles produced these outcomes and validated successful search responses against the advertised schema. After saving a snapshot and reopening it in a fresh session, the bounded overlay result and Evidence ID were identical. Target SHA-256 a9b709dc5c0c5fe54ae489ea619f2ba2b3d2f48259a781e536c5925068b544f6 stayed unchanged.

Expected behavior

Preserve why each region was excluded from this search. A loaded overlay should not be reported as not loaded. Make the tool's agent-facing description state that default unbounded searches skip overlays and that bounds selecting their address space can search them. complete should remain clearly scoped to the eligible search and page, not interpreted as evidence that excluded blocks contain no match.

Impact and scope

An agent may mistake a deliberately excluded loaded overlay for unloaded data, or a complete empty page for a search of all initialized analyzed memory. The result does identify the skipped range and the provider guide documents this behavior; no autonomous-agent outcome or prevalence is claimed. One generated ELF, host and Ghidra version were exercised.

REA version

b1f382ce16d4bfc13536fa05964275be8cbc2647 based on d3ab0faf5; branch changes affect function matching, not byte search.

Runtime and platform

Node 24.22.1, macOS arm64, Ghidra 12.1.4 and JDK 21.

Target and artifact context

Source-generated static ELF64 x86-64 with two overlapping file-backed load segments; no target execution or mutation.

Interface

MCP

Earliest failure stage

Native analysis or reconstruction

Relevant output or evidence

inspect_native_load_image: segment_0, loaded: true, overlay: true, file offset 4096. Default search: matches: [], searched.skipped_not_loaded: [{segment: "segment_0", start: "segment_0:0x401000", end: "segment_0:0x40100f", bytes: 16}]. Explicit overlay search: one match at segment_0:0x401000, file offset 4096. Source inspection shows the bridge adds a block to notLoaded when !block.isLoaded() || block.isOverlay(); the shared result schema calls the combined list skipped_not_loaded.

Typed outcome or recovery expected

Report skipped non-loaded blocks separately from loaded overlays, or use another explicit representation that faithfully conveys each reason and supports a bounded overlay follow-up. Account for output-schema and snapshot compatibility, selected-address semantics, blocks satisfying both conditions, and provider-specific coverage. Include a real public MCP control, offline/snapshot handoff, and malformed/overlap regressions as appropriate.

Analysis or suspected cause

The source producer groups two distinct exclusion conditions into one array before the shared contract projects it. docs/ghidra-provider.md explains the grouping, but the array name and advertised tool description do not preserve it for agent consumers.

Additional context

Related: #8170. Do not infer that the synthetic overlapping ELF is representative of ordinary binaries or that Ghidra's mapping matches a runtime loader.

cc @gensokyo-dev @kaoru0822-kitauji @N0zoM1z0

Originally created by @morluto on GitHub (Nov 1, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/8607 ### Before submitting - [x] I searched open and closed issues for a related report. - [x] I removed credentials and sensitive target data. ### Area Native analysis or decompilation ### Observed behavior Real REA/Ghidra `search_bytes` places a loaded, initialized Ghidra overlay in `searched.skipped_not_loaded` when no bounds are supplied. On the fixture below, an unbounded search returned no matches and `complete: true`, while the skipped row was `segment_0:0x401000..segment_0:0x40100f`. `inspect_native_load_image` separately reported that same block as `loaded: true`, `initialized: true`, `overlay: true`. An explicitly bounded overlay search found the pattern. ### Reproduction 1. Generate the overlapping-segment ELF `ab.elf` from the Python reproduction in [Noelo-Lab/kuna#1426](https://github.com/Noelo-Lab/kuna/issues/1426); do not execute it. 2. Open it with REA/Ghidra and call `inspect_native_load_image` with `detail: complete`. The default block maps offset `0x2000`, and loaded overlay `segment_0` maps offset `0x1000` at the same numeric address. 3. Call `search_bytes` with `pattern: "11 22 33 44"`. It returns `matches: []`, `complete: true` and lists `segment_0` in `skipped_not_loaded`. 4. Call `search_bytes` with the same pattern, `start: "segment_0:0x401000"`, `end: "segment_0:0x40100f"`. It finds `segment_0:0x401000`, file offset `4096`. Both compact and full stdio MCP profiles produced these outcomes and validated successful search responses against the advertised schema. After saving a snapshot and reopening it in a fresh session, the bounded overlay result and Evidence ID were identical. Target SHA-256 `a9b709dc5c0c5fe54ae489ea619f2ba2b3d2f48259a781e536c5925068b544f6` stayed unchanged. ### Expected behavior Preserve why each region was excluded from this search. A loaded overlay should not be reported as not loaded. Make the tool's agent-facing description state that default unbounded searches skip overlays and that bounds selecting their address space can search them. `complete` should remain clearly scoped to the eligible search and page, not interpreted as evidence that excluded blocks contain no match. ### Impact and scope An agent may mistake a deliberately excluded loaded overlay for unloaded data, or a complete empty page for a search of all initialized analyzed memory. The result does identify the skipped range and the provider guide documents this behavior; no autonomous-agent outcome or prevalence is claimed. One generated ELF, host and Ghidra version were exercised. ### REA version `b1f382ce16d4bfc13536fa05964275be8cbc2647` based on `d3ab0faf5`; branch changes affect function matching, not byte search. ### Runtime and platform Node 24.22.1, macOS arm64, Ghidra 12.1.4 and JDK 21. ### Target and artifact context Source-generated static ELF64 x86-64 with two overlapping file-backed load segments; no target execution or mutation. ### Interface MCP ### Earliest failure stage Native analysis or reconstruction ### Relevant output or evidence `inspect_native_load_image`: `segment_0`, `loaded: true`, `overlay: true`, file offset 4096. Default search: `matches: []`, `searched.skipped_not_loaded: [{segment: "segment_0", start: "segment_0:0x401000", end: "segment_0:0x40100f", bytes: 16}]`. Explicit overlay search: one match at `segment_0:0x401000`, file offset 4096. Source inspection shows the bridge adds a block to `notLoaded` when `!block.isLoaded() || block.isOverlay()`; the shared result schema calls the combined list `skipped_not_loaded`. ### Typed outcome or recovery expected Report skipped non-loaded blocks separately from loaded overlays, or use another explicit representation that faithfully conveys each reason and supports a bounded overlay follow-up. Account for output-schema and snapshot compatibility, selected-address semantics, blocks satisfying both conditions, and provider-specific coverage. Include a real public MCP control, offline/snapshot handoff, and malformed/overlap regressions as appropriate. ### Analysis or suspected cause The source producer groups two distinct exclusion conditions into one array before the shared contract projects it. `docs/ghidra-provider.md` explains the grouping, but the array name and advertised tool description do not preserve it for agent consumers. ### Additional context Related: #8170. Do not infer that the synthetic overlapping ELF is representative of ordinary binaries or that Ghidra's mapping matches a runtime loader. cc @gensokyo-dev @kaoru0822-kitauji @N0zoM1z0
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#7495
No description provided.