Skip to content

InstructionEncoder produces corrupted IL when mixing OpCode with direct CodeBuilder writes across BlobBuilder chunk boundaries #127261

Description

@jkoritzinsky

Description

InstructionEncoder produces corrupted IL bodies when its CodeBuilder (BlobBuilder) crosses chunk boundaries (default 256 bytes). The corruption occurs when mixing InstructionEncoder.OpCode() with direct CodeBuilder.WriteByte() / CodeBuilder.WriteInt32() calls for instruction operands.

This is the expected usage pattern for instructions like ldarg.s where OpCode(ILOpCode.Ldarg_s) emits the opcode and CodeBuilder.WriteByte(index) emits the operand — there is no dedicated InstructionEncoder API for these operands.

Impact

Any consumer of InstructionEncoder that writes operand bytes directly to CodeBuilder (rather than using high-level APIs like Branch, LoadString, Token) will produce corrupted IL when the method body exceeds 256 bytes.

Workaround

Use new BlobBuilder(capacity) with a capacity larger than the expected IL body size to avoid multi-chunk operation:

var codeBuilder = new BlobBuilder(4096); // avoid 256-byte chunk boundary
var il = new InstructionEncoder(codeBuilder, new ControlFlowBuilder());

Reproduction

See the standalone repro in the comment below. Reproduces on .NET 9 and .NET 11.

Note

This issue was created with the assistance of Copilot.

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions