[GH-ISSUE #2584] fix(managed): retain ReadyToRun detection for larger method lists #901

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

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

Summary

A managed fixture requested with ReadyToRun enabled loses that classification when its method list grows from 46 to 47 entries. The producer returns an apparently managed image whose declared native header contains metadata text instead of the requested signature. This gives verification consumers a false negative for ReadyToRun support.

Steps to reproduce

At the repository root in the environment below, compare these two fixture inputs. No build or target execution is required for the byte-level check.

node --input-type=module <<'JS'
import { buildManagedPeFixture } from './scripts/fixtures/managed/pe.mjs';
for (const count of [46, 47]) {
  const bytes = buildManagedPeFixture({ readyToRun: true,
    methods: Array.from({ length: count }, (_, i) => ({ name: `Method${i}` })) });
  const rva = bytes.readUInt32LE(0x240);
  const offset = rva - 0x2000 + 0x200;
  console.log(JSON.stringify({ count, nativeHeaderRva: rva,
    size: bytes.readUInt32LE(0x244),
    signature: bytes.subarray(offset, offset + 4).toString('latin1') }));
}
JS

Expected behavior

Both fixtures preserve the requested ReadyToRun signature at the native-header address declared by the CLI header. Managed artifact inspection reports ReadyToRun detection and the combined CIL and ReadyToRun implementation for both supported method lists.

Actual behavior

The 46-method fixture contains RTR followed by a NUL byte at the declared address. The 47-method fixture contains n=v8 there, although both declare the same 4-byte native header. A focused source-inspector test reproduced detection changing from true to false and implementation changing from cil-and-ready-to-run to cil. Both fixtures were classified as managed with no coverage issues.

Evidence

  • Expected source: scripts/fixtures/managed/pe.d.mts:17 and :24 declare the method-list and ReadyToRun options; scripts/verify/managed/conformance.mjs:210 builds through this producer and requires ReadyToRun classification and native-boundary detection.
  • Failure source: scripts/fixtures/managed/pe.mjs:376 writes the declared native header and signature before :385 copies metadata across the signature location. src/dotnet/ManagedPeReader.ts:243 reads the signature at that declared address. The byte check and source-inspector test reproduced the false negative.
  • Evidence provenance: observed
  • Local verification: reproduced
  • Reproduction completeness: complete

The metadata length grows from 1524 to 1544 bytes between the controls and reaches into the signature's slot. This signal occurs within the allocated image and does not depend on metadata extending past the end of the file.

Restoration check

Repeat both inputs and read the signature from each fixture's declared native-header address. Require the ReadyToRun signature and positive detection for both, while preserving their complete metadata and method bodies. Require the source inspector to report cil-and-ready-to-run. Moving the signature address is acceptable when the directory and bytes remain consistent; writing signature bytes into live metadata is not a valid restoration.

Runtime or environment

Repository revision 8b181716ac; Node v26.10.0; locked dependencies already installed. Classification was checked through the repository's focused source test runner.

Triage assessment

  • Impact level: P2
  • Assessment status: supported
  • Impact basis: Supported verification fixtures silently lose requested ReadyToRun detection for a bounded method-list input, which can invalidate conformance results.
  • Workaround status: unverified
  • Workaround basis: Shorter method lists retain detection but omit requested methods; no workaround preserving the full requested fixture was verified.
Originally created by @coygeek on GitHub (Oct 13, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/2584 ## Summary A managed fixture requested with ReadyToRun enabled loses that classification when its method list grows from 46 to 47 entries. The producer returns an apparently managed image whose declared native header contains metadata text instead of the requested signature. This gives verification consumers a false negative for ReadyToRun support. ## Steps to reproduce At the repository root in the environment below, compare these two fixture inputs. No build or target execution is required for the byte-level check. ```bash node --input-type=module <<'JS' import { buildManagedPeFixture } from './scripts/fixtures/managed/pe.mjs'; for (const count of [46, 47]) { const bytes = buildManagedPeFixture({ readyToRun: true, methods: Array.from({ length: count }, (_, i) => ({ name: `Method${i}` })) }); const rva = bytes.readUInt32LE(0x240); const offset = rva - 0x2000 + 0x200; console.log(JSON.stringify({ count, nativeHeaderRva: rva, size: bytes.readUInt32LE(0x244), signature: bytes.subarray(offset, offset + 4).toString('latin1') })); } JS ``` ## Expected behavior Both fixtures preserve the requested ReadyToRun signature at the native-header address declared by the CLI header. Managed artifact inspection reports ReadyToRun detection and the combined CIL and ReadyToRun implementation for both supported method lists. ## Actual behavior The 46-method fixture contains `RTR` followed by a NUL byte at the declared address. The 47-method fixture contains `n=v8` there, although both declare the same 4-byte native header. A focused source-inspector test reproduced detection changing from true to false and implementation changing from `cil-and-ready-to-run` to `cil`. Both fixtures were classified as managed with no coverage issues. ## Evidence - Expected source: `scripts/fixtures/managed/pe.d.mts:17` and `:24` declare the method-list and ReadyToRun options; `scripts/verify/managed/conformance.mjs:210` builds through this producer and requires ReadyToRun classification and native-boundary detection. - Failure source: `scripts/fixtures/managed/pe.mjs:376` writes the declared native header and signature before `:385` copies metadata across the signature location. `src/dotnet/ManagedPeReader.ts:243` reads the signature at that declared address. The byte check and source-inspector test reproduced the false negative. - Evidence provenance: observed - Local verification: reproduced - Reproduction completeness: complete The metadata length grows from 1524 to 1544 bytes between the controls and reaches into the signature's slot. This signal occurs within the allocated image and does not depend on metadata extending past the end of the file. ## Restoration check Repeat both inputs and read the signature from each fixture's declared native-header address. Require the ReadyToRun signature and positive detection for both, while preserving their complete metadata and method bodies. Require the source inspector to report `cil-and-ready-to-run`. Moving the signature address is acceptable when the directory and bytes remain consistent; writing signature bytes into live metadata is not a valid restoration. ## Runtime or environment Repository revision 8b181716aca2cb467be499cba226abfb5ae19141; Node v26.10.0; locked dependencies already installed. Classification was checked through the repository's focused source test runner. ## Triage assessment - Impact level: P2 - Assessment status: supported - Impact basis: Supported verification fixtures silently lose requested ReadyToRun detection for a bounded method-list input, which can invalidate conformance results. - Workaround status: unverified - Workaround basis: Shorter method lists retain detection but omit requested methods; no workaround preserving the full requested fixture was verified.
bsakaguchi 2026-10-15 18:29:26 +00:00
Author
Owner

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

Verified the reported defect is addressed on main by 537467ab9e.

Root cause and resolution: Metadata copied over the fixed ReadyToRun signature slot as method count increased.

Validation: src/dotnet/ManagedPeFixtureLayout.test.ts — keeps the ReadyToRun signature outside expanded metadata builds 47 methods and asserts the signature at the declared native-header RVA remains RTR\0.

Evidence: CI run 500e: owner unchanged and assertion passed.

Verification scope: The signature/metadata layout is covered; do not infer general managed runtime compatibility.

Current main CI has separate failures under repair; this closure does not claim the complete main workflow is green.

<!-- gh-comment-id:6162515404 --> @morluto commented on GitHub (Oct 14, 2026): Verified the reported defect is addressed on main by 537467ab9ecad4db8f984c792cd165d01a10054d. Root cause and resolution: Metadata copied over the fixed ReadyToRun signature slot as method count increased. Validation: `src/dotnet/ManagedPeFixtureLayout.test.ts` — `keeps the ReadyToRun signature outside expanded metadata` builds 47 methods and asserts the signature at the declared native-header RVA remains `RTR\0`. Evidence: CI run 500e: owner unchanged and assertion passed. Verification scope: The signature/metadata layout is covered; do not infer general managed runtime compatibility. Current main CI has separate failures under repair; this closure does not claim the complete main workflow is green.
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#901
No description provided.