[PR #2241] [MERGED] fix(managed): decode the CIL no. prefix #5108

Closed
opened 2026-10-31 01:04:01 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/2241
Author: @Angelopgit
Created: 10/12/2026
Status: ✅ Merged
Merged: 10/13/2026
Merged by: @morluto

Base: main ← Head: fix/managed-no-prefix


📝 Commits (1)

  • 48ffdd9 fix(managed): decode the CIL no. prefix

📊 Changes

2 files changed (+27 additions, -0 deletions)

View changed files

📝 src/dotnet/ManagedCilDecoding.test.ts (+25 -0)
📝 src/dotnet/ManagedMemberInstructionDecoder.ts (+2 -0)

📄 Description

Summary

inspect_managed_members reports a method as malformed when its IL uses the no. prefix. The CIL opcode table has five of the six ECMA-335 prefix opcodes and omits no. (FE 19 <unsigned int8>, Partition III §2.2). No issue is linked: I searched open and closed issues and PRs for 0xfe19 and the decoder and found none, and the fix is two table lines.

Problem and expected behavior

Smallest trigger, a method body with this IL:

02              ldarg.0
FE 19 04        no. nullcheck
7B 01 00 00 04  ldfld 0x04000001
26              pop
2A              ret

Observed on main: status: "malformed", issue: "Unsupported CIL opcode 0xfe19 at IL offset 1", normalized_il_sha256: null.

Expected: status: "present", five decoded instructions, issue: null, as for the other prefixes.

Change and scope

  • Add 0xfe19 as no. with a one-byte operand (short-i, the same kind unaligned. uses).
  • Add no. to PREFIX_OPCODES, so it shares an instruction boundary with the opcode it modifies and an exception region cannot start between them.

Not included: validation of the check-mask bits or of which opcodes no. may precede. The decoder does not validate that for the other prefixes either.

Contract and boundary impact

  • Semantic owner and earliest changed stage: CIL instruction decoding in src/dotnet/ManagedMemberInstructionDecoder.ts.
  • CLI and MCP/tool-catalog contract: none. No schemas change; no. can now appear as an opcode name in opcode_counts.
  • Provider, bridge, target-format, or platform compatibility: method bodies using no. are decoded instead of marked malformed. Digests of bodies that already decoded are unchanged.
  • Evidence, artifact, provenance, or reconstruction contract: none.
  • Process execution, authorization, cleanup, or containment impact: none.
  • Generated metadata, package, or installation impact: none.

Evidence and regression coverage

  • Tests added or updated: one test in src/dotnet/ManagedCilDecoding.test.ts ("managed exception region prefix boundaries"). It checks that the body above decodes, and that a try range starting between no. and ldfld is refused as misaligned.
  • Base reproduction or other evidence: executed. With the decoder change reverted the new test fails with Unsupported CIL opcode 0xfe19 at IL offset 1.
  • User-visible CLI/MCP output: not applicable beyond the fields above.
  • Remaining proof gaps: the IL is a hand-built fixture. Mainstream compilers rarely emit no., and I did not have an assembler-produced binary containing it.

For evidence-bearing changes:

  • Observed, derived, and inferred claims remain distinguishable.
  • Artifact identity, source provenance, and failed attempts remain preserved.
  • Unsupported, incomplete, unavailable, or uncertain outcomes remain visible.

Validation performed

  • npx vitest run src/dotnet tests/boundary/dotnet — 11 files passed
  • npm run check — passed
  • npm run verify:test-discovery — "Discovered all 936 test files exactly once."

Compatibility, safety, and release

  • Breaking changes or migration steps: none.
  • Real Hopper/Ghidra, browser, or OS coverage: Linux x64 only. No provider runs; this path is static parsing.
  • Package or release metadata impact: none.
  • Security, privacy, process, or containment review: parsing only; the operand read is bound-checked by the existing decoder path.

Review checklist

  • This PR addresses a concrete problem or an agreed enhancement.
  • The PR has one focused outcome and the title follows type(scope): outcome.
  • Related issue is linked, or the reason for not linking one is stated above.
  • Tests cover changed observable behavior and meaningful failure paths.
  • Owning docs, contracts, and generated metadata are updated where needed.
  • User-visible CLI/MCP changes include representative output.
  • I checked the final diff for secrets, unrelated cleanup, and unsupported claims.

🤖 Generated with Claude Code

https://claude.ai/code/session_012pRGskbPGjT444CgJfuhhj


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/2241 **Author:** [@Angelopgit](https://github.com/Angelopgit) **Created:** 10/12/2026 **Status:** ✅ Merged **Merged:** 10/13/2026 **Merged by:** [@morluto](https://github.com/morluto) **Base:** `main` ← **Head:** `fix/managed-no-prefix` --- ### 📝 Commits (1) - [`48ffdd9`](https://github.com/morluto/rea/commit/48ffdd9a62c8a81ccc61e9b441ea724ddefeeae4) fix(managed): decode the CIL no. prefix ### 📊 Changes **2 files changed** (+27 additions, -0 deletions) <details> <summary>View changed files</summary> 📝 `src/dotnet/ManagedCilDecoding.test.ts` (+25 -0) 📝 `src/dotnet/ManagedMemberInstructionDecoder.ts` (+2 -0) </details> ### 📄 Description ## Summary `inspect_managed_members` reports a method as malformed when its IL uses the `no.` prefix. The CIL opcode table has five of the six ECMA-335 prefix opcodes and omits `no.` (`FE 19 <unsigned int8>`, Partition III §2.2). No issue is linked: I searched open and closed issues and PRs for `0xfe19` and the decoder and found none, and the fix is two table lines. ## Problem and expected behavior Smallest trigger, a method body with this IL: ``` 02 ldarg.0 FE 19 04 no. nullcheck 7B 01 00 00 04 ldfld 0x04000001 26 pop 2A ret ``` Observed on `main`: `status: "malformed"`, `issue: "Unsupported CIL opcode 0xfe19 at IL offset 1"`, `normalized_il_sha256: null`. Expected: `status: "present"`, five decoded instructions, `issue: null`, as for the other prefixes. ## Change and scope - Add `0xfe19` as `no.` with a one-byte operand (`short-i`, the same kind `unaligned.` uses). - Add `no.` to `PREFIX_OPCODES`, so it shares an instruction boundary with the opcode it modifies and an exception region cannot start between them. Not included: validation of the check-mask bits or of which opcodes `no.` may precede. The decoder does not validate that for the other prefixes either. ## Contract and boundary impact - Semantic owner and earliest changed stage: CIL instruction decoding in `src/dotnet/ManagedMemberInstructionDecoder.ts`. - CLI and MCP/tool-catalog contract: none. No schemas change; `no.` can now appear as an opcode name in `opcode_counts`. - Provider, bridge, target-format, or platform compatibility: method bodies using `no.` are decoded instead of marked malformed. Digests of bodies that already decoded are unchanged. - Evidence, artifact, provenance, or reconstruction contract: none. - Process execution, authorization, cleanup, or containment impact: none. - Generated metadata, package, or installation impact: none. ## Evidence and regression coverage - Tests added or updated: one test in `src/dotnet/ManagedCilDecoding.test.ts` ("managed exception region prefix boundaries"). It checks that the body above decodes, and that a try range starting between `no.` and `ldfld` is refused as misaligned. - Base reproduction or other evidence: executed. With the decoder change reverted the new test fails with `Unsupported CIL opcode 0xfe19 at IL offset 1`. - User-visible CLI/MCP output: not applicable beyond the fields above. - Remaining proof gaps: the IL is a hand-built fixture. Mainstream compilers rarely emit `no.`, and I did not have an assembler-produced binary containing it. For evidence-bearing changes: - [x] Observed, derived, and inferred claims remain distinguishable. - [x] Artifact identity, source provenance, and failed attempts remain preserved. - [x] Unsupported, incomplete, unavailable, or uncertain outcomes remain visible. ## Validation performed - `npx vitest run src/dotnet tests/boundary/dotnet` — 11 files passed - `npm run check` — passed - `npm run verify:test-discovery` — "Discovered all 936 test files exactly once." ## Compatibility, safety, and release - Breaking changes or migration steps: none. - Real Hopper/Ghidra, browser, or OS coverage: Linux x64 only. No provider runs; this path is static parsing. - Package or release metadata impact: none. - Security, privacy, process, or containment review: parsing only; the operand read is bound-checked by the existing decoder path. ## Review checklist - [x] This PR addresses a concrete problem or an agreed enhancement. - [x] The PR has one focused outcome and the title follows `type(scope): outcome`. - [x] Related issue is linked, or the reason for not linking one is stated above. - [x] Tests cover changed observable behavior and meaningful failure paths. - [x] Owning docs, contracts, and generated metadata are updated where needed. - [x] User-visible CLI/MCP changes include representative output. - [x] I checked the final diff for secrets, unrelated cleanup, and unsupported claims. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_012pRGskbPGjT444CgJfuhhj --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-31 01:04:01 +00:00
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#5108
No description provided.