fix: MLIL OperationOperands undercounts (27 ops) + bogus VAR_PHI.SourceMemory#28
Merged
Merged
Conversation
…ceMemory (#28) The OperationOperands count table in Struct/BNMediumLevelILInstruction.cs sized the per-instruction RawOperands[] array too small for 27 operations, so accessing the affected typed-accessor property threw IndexOutOfRange. Groups: TwoOperandWithCarry (ADC/SBB/RLC/RRC 2->3); SSA stores missing memory-version slots (CALL_SSA, SYSCALL_SSA, TAILCALL_SSA, STORE_SSA, SET_VAR_*_SSA, MEMORY_INTRINSIC_SSA); SSAVariable second-slot (FORCE_VER_SSA, SET_VAR_SSA, FREE_VAR_SLOT_SSA, VAR_SPLIT_SSA); phi/partial (MEM_PHI, VAR_PHI, SET_VAR_ALIASED*, VAR_ALIASED*); carry (ASSERT 1->2); FORCE_VER 1->2. Also removed the bogus MLIL_VAR_PHI.SourceMemory property: it read RawOperands[1] (the dest SSA version slot) and mislabeled it as memory -- C++ MLIL_VAR_PHI has no source-memory operand (only MEM_PHI does). Counts verified 1:1 against mediumlevelilinstruction.h raw layouts (C# GetOperandAs index == C++ GetRawOperandAs index; SSAVariable = 2 slots). The 3 non-SSA untyped variants (CALL_UNTYPED/SYSCALL_UNTYPED/TAILCALL_UNTYPED) are deferred: their non-SSA output is a 2-slot expr_list (no non-SSA MLIL_CALL_OUTPUT op exists), so their accessors are off-by-one, not merely undercounted -- a follow-up accessor PR will address them.
This was referenced Jul 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The
OperationOperandscount table inStruct/BNMediumLevelILInstruction.cssizes each instruction'sRawOperands[]array. 27 entries undercounted their operands, so accessing the affected typed-accessor property threwIndexOutOfRangeException.Also:
MLIL_VAR_PHI.SourceMemorywas a bogus property that readRawOperands[1](the dest SSA version slot) and mislabeled it as memory — C++MLIL_VAR_PHIhas no source-memory operand (onlyMEM_PHIdoes).Root cause
Counts verified 1:1 against
mediumlevelilinstruction.hraw layouts (C# GetOperandAs index == C++ GetRawOperandAs index; SSAVariable = 2 slots). Misses by group:2→31→2, FORCE_VER1→2Completes the OperationOperands cluster (HLIL was PR #26, LLIL was PR #27).
Deferred (separate follow-up PRs)
CALL_UNTYPED/SYSCALL_UNTYPED/TAILCALL_UNTYPED): their non-SSAoutputis a 2-slotexpr_list(no non-SSAMLIL_CALL_OUTPUTop exists), so their accessors are off-by-one, not merely undercounted. Needs accessor surgery (wrapper→direct-list); left crashing rather than silently returning shifted data.MLIL_JUMP_TO.Targetsindex-map reader:GetOperandAsIntegerMapwrongly callsBNMediumLevelILGetOperandList(the expr-list reader); C++ usesGetRawOperandAsIndexMap(operands[count@1, offset@2]). Returns a malformed array → OOB. Separate gap (missing index-map native accessor).Changes
Struct/BNMediumLevelILInstruction.cs: 27 count bumps, each with an operand-list comment.MediumLevelIL/MLILVariablePhi.cs: removed bogusSourceMemory.Verification
dotnet build -c Releaseclean.crash_audit_mlil.py): the 27 fixed ops now clear; only the 3 deferred untyped variants remain (tracked).MustGetExpressionsweep overcat.bndbMLIL, invokes each declared operand-accessor getter (index-map getters excluded as a separate gap), asserts none throwsIndexOutOfRangeException.