[GH-ISSUE #7385] [Bug] Managed field signature diagnostics report blob-relative offsets as file offsets #4390

Closed
opened 2026-10-31 00:49:27 +00:00 by bsakaguchi · 0 comments
Owner

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

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Evidence, artifacts, or reconstruction

Observed behavior

node scripts/rea.mjs inspect-managed-members "$WORK/both-signatures.dll" --json returns a malformed field-signature issue at offset: 2, although its invalid TypeDefOrRefOrSpec byte is at artifact file offset 1229. The same result reports the equivalent local-signature failure correctly at 1238. Both entries share one coverage.issues array but use different coordinate systems. The command exits 0 with partial coverage.

Reproduction

Use a checkout at 86d4a21215cb0fbafaf555b5c7d9fcda3f255d82 with Node.js v24.22.1. For fresh setup, run npm ci && npm run build:cached; verification used existing locked dependencies and rebuilt with npm run build:cached. Run the following from the repository root. It generates a synthetic PE/CLI artifact without executing target code or using an external provider. The malformed CLI observation reproduced twice; this shorter inline-generator form ran once.

export WORK="${WORK:-$PWD/work}"
mkdir -p "$WORK"/{home,config,data,cache,state,tmp}
export HOME="$WORK/home" XDG_CONFIG_HOME="$WORK/config" XDG_DATA_HOME="$WORK/data" XDG_CACHE_HOME="$WORK/cache" XDG_STATE_HOME="$WORK/state" TMPDIR="$WORK/tmp"
node --input-type=module <<'JS'
import { writeFileSync } from 'node:fs';
import { buildManagedPeFixture } from './src/dotnet/ManagedPe.fixture.ts';
const header = Buffer.alloc(12);
header.writeUInt16LE(0x3013, 0);
header.writeUInt16LE(1, 2);
header.writeUInt32LE(1, 4);
header.writeUInt32LE(0x11000001, 8);
const bytes = buildManagedPeFixture({
  fieldSignature: Buffer.from([0x06, 0x12, 0x07]),
  ilBody: Buffer.concat([header, Buffer.from([0x2a])]),
  standaloneSignatures: [Buffer.from([0x07, 0x01, 0x12, 0x07])],
});
writeFileSync(`${process.env.WORK}/both-signatures.dll`, bytes);
console.log(JSON.stringify({length:bytes.length, field_item_at_1226:bytes.subarray(1226,1230).toString('hex'), local_item_at_1234:bytes.subarray(1234,1239).toString('hex'), byte_at_2:bytes[2]}));
JS
node scripts/rea.mjs inspect-managed-members "$WORK/both-signatures.dll" --json > "$WORK/report.json"
node --input-type=module <<'JS'
import {readFileSync} from 'node:fs';
const d=JSON.parse(readFileSync(`${process.env.WORK}/report.json`,'utf8'));
console.log(JSON.stringify((d.normalized_result??d).coverage));
JS

Expected behavior

The field issue should report artifact file offset 1229, preserving its invalid-row code, scope, failure detail, and partial coverage. CHANGELOG.md:170 states “Metadata errors report artifact file offsets”; docs/managed-code-analysis.md:625 applies this convention to malformed metadata. The adjacent local-signature implementation in src/dotnet/ManagedMemberInspectorCore.ts:845 adds the blob's artifact base to the decoder offset, matching the observed local-signature result.

Impact and scope

P2: this bounded malformed-input case points an analyst or script at a DOS-header byte instead of the invalid field operand. Invalidity remains visible, and an independently tested valid primitive-field control returned complete coverage with no issues. The fixture's blob bytes provide a manual workaround: the field item begins at 1226, its one-byte length prefix is followed by 06 12 07, and the invalid final byte is at 1229. Other member kinds and the MCP adapter were not executed.

REA version

Exact node scripts/rea.mjs --version output: 6.8.0. Source commit: 86d4a21215cb0fbafaf555b5c7d9fcda3f255d82.

Runtime and platform

Node.js v24.22.1; macOS 27.0.1; darwin arm64, measured in the reproduction environment.

Target and artifact context

A 4096-byte synthetic managed PE from src/dotnet/ManagedPe.fixture.ts, containing FIELD CLASS with reserved coded-index tag 3 and an equivalent malformed local-variable signature. No private artifact or external analysis engine was used.

Interface

CLI

Earliest failure stage

Native analysis or reconstruction

Relevant output or evidence

Observed output from the inline generator and CLI projection:

{"length":4096,"field_item_at_1226":"03061207","local_item_at_1234":"0407011207","byte_at_2":0}
{"state":"partial","issues":[{"code":"invalid-row","scope":"Field:0x04000001.signature","offset":2,"detail":"TypeDefOrRefOrSpec operand 0x7 is invalid: coded index tag 3 is not defined"},{"code":"invalid-row","scope":"metadata.StandAloneSig:0x11000001.signature","offset":1238,"detail":"TypeDefOrRefOrSpec operand 0x7 is invalid: coded index tag 3 is not defined"}]}

Typed outcome or recovery expected

Proposed restoration check, not executed: rerun this fixture and require field offset 1229 while retaining local offset 1238, both failure details, and partial coverage. The valid primitive-field control should remain complete.

Analysis or suspected cause

Source-derived reasoning: decodeSignature at src/dotnet/ManagedMemberInspectorCore.ts:1045 forwards invalid-row failures with only their scope replaced. metadataSignature at line 1196 pushes those issues unchanged. Its caller in src/dotnet/ManagedMemberRows.ts:577 supplies the signature bytes without their artifact-coordinate base, leaving the decoder's local offset in caller-visible coverage.

Additional context

Closed #3364 and #4372 corrected metadata range and stream-name coordinates in different producers. Closed #6572 concerns invalid signature operands being falsely decoded as complete; the current result correctly recognizes invalidity, but this report concerns the retained diagnostic's source coordinate. No fix or post-fix verification was performed.

Originally created by @coygeek on GitHub (Oct 27, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/7385 ## 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 Evidence, artifacts, or reconstruction ## Observed behavior `node scripts/rea.mjs inspect-managed-members "$WORK/both-signatures.dll" --json` returns a malformed field-signature issue at `offset: 2`, although its invalid TypeDefOrRefOrSpec byte is at artifact file offset `1229`. The same result reports the equivalent local-signature failure correctly at `1238`. Both entries share one `coverage.issues` array but use different coordinate systems. The command exits 0 with partial coverage. ## Reproduction Use a checkout at `86d4a21215cb0fbafaf555b5c7d9fcda3f255d82` with Node.js `v24.22.1`. For fresh setup, run `npm ci && npm run build:cached`; verification used existing locked dependencies and rebuilt with `npm run build:cached`. Run the following from the repository root. It generates a synthetic PE/CLI artifact without executing target code or using an external provider. The malformed CLI observation reproduced twice; this shorter inline-generator form ran once. ```sh export WORK="${WORK:-$PWD/work}" mkdir -p "$WORK"/{home,config,data,cache,state,tmp} export HOME="$WORK/home" XDG_CONFIG_HOME="$WORK/config" XDG_DATA_HOME="$WORK/data" XDG_CACHE_HOME="$WORK/cache" XDG_STATE_HOME="$WORK/state" TMPDIR="$WORK/tmp" node --input-type=module <<'JS' import { writeFileSync } from 'node:fs'; import { buildManagedPeFixture } from './src/dotnet/ManagedPe.fixture.ts'; const header = Buffer.alloc(12); header.writeUInt16LE(0x3013, 0); header.writeUInt16LE(1, 2); header.writeUInt32LE(1, 4); header.writeUInt32LE(0x11000001, 8); const bytes = buildManagedPeFixture({ fieldSignature: Buffer.from([0x06, 0x12, 0x07]), ilBody: Buffer.concat([header, Buffer.from([0x2a])]), standaloneSignatures: [Buffer.from([0x07, 0x01, 0x12, 0x07])], }); writeFileSync(`${process.env.WORK}/both-signatures.dll`, bytes); console.log(JSON.stringify({length:bytes.length, field_item_at_1226:bytes.subarray(1226,1230).toString('hex'), local_item_at_1234:bytes.subarray(1234,1239).toString('hex'), byte_at_2:bytes[2]})); JS node scripts/rea.mjs inspect-managed-members "$WORK/both-signatures.dll" --json > "$WORK/report.json" node --input-type=module <<'JS' import {readFileSync} from 'node:fs'; const d=JSON.parse(readFileSync(`${process.env.WORK}/report.json`,'utf8')); console.log(JSON.stringify((d.normalized_result??d).coverage)); JS ``` ## Expected behavior The field issue should report artifact file offset `1229`, preserving its invalid-row code, scope, failure detail, and partial coverage. `CHANGELOG.md:170` states “Metadata errors report artifact file offsets”; `docs/managed-code-analysis.md:625` applies this convention to malformed metadata. The adjacent local-signature implementation in `src/dotnet/ManagedMemberInspectorCore.ts:845` adds the blob's artifact base to the decoder offset, matching the observed local-signature result. ## Impact and scope P2: this bounded malformed-input case points an analyst or script at a DOS-header byte instead of the invalid field operand. Invalidity remains visible, and an independently tested valid primitive-field control returned complete coverage with no issues. The fixture's blob bytes provide a manual workaround: the field item begins at `1226`, its one-byte length prefix is followed by `06 12 07`, and the invalid final byte is at `1229`. Other member kinds and the MCP adapter were not executed. ## REA version Exact `node scripts/rea.mjs --version` output: `6.8.0`. Source commit: `86d4a21215cb0fbafaf555b5c7d9fcda3f255d82`. ## Runtime and platform Node.js `v24.22.1`; macOS `27.0.1`; `darwin arm64`, measured in the reproduction environment. ## Target and artifact context A 4096-byte synthetic managed PE from `src/dotnet/ManagedPe.fixture.ts`, containing `FIELD CLASS` with reserved coded-index tag 3 and an equivalent malformed local-variable signature. No private artifact or external analysis engine was used. ## Interface CLI ## Earliest failure stage Native analysis or reconstruction ## Relevant output or evidence Observed output from the inline generator and CLI projection: ```json {"length":4096,"field_item_at_1226":"03061207","local_item_at_1234":"0407011207","byte_at_2":0} {"state":"partial","issues":[{"code":"invalid-row","scope":"Field:0x04000001.signature","offset":2,"detail":"TypeDefOrRefOrSpec operand 0x7 is invalid: coded index tag 3 is not defined"},{"code":"invalid-row","scope":"metadata.StandAloneSig:0x11000001.signature","offset":1238,"detail":"TypeDefOrRefOrSpec operand 0x7 is invalid: coded index tag 3 is not defined"}]} ``` ## Typed outcome or recovery expected Proposed restoration check, not executed: rerun this fixture and require field offset `1229` while retaining local offset `1238`, both failure details, and partial coverage. The valid primitive-field control should remain complete. ## Analysis or suspected cause Source-derived reasoning: `decodeSignature` at `src/dotnet/ManagedMemberInspectorCore.ts:1045` forwards invalid-row failures with only their scope replaced. `metadataSignature` at line 1196 pushes those issues unchanged. Its caller in `src/dotnet/ManagedMemberRows.ts:577` supplies the signature bytes without their artifact-coordinate base, leaving the decoder's local offset in caller-visible coverage. ## Additional context Closed [#3364](https://github.com/morluto/rea/issues/3364) and [#4372](https://github.com/morluto/rea/issues/4372) corrected metadata range and stream-name coordinates in different producers. Closed [#6572](https://github.com/morluto/rea/issues/6572) concerns invalid signature operands being falsely decoded as complete; the current result correctly recognizes invalidity, but this report concerns the retained diagnostic's source coordinate. No fix or post-fix verification was performed.
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#4390
No description provided.