Skip to content

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

@jkoritzinsky

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
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions