[GH-ISSUE #3366] [Bug] Native-boundary summary reports false for mixed-mode assemblies #1233

Closed
opened 2026-10-16 21:03:06 +00:00 by bsakaguchi · 0 comments
Owner

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

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

inspect-managed-native-boundaries reports summary.mixed_mode_or_native_header: false for an admitted PE/CLI artifact with ILONLY clear, no ReadyToRun header, and a native method implementation. inspect-managed-artifact classifies the same bytes as mixed-clr-native / cpp-cli-mixed, and the boundary result retains the native implementation. Both mixed-artifact inspections report complete coverage, but the public CLI returns contradictory classification and summary facts.

All four CLI inspections in the reproduction exit with status 0. The mixed boundary result returns cli_native.il_only: false, ready_to_run_signature: false, zero native-header RVA and size, and a NativeMethod implementation with code_type: "native" and boundary_kind: "native-body". Its summary nevertheless reports native_implementation_count: 1, ready_to_run: false, and mixed_mode_or_native_header: false. The pure-IL control returns false and the ReadyToRun control returns true, as expected. The reproduction is complete and was reproduced locally through the built CLI.

Reproduction

  1. Start from a clean checkout of 8dde6370d0809ad04cda3342d4e6f290f48aa063. From the repository root, install the locked dependencies and build the runtime:
npm ci
npm run build:cached
  1. Create mixed.dll and two controls with the repository's byte-fixture builder. The mixed fixture contains one native ret byte and a separate tiny managed ret body:
mkdir -p repro/home
node --input-type=module <<'JS'
import { writeFileSync } from 'node:fs';
import { buildManagedPeFixture } from './scripts/fixtures/managed/pe.mjs';
writeFileSync('repro/mixed.dll', buildManagedPeFixture({
  cliFlags: 0,
  methods: [
    { name: 'NativeMethod', body: Buffer.from([0xc3]), implFlags: 1 },
    { name: 'ManagedMethod', body: Buffer.from([0x06, 0x2a]) }
  ]
}));
writeFileSync('repro/pure.dll', buildManagedPeFixture());
writeFileSync('repro/ready.dll', buildManagedPeFixture({ readyToRun: true }));
JS
  1. Inspect the mixed artifact and all three boundary results. Neither method body is executed by inspection:
HOME="$PWD/repro/home" node scripts/rea.mjs inspect-managed-artifact "$PWD/repro/mixed.dll" --format json --filter-output normalized_result.classification,normalized_result.coverage
HOME="$PWD/repro/home" node scripts/rea.mjs inspect-managed-native-boundaries "$PWD/repro/mixed.dll" --format json --filter-output normalized_result.cli_native,normalized_result.native_implementations,normalized_result.summary,normalized_result.coverage
HOME="$PWD/repro/home" node scripts/rea.mjs inspect-managed-native-boundaries "$PWD/repro/pure.dll" --format json --filter-output normalized_result.summary
HOME="$PWD/repro/home" node scripts/rea.mjs inspect-managed-native-boundaries "$PWD/repro/ready.dll" --format json --filter-output normalized_result.summary
  1. Compare the mixed artifact's classification and retained boundary facts with summary.mixed_mode_or_native_header, then compare that summary field with the pure-IL and ReadyToRun controls.

Expected behavior

The boundary summary should retain the mixed-mode observation already established by the admitted CLI flags. For the mixed fixture, mixed_mode_or_native_header should be true. The pure-IL control should remain false, and the ReadyToRun control should remain true because it has a native header.

docs/managed-code-analysis.md:118 introduces the shipped scope, and docs/managed-code-analysis.md:121 promises observed implementation markers while preserving unavailable facts. docs/managed-code-analysis.md:127 distinguishes a candidate native boundary from recovered native semantics or runtime behavior. Under the managed/native boundary rules at docs/managed-code-analysis.md:321, docs/managed-code-analysis.md:327 keeps metadata tokens separate from native addresses and requires separately verified support for native body mapping.

src/dotnet/ManagedArtifactInspector.test.ts:598 pins the clear-ILONLY classification as mixed-clr-native / cpp-cli-mixed. src/dotnet/ManagedArtifactInspector.ts:194 handles that classification and records that the clear flag requires composed managed/native analysis. Preserving this observation in the summary does not require recovering native body semantics or translating metadata tokens into native addresses.

Impact and scope

P2, supported. The native-boundary summary gives a false negative for an admitted mixed-mode input with complete coverage, so summary-based routing or reporting can omit the native-analysis requirement. The reproduced result retains the underlying flags and native method declaration.

A workaround is available. The executed artifact inspection reports the mixed-mode classification correctly, and the boundary result retains il_only: false and its native implementation. Callers can use those observed facts instead of the faulty summary.

REA version

6.4.0 (main at 8dde6370d0)

Runtime and platform

Node.js v26.10.0; macOS 27.0.1; arm64. The reproduction uses the built local CLI and source-owned byte fixtures. No .NET runtime or external analysis engine was used.

Target and artifact context

Three PE/CLI files generated through scripts/fixtures/managed/pe.mjs: a mixed-mode input with cliFlags: 0, one native method implementation and one tiny managed method body; an ordinary pure-IL control; and a ReadyToRun control. The mixed input has no ReadyToRun signature and zero native-header RVA and size. Inspection executes neither body.

Interface

CLI

Earliest failure stage

Native analysis or reconstruction

Relevant output or evidence

The following excerpts preserve the observed mixed-artifact classification and boundary summary:

{"runtime_family":"mixed-clr-native","implementation":"cpp-cli-mixed"}
{"native_implementation_count":1,"ready_to_run":false,"mixed_mode_or_native_header":false}

Both mixed-artifact inspections report complete coverage. The retained boundary facts are cli_native.il_only: false, ready_to_run_signature: false, zero native-header RVA and size, and NativeMethod with code_type: "native" and boundary_kind: "native-body". All four CLI inspections exit 0. The pure-IL summary field is false, and the ReadyToRun summary field is true.

Typed outcome or recovery expected

Repeat the reproduction commands. The mixed fixture must return a true mixed-mode/native-header summary while preserving its native method declaration and complete coverage. The pure-IL control must stay false, and the ReadyToRun control must stay true. Preserve the distinction between static implementation indicators and recovered or executed native semantics.

Analysis or suspected cause

Source-derived reasoning: src/dotnet/ManagedNativeBoundaryHelpers.ts:405 computes mixed_mode_or_native_header from native-header presence and the entry-point flag, omitting the admitted ILONLY observation. This omission is consistent with the reproduced false summary despite the retained clear flag and native implementation. src/dotnet/ManagedArtifactInspector.ts:194 already uses the clear-ILONLY observation without a ReadyToRun signature to preserve mixed CLR/native classification.

Additional context

Related closed issue #2584 concerns generated fixtures losing their requested ReadyToRun signature when metadata grows; this report concerns a false mixed-mode summary with no ReadyToRun header and correctly retained classification and implementation facts.

Related open issue #3201 concerns missing module identity reported as a P/Invoke module mismatch during verification; this report concerns inspection summary construction without declaration matching or supplied native Evidence.

Related open tracker #2383 tracks broader C++/CLI capability coverage; this report requires preservation of already observed static mixed-mode facts and no native body recovery or debugging capability.

Originally created by @coygeek on GitHub (Oct 14, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/3366 ### 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 `inspect-managed-native-boundaries` reports `summary.mixed_mode_or_native_header: false` for an admitted PE/CLI artifact with ILONLY clear, no ReadyToRun header, and a native method implementation. `inspect-managed-artifact` classifies the same bytes as `mixed-clr-native` / `cpp-cli-mixed`, and the boundary result retains the native implementation. Both mixed-artifact inspections report complete coverage, but the public CLI returns contradictory classification and summary facts. All four CLI inspections in the reproduction exit with status 0. The mixed boundary result returns `cli_native.il_only: false`, `ready_to_run_signature: false`, zero native-header RVA and size, and a `NativeMethod` implementation with `code_type: "native"` and `boundary_kind: "native-body"`. Its summary nevertheless reports `native_implementation_count: 1`, `ready_to_run: false`, and `mixed_mode_or_native_header: false`. The pure-IL control returns false and the ReadyToRun control returns true, as expected. The reproduction is complete and was reproduced locally through the built CLI. ### Reproduction 1. Start from a clean checkout of `8dde6370d0809ad04cda3342d4e6f290f48aa063`. From the repository root, install the locked dependencies and build the runtime: ```sh npm ci npm run build:cached ``` 2. Create `mixed.dll` and two controls with the repository's byte-fixture builder. The mixed fixture contains one native `ret` byte and a separate tiny managed `ret` body: ```sh mkdir -p repro/home node --input-type=module <<'JS' import { writeFileSync } from 'node:fs'; import { buildManagedPeFixture } from './scripts/fixtures/managed/pe.mjs'; writeFileSync('repro/mixed.dll', buildManagedPeFixture({ cliFlags: 0, methods: [ { name: 'NativeMethod', body: Buffer.from([0xc3]), implFlags: 1 }, { name: 'ManagedMethod', body: Buffer.from([0x06, 0x2a]) } ] })); writeFileSync('repro/pure.dll', buildManagedPeFixture()); writeFileSync('repro/ready.dll', buildManagedPeFixture({ readyToRun: true })); JS ``` 3. Inspect the mixed artifact and all three boundary results. Neither method body is executed by inspection: ```sh HOME="$PWD/repro/home" node scripts/rea.mjs inspect-managed-artifact "$PWD/repro/mixed.dll" --format json --filter-output normalized_result.classification,normalized_result.coverage HOME="$PWD/repro/home" node scripts/rea.mjs inspect-managed-native-boundaries "$PWD/repro/mixed.dll" --format json --filter-output normalized_result.cli_native,normalized_result.native_implementations,normalized_result.summary,normalized_result.coverage HOME="$PWD/repro/home" node scripts/rea.mjs inspect-managed-native-boundaries "$PWD/repro/pure.dll" --format json --filter-output normalized_result.summary HOME="$PWD/repro/home" node scripts/rea.mjs inspect-managed-native-boundaries "$PWD/repro/ready.dll" --format json --filter-output normalized_result.summary ``` 4. Compare the mixed artifact's classification and retained boundary facts with `summary.mixed_mode_or_native_header`, then compare that summary field with the pure-IL and ReadyToRun controls. ### Expected behavior The boundary summary should retain the mixed-mode observation already established by the admitted CLI flags. For the mixed fixture, `mixed_mode_or_native_header` should be true. The pure-IL control should remain false, and the ReadyToRun control should remain true because it has a native header. `docs/managed-code-analysis.md:118` introduces the shipped scope, and `docs/managed-code-analysis.md:121` promises observed implementation markers while preserving unavailable facts. `docs/managed-code-analysis.md:127` distinguishes a candidate native boundary from recovered native semantics or runtime behavior. Under the managed/native boundary rules at `docs/managed-code-analysis.md:321`, `docs/managed-code-analysis.md:327` keeps metadata tokens separate from native addresses and requires separately verified support for native body mapping. `src/dotnet/ManagedArtifactInspector.test.ts:598` pins the clear-ILONLY classification as `mixed-clr-native` / `cpp-cli-mixed`. `src/dotnet/ManagedArtifactInspector.ts:194` handles that classification and records that the clear flag requires composed managed/native analysis. Preserving this observation in the summary does not require recovering native body semantics or translating metadata tokens into native addresses. ### Impact and scope P2, supported. The native-boundary summary gives a false negative for an admitted mixed-mode input with complete coverage, so summary-based routing or reporting can omit the native-analysis requirement. The reproduced result retains the underlying flags and native method declaration. A workaround is available. The executed artifact inspection reports the mixed-mode classification correctly, and the boundary result retains `il_only: false` and its native implementation. Callers can use those observed facts instead of the faulty summary. ### REA version 6.4.0 (main at 8dde6370d0809ad04cda3342d4e6f290f48aa063) ### Runtime and platform Node.js v26.10.0; macOS 27.0.1; arm64. The reproduction uses the built local CLI and source-owned byte fixtures. No .NET runtime or external analysis engine was used. ### Target and artifact context Three PE/CLI files generated through `scripts/fixtures/managed/pe.mjs`: a mixed-mode input with `cliFlags: 0`, one native method implementation and one tiny managed method body; an ordinary pure-IL control; and a ReadyToRun control. The mixed input has no ReadyToRun signature and zero native-header RVA and size. Inspection executes neither body. ### Interface CLI ### Earliest failure stage Native analysis or reconstruction ### Relevant output or evidence The following excerpts preserve the observed mixed-artifact classification and boundary summary: ```text {"runtime_family":"mixed-clr-native","implementation":"cpp-cli-mixed"} {"native_implementation_count":1,"ready_to_run":false,"mixed_mode_or_native_header":false} ``` Both mixed-artifact inspections report complete coverage. The retained boundary facts are `cli_native.il_only: false`, `ready_to_run_signature: false`, zero native-header RVA and size, and `NativeMethod` with `code_type: "native"` and `boundary_kind: "native-body"`. All four CLI inspections exit 0. The pure-IL summary field is false, and the ReadyToRun summary field is true. ### Typed outcome or recovery expected Repeat the reproduction commands. The mixed fixture must return a true mixed-mode/native-header summary while preserving its native method declaration and complete coverage. The pure-IL control must stay false, and the ReadyToRun control must stay true. Preserve the distinction between static implementation indicators and recovered or executed native semantics. ### Analysis or suspected cause Source-derived reasoning: `src/dotnet/ManagedNativeBoundaryHelpers.ts:405` computes `mixed_mode_or_native_header` from native-header presence and the entry-point flag, omitting the admitted ILONLY observation. This omission is consistent with the reproduced false summary despite the retained clear flag and native implementation. `src/dotnet/ManagedArtifactInspector.ts:194` already uses the clear-ILONLY observation without a ReadyToRun signature to preserve mixed CLR/native classification. ### Additional context Related closed issue [#2584](https://github.com/morluto/rea/issues/2584) concerns generated fixtures losing their requested ReadyToRun signature when metadata grows; this report concerns a false mixed-mode summary with no ReadyToRun header and correctly retained classification and implementation facts. Related open issue [#3201](https://github.com/morluto/rea/issues/3201) concerns missing module identity reported as a P/Invoke module mismatch during verification; this report concerns inspection summary construction without declaration matching or supplied native Evidence. Related open tracker [#2383](https://github.com/morluto/rea/issues/2383) tracks broader C++/CLI capability coverage; this report requires preservation of already observed static mixed-mode facts and no native body recovery or debugging capability.
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#1233
No description provided.