[GH-ISSUE #2980] [Bug] Real-Ghidra lanes fail: compare_functions of a Ghidra dossier with itself is unknown after #2450 #1045

Closed
opened 2026-10-15 18:30:38 +00:00 by bsakaguchi · 0 comments
Owner

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

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

On current main, npm run verify:ghidra:aarch64-jump-table (and any lane that runs the host-native native-value check) fails before reaching its own fixtures:

AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
+ 'unknown'
- 'unchanged'
    at verifyNativeValueAdapters (scripts/lib/native-value-e2e.mjs:238:12)

The check compares a Ghidra analyze_function result with itself through compare_functions. Two dimensions come back unknown:

[
  {"dimension":"comments","status":"unknown","limitations":["Left: comments: Provider did not declare coverage for this empty facet.","Right: comments: Provider did not declare coverage for this empty facet."]},
  {"dimension":"calls","status":"unknown","limitations":["Left: Provider did not report relationship coverage.","Right: Provider did not report relationship coverage."]}
]

Reproduction

  1. On current main (8fef2aa64), with Ghidra 12.1.4 and JDK 21, run npm run verify:ghidra:aarch64-jump-table (or npm run verify:ghidra).
  2. It fails at scripts/lib/native-value-e2e.mjs:238 on the host-native debug fixture.

To see the dimensions, temporarily add JSON.stringify(comparisonEvidence.normalized_result.dimensions.filter((d) => d.status !== "unchanged")) as the message of that assert.equal.

Expected behavior

Comparing a Ghidra function dossier with itself returns unchanged, and the real-Ghidra lanes pass. An empty facet that Ghidra actually observed should be declared available, as docs/mcp-contracts.md now describes, so observed absence stays comparable.

Impact and scope

Affects compare_functions for every Ghidra dossier whose function has no comments, plus the calls dimension for every Ghidra dossier; both now come back unknown. The real-Ghidra verification lanes stop at the native-value check, so they no longer reach their own fixtures. CI doesn't run real Ghidra, which is why this wasn't caught. No evidence is corrupted: the result is overly cautious, not wrong. Hopper was not checked.

REA version

main at 8fef2aa64

Runtime and platform

macOS 27 arm64 (Apple Silicon), Node 24.18.0, Ghidra 12.1.4, JDK 21 (Temurin). Not tried on Linux, but nothing in the cause is platform-specific.

Target and artifact context

Host-native debug fixture built by the verifier from tests/conformance/ghidra/inventory.c (arm64 Mach-O)

Interface

MCP

Earliest failure stage

Native analysis or reconstruction

Relevant output or evidence


Typed outcome or recovery expected

No response

Analysis or suspected cause

Source reading, not yet tested as a fix:

  • b17487f4 (#2450) made an empty facet without a coverage declaration compare as unknown, and documents that producers which observed an empty facet should declare facet_availability. The Ghidra bridge (ReaGhidraBridge.java analyzeFunction) declares no facet_availability at all, so a function with no comments is now unknown on comments.
  • The calls dimension also requires Evidence relationship coverage. Ghidra's analyze_function Evidence doesn't report it, so calls is unknown too.

A likely fix is for the Ghidra bridge to declare the facets it actually reads (comments, callers, callees, references and so on) as available, and to report relationship coverage for the dossier's call relationships, plus a regression test comparing a Ghidra dossier fixture with itself.

Additional context

Found while running the AArch64 lane for #487. In that PR I skipped this single assertion locally to reach the new fixtures.

Originally created by @RishTheFish21 on GitHub (Oct 13, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/2980 ### 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 On current `main`, `npm run verify:ghidra:aarch64-jump-table` (and any lane that runs the host-native native-value check) fails before reaching its own fixtures: ``` AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: + 'unknown' - 'unchanged' at verifyNativeValueAdapters (scripts/lib/native-value-e2e.mjs:238:12) ``` The check compares a Ghidra `analyze_function` result with itself through `compare_functions`. Two dimensions come back `unknown`: ```json [ {"dimension":"comments","status":"unknown","limitations":["Left: comments: Provider did not declare coverage for this empty facet.","Right: comments: Provider did not declare coverage for this empty facet."]}, {"dimension":"calls","status":"unknown","limitations":["Left: Provider did not report relationship coverage.","Right: Provider did not report relationship coverage."]} ] ``` ### Reproduction 1. On current `main` (`8fef2aa64`), with Ghidra 12.1.4 and JDK 21, run `npm run verify:ghidra:aarch64-jump-table` (or `npm run verify:ghidra`). 2. It fails at `scripts/lib/native-value-e2e.mjs:238` on the host-native debug fixture. To see the dimensions, temporarily add `JSON.stringify(comparisonEvidence.normalized_result.dimensions.filter((d) => d.status !== "unchanged"))` as the message of that `assert.equal`. ### Expected behavior Comparing a Ghidra function dossier with itself returns `unchanged`, and the real-Ghidra lanes pass. An empty facet that Ghidra actually observed should be declared available, as `docs/mcp-contracts.md` now describes, so observed absence stays comparable. ### Impact and scope Affects `compare_functions` for every Ghidra dossier whose function has no comments, plus the calls dimension for every Ghidra dossier; both now come back `unknown`. The real-Ghidra verification lanes stop at the native-value check, so they no longer reach their own fixtures. CI doesn't run real Ghidra, which is why this wasn't caught. No evidence is corrupted: the result is overly cautious, not wrong. Hopper was not checked. ### REA version main at 8fef2aa64 ### Runtime and platform macOS 27 arm64 (Apple Silicon), Node 24.18.0, Ghidra 12.1.4, JDK 21 (Temurin). Not tried on Linux, but nothing in the cause is platform-specific. ### Target and artifact context Host-native debug fixture built by the verifier from tests/conformance/ghidra/inventory.c (arm64 Mach-O) ### Interface MCP ### Earliest failure stage Native analysis or reconstruction ### Relevant output or evidence ```text ``` ### Typed outcome or recovery expected _No response_ ### Analysis or suspected cause Source reading, not yet tested as a fix: - `b17487f4` (#2450) made an empty facet without a coverage declaration compare as `unknown`, and documents that producers which observed an empty facet should declare `facet_availability`. The Ghidra bridge (`ReaGhidraBridge.java` `analyzeFunction`) declares no `facet_availability` at all, so a function with no comments is now `unknown` on `comments`. - The calls dimension also requires Evidence relationship coverage. Ghidra's `analyze_function` Evidence doesn't report it, so `calls` is `unknown` too. A likely fix is for the Ghidra bridge to declare the facets it actually reads (comments, callers, callees, references and so on) as available, and to report relationship coverage for the dossier's call relationships, plus a regression test comparing a Ghidra dossier fixture with itself. ### Additional context Found while running the AArch64 lane for #487. In that PR I skipped this single assertion locally to reach the new fixtures.
bsakaguchi 2026-10-15 18:30:38 +00:00
  • closed this issue
  • added the
    triage
    bug
    labels
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#1045
No description provided.