[GH-ISSUE #5552] [Bug] demangle-swift reports an omitted record as demangled and fails mixed batches #3380

Closed
opened 2026-10-31 00:39:45 +00:00 by bsakaguchi · 2 comments
Owner

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

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

With the native macOS provider, demangle-swift returns a successful empty name marked demangled for _. A batch containing _ and $s4main3FooV instead fails with unreadable_output, losing the valid companion's main.Foo result. Both outcomes were independently reproduced through the public CLI and real stdio MCP server.

The real Swift demangler exits 0 but omits the _ output record. This report concerns how REA interprets that incomplete output.

Reproduction

The independent verifier ran these cases once each from the baseline source checkout with dependencies installed and the runtime built. REA used disposable HOME, XDG_CONFIG_HOME, XDG_DATA_HOME, XDG_CACHE_HOME, XDG_STATE_HOME and TMPDIR directories, with REA_ANALYSIS_PROVIDER=auto and REA_LOG_LEVEL=silent. No analysis database was needed.

work="$(mktemp -d)"
cp /usr/bin/true "$work/artifact"

xcrun swift-demangle --compact -- '_'
xcrun swift-demangle --compact -- '_' '$s4main3FooV'

node scripts/rea.mjs demangle-swift "$work/artifact" --format json '_'
node scripts/rea.mjs demangle-swift "$work/artifact" --format json '_' '$s4main3FooV'
node scripts/rea.mjs demangle-swift "$work/artifact" --format json '$s4main3FooV' '_Sa'

The producer commands exit 0 with, respectively, empty stdout and only main.Foo followed by LF. REA's first request exits 0 with the incorrect record below; the mixed request exits 1. The control exits 0 with main.Foo/demangled and _Sa/unchanged.

MCP parity was independently reproduced with node scripts/rea.mjs mcp: open_binary on the absolute artifact path, then demangle_swift with each of {"symbols":["_"]}, {"symbols":["_","$s4main3FooV"]} and {"symbols":["$s4main3FooV","_Sa"]}, then close_binary. The single input succeeds with the same incorrect record, the mixed call returns isError: true, and the control succeeds.

Expected behavior

Source-derived contract: src/contracts/native/nativeToolContracts.ts:69-75 accepts nonempty single-line strings without NUL, including _. Its demangle_swift description at lines 124-128 promises a demangled, unchanged or invalid status for each input; the live MCP catalog advertised the same promise.

An omitted producer record must not become a fabricated successful decoding. The mixed request should preserve one truthful ordered outcome per input, including main.Foo for $s4main3FooV.

Impact and scope

P2, supported by the independent reproduction. One accepted input yields an incorrect machine-readable status or prevents retrieval of another symbol's result in a batch. Both CLI and MCP reproduced the defect on the stated toolchain. No broader outage, persistent data loss or security impact was established. Other toolchain versions and population frequency were not tested.

Excluding _ allows other symbols to be processed, as demonstrated by the successful control batch; callers must account for the excluded input themselves.

REA version

6.7.0, source-built runtime at 074768901f3cdc8205b61773fb1faf6f6c7b3ca8.

The latest published release checked was rea-agents-6.7.0. Upstream main was inspected at eac296a7da3356f1c5342155d635975ddd89cba6: the parser and input contract are unchanged since the baseline, and the intervening provider change concerns failure cleanup ownership. Current-main applicability is source-inspected, not a new runtime reproduction or an installed-package test.

Runtime and platform

Node v26.12.0; macOS 27.0.1 arm64; Xcode 27.1 build 27A9275; Apple Swift 6.4, swiftlang-6.4.0.34.1 clang-2100.3.34.1.

Target and artifact context

A disposable copy of the system Mach-O executable /usr/bin/true, used for artifact identity and never executed. No Hopper or Ghidra provider was required.

Interface

CLI

Earliest failure stage

Native analysis or reconstruction

Relevant output or evidence

Observed single-input normalized_result.symbols through CLI and MCP:

[{"input":"_","output":"","status":"demangled"}]

The successful result records stdout_bytes: 0 and stderr_bytes: 125 in invocation provenance. The producer emits a warning on stderr, which REA does not expose as text in these results.

The mixed CLI request has top-level code: "unreadable_output", category: "execution_failure", retryable: false, and details:

{"operation":"demangle_swift","reason":"Native output parsing failed"}

Its message recommends rea doctor. MCP returns these diagnostic fields inside a canonical error object in text content with isError: true. Neither returns the valid companion result for this batch. The producer's exit 0 and the successful control distinguish this from an unavailable toolchain or general session failure.

Typed outcome or recovery expected

Return a truthful per-input outcome for _ without claiming it decoded to an empty name. Preserve main.Foo/demangled for the valid companion in the mixed batch and preserve the control's _Sa/unchanged outcome. The choice of representation for an omitted producer record is left to the maintainers.

Analysis or suspected cause

Source-derived: src/native/NativeMacOSProvider.ts passes successful producer stdout to parseDemangledSymbols. In src/native/parsers/demangle.ts:31-38, splitting empty stdout produces one empty line, which satisfies the one-input count and becomes demangled. With two inputs and only one producer record, the count check throws instead. No repair implementation is prescribed.

Additional context

Prepared with AI assistance and independently reproduced through the real producer, CLI and MCP. Related #4215 and its superseded PR #4287 concern adjusted undecoded spellings, rather than missing output records. PR #2875 concerns an empty input list, rather than this nonempty input and mixed batch.

NOT_ENOUGH_INFO: no last-known-good version was established, and other Swift toolchains or architectures were not tested.

Originally created by @coygeek on GitHub (Oct 20, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/5552 ### 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 With the native macOS provider, `demangle-swift` returns a successful empty name marked `demangled` for `_`. A batch containing `_` and `$s4main3FooV` instead fails with `unreadable_output`, losing the valid companion's `main.Foo` result. Both outcomes were independently reproduced through the public CLI and real stdio MCP server. The real Swift demangler exits 0 but omits the `_` output record. This report concerns how REA interprets that incomplete output. ### Reproduction The independent verifier ran these cases once each from the baseline source checkout with dependencies installed and the runtime built. REA used disposable HOME, XDG_CONFIG_HOME, XDG_DATA_HOME, XDG_CACHE_HOME, XDG_STATE_HOME and TMPDIR directories, with `REA_ANALYSIS_PROVIDER=auto` and `REA_LOG_LEVEL=silent`. No analysis database was needed. ```sh work="$(mktemp -d)" cp /usr/bin/true "$work/artifact" xcrun swift-demangle --compact -- '_' xcrun swift-demangle --compact -- '_' '$s4main3FooV' node scripts/rea.mjs demangle-swift "$work/artifact" --format json '_' node scripts/rea.mjs demangle-swift "$work/artifact" --format json '_' '$s4main3FooV' node scripts/rea.mjs demangle-swift "$work/artifact" --format json '$s4main3FooV' '_Sa' ``` The producer commands exit 0 with, respectively, empty stdout and only `main.Foo` followed by LF. REA's first request exits 0 with the incorrect record below; the mixed request exits 1. The control exits 0 with `main.Foo`/`demangled` and `_Sa`/`unchanged`. MCP parity was independently reproduced with `node scripts/rea.mjs mcp`: `open_binary` on the absolute artifact path, then `demangle_swift` with each of `{"symbols":["_"]}`, `{"symbols":["_","$s4main3FooV"]}` and `{"symbols":["$s4main3FooV","_Sa"]}`, then `close_binary`. The single input succeeds with the same incorrect record, the mixed call returns `isError: true`, and the control succeeds. ### Expected behavior Source-derived contract: `src/contracts/native/nativeToolContracts.ts:69-75` accepts nonempty single-line strings without NUL, including `_`. Its `demangle_swift` description at lines 124-128 promises a demangled, unchanged or invalid status for each input; the live MCP catalog advertised the same promise. An omitted producer record must not become a fabricated successful decoding. The mixed request should preserve one truthful ordered outcome per input, including `main.Foo` for `$s4main3FooV`. ### Impact and scope P2, supported by the independent reproduction. One accepted input yields an incorrect machine-readable status or prevents retrieval of another symbol's result in a batch. Both CLI and MCP reproduced the defect on the stated toolchain. No broader outage, persistent data loss or security impact was established. Other toolchain versions and population frequency were not tested. Excluding `_` allows other symbols to be processed, as demonstrated by the successful control batch; callers must account for the excluded input themselves. ### REA version 6.7.0, source-built runtime at `074768901f3cdc8205b61773fb1faf6f6c7b3ca8`. The latest published release checked was `rea-agents-6.7.0`. Upstream main was inspected at `eac296a7da3356f1c5342155d635975ddd89cba6`: the parser and input contract are unchanged since the baseline, and the intervening provider change concerns failure cleanup ownership. Current-main applicability is source-inspected, not a new runtime reproduction or an installed-package test. ### Runtime and platform Node v26.12.0; macOS 27.0.1 arm64; Xcode 27.1 build 27A9275; Apple Swift 6.4, swiftlang-6.4.0.34.1 clang-2100.3.34.1. ### Target and artifact context A disposable copy of the system Mach-O executable `/usr/bin/true`, used for artifact identity and never executed. No Hopper or Ghidra provider was required. ### Interface CLI ### Earliest failure stage Native analysis or reconstruction ### Relevant output or evidence Observed single-input `normalized_result.symbols` through CLI and MCP: ```json [{"input":"_","output":"","status":"demangled"}] ``` The successful result records `stdout_bytes: 0` and `stderr_bytes: 125` in invocation provenance. The producer emits a warning on stderr, which REA does not expose as text in these results. The mixed CLI request has top-level `code: "unreadable_output"`, `category: "execution_failure"`, `retryable: false`, and details: ```json {"operation":"demangle_swift","reason":"Native output parsing failed"} ``` Its message recommends `rea doctor`. MCP returns these diagnostic fields inside a canonical `error` object in text content with `isError: true`. Neither returns the valid companion result for this batch. The producer's exit 0 and the successful control distinguish this from an unavailable toolchain or general session failure. ### Typed outcome or recovery expected Return a truthful per-input outcome for `_` without claiming it decoded to an empty name. Preserve `main.Foo`/`demangled` for the valid companion in the mixed batch and preserve the control's `_Sa`/`unchanged` outcome. The choice of representation for an omitted producer record is left to the maintainers. ### Analysis or suspected cause Source-derived: `src/native/NativeMacOSProvider.ts` passes successful producer stdout to `parseDemangledSymbols`. In `src/native/parsers/demangle.ts:31-38`, splitting empty stdout produces one empty line, which satisfies the one-input count and becomes `demangled`. With two inputs and only one producer record, the count check throws instead. No repair implementation is prescribed. ### Additional context Prepared with AI assistance and independently reproduced through the real producer, CLI and MCP. Related #4215 and its superseded PR #4287 concern adjusted undecoded spellings, rather than missing output records. PR #2875 concerns an empty input list, rather than this nonempty input and mixed batch. NOT_ENOUGH_INFO: no last-known-good version was established, and other Swift toolchains or architectures were not tested.
Author
Owner

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

Cross-referencing with canonical issue #4296 and sibling #5553 regarding Swift symbol demangling anomalies, omitted record handling, and batch decoding in demangle-swift. Cataloged under Cluster BA in consolidation tracker #4330.

<!-- gh-comment-id:6295544400 --> @matbrgz commented on GitHub (Oct 20, 2026): Cross-referencing with canonical issue #4296 and sibling #5553 regarding Swift symbol demangling anomalies, omitted record handling, and batch decoding in `demangle-swift`. Cataloged under Cluster BA in consolidation tracker #4330.
Author
Owner

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

Resolved by github.com/morluto/rea@93de7bc7e3. The demangler record owner counts only non-skipped underscore arguments, preserves ordering/native spelling and marks skipped underscore invalid. Mixed, all-skipped and missing/excess record controls pass. Validation: src/native/parsers/demangle.test.ts passed in the recorded round2/3 execution; this review did not rerun tests. Coverage is limited to the cited control; no broader real-provider, Windows or performance claim.

<!-- gh-comment-id:6376115640 --> @morluto commented on GitHub (Oct 23, 2026): Resolved by https://github.com/morluto/rea/commit/93de7bc7e324a761162a31625b838ba0d4e3824d. The demangler record owner counts only non-skipped underscore arguments, preserves ordering/native spelling and marks skipped underscore invalid. Mixed, all-skipped and missing/excess record controls pass. Validation: `src/native/parsers/demangle.test.ts` passed in the recorded round2/3 execution; this review did not rerun tests. Coverage is limited to the cited control; no broader real-provider, Windows or performance claim.
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#3380
No description provided.