[GH-ISSUE #2322] [Bug] build_call_path can no longer establish not_found from headless IDA Evidence after #1544 #767

Closed
opened 2026-10-15 18:28:10 +00:00 by bsakaguchi · 1 comment
Owner

Originally created by @nikolay-dementiev on GitHub (Oct 12, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/2322

Before submitting

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

Area

Native analysis or decompilation

Observed behavior

Since #1544, analyze_function Evidence from the headless IDA profile always carries relationship_coverage: {"status": "unknown", "reason": "Upstream xrefs do not establish direct caller relationships."}. build_call_path therefore treats every expanded function as incompletely covered and can no longer establish not_found from IDA Evidence, which #2001 had restored.

Reproduction

macOS arm64, IDA Professional 9.1 (9.1.250226) headless, ida-pro-mcp c133c38. A small arm64 C program: main calls use_wrapper, puts and printf; use_wrapper calls sum_point.

  1. analyze_function for _main, _use_wrapper and _sum_point.
  2. build_call_path with those three Evidence records, from _main to _sum_point, and from _sum_point to _main.
main at 11fe5a13f main at a97b713f7 (after #1544)
analyze_function relationship_coverage.status complete unknown
build_call_path _main -> _sum_point found, 2 hops, exhaustive: false found, 2 hops, exhaustive: false (unchanged; the search reaches the _puts and _printf stubs, for which no Evidence was supplied)
build_call_path _sum_point -> _main not_found, exhaustive: true unknown, exhaustive: false

procedure_callees, get_call_graph and trace_call_path on the same target still report complete coverage and an untruncated trace.

Expected behavior

A forward build_call_path over IDA Evidence whose callee sets are complete establishes not_found with exhaustive: true, as it did before #1544. The modern profile's unavailable direct callers stay visible as unknown without making the callee closure incomplete.

Impact and scope

Every build_call_path over analyze_function Evidence from the modern headless IDA profile. main only; not in a release.

REA version

main at a97b713f7.

Runtime and platform

macOS 26.5.2 (arm64), Node 26.3.0; IDA Professional 9.1 (9.1.250226) with idalib; ida-pro-mcp 2.0.0 at c133c3853.

Target and artifact context

A small arm64 C program built with clang -O0 -arch arm64. No private target data.

Interface

MCP

Earliest failure stage

Native analysis or reconstruction

Analysis or suspected cause

IdaOperationRunner now builds the analyze_function coverage with combinedRelationshipCoverage(callers, callees) (src/ida/IdaOperationRunner.ts), which returns unknown when either side is unknown. In the modern profile the callers side is always unknown ("Upstream xrefs do not establish direct caller relationships."), so the combined value is always unknown. Before #1544 the dossier's coverage came from the callee read alone, with unavailable callers recorded as a limitation. build_call_path (src/domain/callPath.ts, from #2001) reads that single Evidence-level coverage to decide whether a forward expansion is complete, so the always-unknown callers make every forward search non-exhaustive.

Originally created by @nikolay-dementiev on GitHub (Oct 12, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/2322 ### Before submitting - [x] I searched the open and closed issues and pull requests for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ### Area Native analysis or decompilation ### Observed behavior Since #1544, `analyze_function` Evidence from the headless IDA profile always carries `relationship_coverage: {"status": "unknown", "reason": "Upstream xrefs do not establish direct caller relationships."}`. `build_call_path` therefore treats every expanded function as incompletely covered and can no longer establish `not_found` from IDA Evidence, which #2001 had restored. ### Reproduction macOS arm64, IDA Professional 9.1 (9.1.250226) headless, ida-pro-mcp c133c38. A small arm64 C program: `main` calls `use_wrapper`, `puts` and `printf`; `use_wrapper` calls `sum_point`. 1. `analyze_function` for `_main`, `_use_wrapper` and `_sum_point`. 2. `build_call_path` with those three Evidence records, from `_main` to `_sum_point`, and from `_sum_point` to `_main`. | | `main` at 11fe5a13f | `main` at a97b713f7 (after #1544) | | --- | --- | --- | | `analyze_function` `relationship_coverage.status` | `complete` | `unknown` | | `build_call_path` `_main` -> `_sum_point` | `found`, 2 hops, `exhaustive: false` | `found`, 2 hops, `exhaustive: false` (unchanged; the search reaches the `_puts` and `_printf` stubs, for which no Evidence was supplied) | | `build_call_path` `_sum_point` -> `_main` | `not_found`, `exhaustive: true` | `unknown`, `exhaustive: false` | `procedure_callees`, `get_call_graph` and `trace_call_path` on the same target still report `complete` coverage and an untruncated trace. ### Expected behavior A forward `build_call_path` over IDA Evidence whose callee sets are complete establishes `not_found` with `exhaustive: true`, as it did before #1544. The modern profile's unavailable direct callers stay visible as unknown without making the callee closure incomplete. ### Impact and scope Every `build_call_path` over `analyze_function` Evidence from the modern headless IDA profile. `main` only; not in a release. ### REA version `main` at a97b713f7. ### Runtime and platform macOS 26.5.2 (arm64), Node 26.3.0; IDA Professional 9.1 (9.1.250226) with idalib; ida-pro-mcp 2.0.0 at c133c3853. ### Target and artifact context A small arm64 C program built with `clang -O0 -arch arm64`. No private target data. ### Interface MCP ### Earliest failure stage Native analysis or reconstruction ### Analysis or suspected cause `IdaOperationRunner` now builds the `analyze_function` coverage with `combinedRelationshipCoverage(callers, callees)` (`src/ida/IdaOperationRunner.ts`), which returns `unknown` when either side is unknown. In the modern profile the callers side is always unknown ("Upstream xrefs do not establish direct caller relationships."), so the combined value is always `unknown`. Before #1544 the dossier's coverage came from the callee read alone, with unavailable callers recorded as a limitation. `build_call_path` (`src/domain/callPath.ts`, from #2001) reads that single Evidence-level coverage to decide whether a forward expansion is complete, so the always-unknown callers make every forward search non-exhaustive.
bsakaguchi 2026-10-15 18:28:10 +00:00
Author
Owner

@matbrgz commented on GitHub (Oct 12, 2026):

Triage & Implementation Review

The regression where build_call_path cannot establish not_found occurred because relationship coverage marking callers as unknown was incorrectly applied to forward call traversal (callees). Forward traversal from an origin function only depends on complete callee coverage.

  • Invariant: When tracing call paths forward (from caller down to callee), caller-only relationship uncertainty must not disqualify complete callee coverage from proving absence of a path (not_found).
  • Tracking: Implemented in PR #2371 (fix(call-path): keep caller-only unknown coverage from blocking not_found).
<!-- gh-comment-id:6134265880 --> @matbrgz commented on GitHub (Oct 12, 2026): ### Triage & Implementation Review The regression where `build_call_path` cannot establish `not_found` occurred because relationship coverage marking callers as `unknown` was incorrectly applied to forward call traversal (callees). Forward traversal from an origin function only depends on complete callee coverage. - **Invariant:** When tracing call paths forward (from caller down to callee), caller-only relationship uncertainty must not disqualify complete callee coverage from proving absence of a path (`not_found`). - **Tracking:** Implemented in PR #2371 (`fix(call-path): keep caller-only unknown coverage from blocking not_found`).
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#767
No description provided.