[GH-ISSUE #5220] [Bug] Ghidra OOME classification borrows cause details from unrelated output lines #3198

Closed
opened 2026-10-31 00:37:44 +00:00 by bsakaguchi · 2 comments
Owner

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

Before submitting

  • I searched open and closed issues for a related report; #4682 covers retention, not unrelated cause text.
  • The reduced evidence contains no credentials or private target data.

Area

Native analysis or decompilation

Observed behavior

Controlled provider-projection regressions show that Ghidra OOME classification takes cause details from unrelated output lines. With INFO unrelated capacity: unable to create native thread followed by java.lang.OutOfMemoryError: Java heap space, REA returns a capacity constraint instead of memory. With unrelated Java heap space text followed by java.lang.OutOfMemoryError: Metaspace, it reports heap space and heap-specific advice.

Reproduction

Added two controlled cases to src/ghidra/GhidraProvider.behavior.test.ts, then ran:

npm run test:run -- --project adapters src/ghidra/GhidraProvider.behavior.test.ts -t 'binds Ghidra OOME detail'

Both cases fail before the detail-owner correction. These exercise the production provider/error projection with a recording Ghidra port; no real Ghidra JVM was run. The retention work in progress for #4682 does not change the failing whole-output classification.

Expected behavior

Bind resource kind, reported detail and remediation to the OOME reporting line. docs/binary-diagnostics.md#ghidra-process-failures distinguishes heap/GC, Metaspace, array size and native-thread evidence; unrelated logging cannot establish those causes.

Impact and scope

Observed wrong resource kind and wrong recovery advice in 2/2 controlled inputs. Real Ghidra frequency and platform-specific occurrence: NOT_ENOUGH_INFO; not measured. Related to the ownership review of #4682/#4774.

REA version

Main base 048d70755ea9ca1d0d159ac78285d62a7ae00b21, 6.7.0; controlled tests also reproduce against its unchanged whole-output classifier while the separate retention fix is in progress.

Runtime and platform

Node 24.18.0, macOS arm64. Ghidra port simulated; no real JVM compatibility claim.

Target and artifact context

Minimal ELF x86_64 provider test target; only operation diagnostics are varied.

Interface

Other: production provider/error projection

Earliest failure stage

Transport or result projection

Relevant output or evidence

  • Heap OOME + unrelated native-thread line: actual resource_constraint / resource: capacity.
  • Metaspace OOME + unrelated heap line: actual message says java.lang.OutOfMemoryError: Java heap space.

Source: src/ghidra/GhidraProviderClient.ts, projectObservedJvmMemoryFailure, on the pinned main revision. It detects the OOME class, then searches the entire combined operation output for cause phrases. This is source-derived ownership diagnosis supported by the executed controlled tests, not a real-Ghidra reproduction.

Typed outcome or recovery expected

Heap case: memory with configured-heap advice. Metaspace case: memory with Metaspace detail, no heap-specific advice.

Analysis or suspected cause

Normalize OOME reporting lines at the owning projection boundary and derive details only from those lines; retain full diagnostic provenance separately. The correction is being validated together with #4682.

Originally created by @morluto on GitHub (Oct 19, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/5220 ### Before submitting - [x] I searched open and closed issues for a related report; #4682 covers retention, not unrelated cause text. - [x] The reduced evidence contains no credentials or private target data. ### Area Native analysis or decompilation ### Observed behavior Controlled provider-projection regressions show that Ghidra OOME classification takes cause details from unrelated output lines. With `INFO unrelated capacity: unable to create native thread` followed by `java.lang.OutOfMemoryError: Java heap space`, REA returns a capacity constraint instead of memory. With unrelated `Java heap space` text followed by `java.lang.OutOfMemoryError: Metaspace`, it reports heap space and heap-specific advice. ### Reproduction Added two controlled cases to `src/ghidra/GhidraProvider.behavior.test.ts`, then ran: `npm run test:run -- --project adapters src/ghidra/GhidraProvider.behavior.test.ts -t 'binds Ghidra OOME detail'` Both cases fail before the detail-owner correction. These exercise the production provider/error projection with a recording Ghidra port; no real Ghidra JVM was run. The retention work in progress for #4682 does not change the failing whole-output classification. ### Expected behavior Bind resource kind, reported detail and remediation to the OOME reporting line. `docs/binary-diagnostics.md#ghidra-process-failures` distinguishes heap/GC, Metaspace, array size and native-thread evidence; unrelated logging cannot establish those causes. ### Impact and scope Observed wrong resource kind and wrong recovery advice in 2/2 controlled inputs. Real Ghidra frequency and platform-specific occurrence: NOT_ENOUGH_INFO; not measured. Related to the ownership review of #4682/#4774. ### REA version Main base `048d70755ea9ca1d0d159ac78285d62a7ae00b21`, 6.7.0; controlled tests also reproduce against its unchanged whole-output classifier while the separate retention fix is in progress. ### Runtime and platform Node 24.18.0, macOS arm64. Ghidra port simulated; no real JVM compatibility claim. ### Target and artifact context Minimal ELF x86_64 provider test target; only operation diagnostics are varied. ### Interface Other: production provider/error projection ### Earliest failure stage Transport or result projection ### Relevant output or evidence - Heap OOME + unrelated native-thread line: actual `resource_constraint` / `resource: capacity`. - Metaspace OOME + unrelated heap line: actual message says `java.lang.OutOfMemoryError: Java heap space`. Source: `src/ghidra/GhidraProviderClient.ts`, `projectObservedJvmMemoryFailure`, on the pinned main revision. It detects the OOME class, then searches the entire combined operation output for cause phrases. This is source-derived ownership diagnosis supported by the executed controlled tests, not a real-Ghidra reproduction. ### Typed outcome or recovery expected Heap case: memory with configured-heap advice. Metaspace case: memory with Metaspace detail, no heap-specific advice. ### Analysis or suspected cause Normalize OOME reporting lines at the owning projection boundary and derive details only from those lines; retain full diagnostic provenance separately. The correction is being validated together with #4682.
bsakaguchi 2026-10-31 00:37:44 +00:00
  • closed this issue
  • added the
    triage
    bug
    labels
Author
Owner

@prashantpiyush1111 commented on GitHub (Oct 19, 2026):

Hi, I'd like to take this one.

From reading projectObservedJvmMemoryFailure in src/ghidra/GhidraProviderClient.ts, the cause looks like this: after finding java.lang.OutOfMemoryError anywhere in the output, threadCapacity, heapExhaustion and detail are all matched against the whole output. An unrelated "unable to create native thread" or "Java heap space" line can therefore win.

My plan:

  • Take only the lines that contain java.lang.OutOfMemoryError and derive the subtype from those lines alone. This also covers the real detail-before-class format (... error: Java heap space (HeadlessAnalyzer) java.lang.OutOfMemoryError:).
  • Keep the bare-class behavior unchanged: unknown subtype, no heap advice.
  • Add the two cases from this issue as tests in GhidraProvider.behavior.test.ts, and sync the "Ghidra process failures" section in docs/binary-diagnostics.md.

Since this is being validated alongside #4682, is it fine for me to open a PR, or would you rather handle it with that work? I'll wait for your go-ahead before starting.

<!-- gh-comment-id:6263664855 --> @prashantpiyush1111 commented on GitHub (Oct 19, 2026): Hi, I'd like to take this one. From reading `projectObservedJvmMemoryFailure` in `src/ghidra/GhidraProviderClient.ts`, the cause looks like this: after finding `java.lang.OutOfMemoryError` anywhere in the output, `threadCapacity`, `heapExhaustion` and `detail` are all matched against the whole output. An unrelated "unable to create native thread" or "Java heap space" line can therefore win. My plan: - Take only the lines that contain `java.lang.OutOfMemoryError` and derive the subtype from those lines alone. This also covers the real detail-before-class format (`... error: Java heap space (HeadlessAnalyzer) java.lang.OutOfMemoryError:`). - Keep the bare-class behavior unchanged: unknown subtype, no heap advice. - Add the two cases from this issue as tests in `GhidraProvider.behavior.test.ts`, and sync the "Ghidra process failures" section in `docs/binary-diagnostics.md`. Since this is being validated alongside #4682, is it fine for me to open a PR, or would you rather handle it with that work? I'll wait for your go-ahead before starting.
Author
Owner

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

Fixed on main in 91884c3743 together with #4682.

The old classifier confirmed an OOME, then took its cause phrases from the entire operation output. The producer now supplies bounded confirmed OOME observations, and the projection parses that owned representation once. Unrelated log lines cannot change heap exhaustion into thread capacity or turn Metaspace into heap-specific remediation. Full retained diagnostics remain available separately.

Both controlled regressions now pass: heap OOME plus unrelated native-thread text reports memory with heap guidance; Metaspace plus unrelated heap text reports Metaspace without heap-specific guidance. The complete focused set passes 268 tests; type/lint, architecture guards, docs, discovery and normal hooks pass. These are controlled provider/pipe/socket and existing CLI/MCP projection checks, not real Ghidra JVM reproductions.

<!-- gh-comment-id:6263847165 --> @morluto commented on GitHub (Oct 19, 2026): Fixed on main in 91884c374385182726a93d56059720d5e78a0e42 together with #4682. The old classifier confirmed an OOME, then took its cause phrases from the entire operation output. The producer now supplies bounded confirmed OOME observations, and the projection parses that owned representation once. Unrelated log lines cannot change heap exhaustion into thread capacity or turn Metaspace into heap-specific remediation. Full retained diagnostics remain available separately. Both controlled regressions now pass: heap OOME plus unrelated native-thread text reports memory with heap guidance; Metaspace plus unrelated heap text reports Metaspace without heap-specific guidance. The complete focused set passes 268 tests; type/lint, architecture guards, docs, discovery and normal hooks pass. These are controlled provider/pipe/socket and existing CLI/MCP projection checks, not real Ghidra JVM reproductions.
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#3198
No description provided.