Skip to content

fix: LLIL OperationOperands undercounts (17 ops)#27

Merged
tinysec merged 1 commit into
masterfrom
fix/llil-operand-count-table
Jul 8, 2026
Merged

fix: LLIL OperationOperands undercounts (17 ops)#27
tinysec merged 1 commit into
masterfrom
fix/llil-operand-count-table

Conversation

@tinysec

@tinysec tinysec commented Jul 8, 2026

Copy link
Copy Markdown
Owner

Problem

The OperationOperands count table in Struct/BNLowLevelILInstruction.cs sizes each instruction's RawOperands[] array. 17 entries undercounted their operands, so accessing the affected typed-accessor property threw IndexOutOfRangeException at runtime.

Root cause

Counts verified 1:1 against lowlevelilinstruction.h/.cpp (s_instructionOperandUsage + the per-op LowLevelILInstructionAccessor raw-index calls). Misses by group:

  • SSA register/flag/stack ops omitted the version's second raw slot — ASSERT_SSA, FLAG_BIT_SSA, REG_SSA_PARTIAL, REG_STACK_ABS_SSA, REG_STACK_REL_SSA, SET_REG_SSA_PARTIAL, FORCE_VER_SSA, CALL_STACK_SSA
  • Phi ops omitted the 2-slot dest SSA — FLAG_PHI (1→3), REG_PHI (1→3), REG_STACK_PHI (1→3)
  • Memory-version slots — STORE_SSA (3→4, destMem/srcMem), TAILCALL_SSA (3→4)
  • Two-operand ops — ASSERT (1→2), FLAG_BIT (1→2), FLAG_COND (1→2), INTRINSIC (3→4)

An SSA register/flag/stack occupies two raw slots (value, version). The phi source-list readers route through the native list API rather than RawOperands[], so the count need only cover the directly-indexed slots. No bogus accessors found (verified each C# index maps to a genuine C++ operand).

Same systematic-miscount cluster as HLIL (PR #26); MLIL follows in a separate PR.

Changes

  • Struct/BNLowLevelILInstruction.cs: 17 count bumps, each with an operand-list comment.

Verification

  • dotnet build -c Release clean.
  • Static audit (crash_audit_llil.py): NO OOB after the fix (was 17 OOB).
  • New E2E regression in the harness repo: flat MustGetExpression sweep over cat.bndb LLIL, invokes each declared operand-accessor getter, asserts none throws IndexOutOfRangeException.
  • Full harness regression: 41/41 pass.

The OperationOperands count table in Struct/BNLowLevelILInstruction.cs
sized the per-instruction RawOperands[] array too small for 17 operations,
so accessing the affected typed-accessor property threw
IndexOutOfRangeException at runtime. The undercounts fell into groups:

- SSA register/flag/stack ops omitted the version's second raw slot
  (ASSERT_SSA, FLAG_BIT_SSA, REG_SSA_PARTIAL, REG_STACK_ABS_SSA,
  REG_STACK_REL_SSA, SET_REG_SSA_PARTIAL, FORCE_VER_SSA, CALL_STACK_SSA)
- Phi ops omitted the 2-slot dest SSA (FLAG_PHI, REG_PHI, REG_STACK_PHI)
- Memory-version slots omitted (STORE_SSA destMem/srcMem, TAILCALL_SSA)
- Two-slot operands (ASSERT sourceRegister+constraint, FLAG_BIT/FLAG_COND,
  INTRINSIC output-list+intrinsic+params)

Counts verified 1:1 against lowlevelilinstruction.h/.cpp; an SSA
register/flag/stack occupies two raw slots (value, version), and the phi
source-list readers route through the native list API so the count need
only cover the directly-indexed slots. No bogus accessors found.
@tinysec tinysec merged commit 8d7a31e into master Jul 8, 2026
1 check passed
@tinysec tinysec deleted the fix/llil-operand-count-table branch July 8, 2026 07:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant