From a546e275a825478493dbde6881d13be0615a698d Mon Sep 17 00:00:00 2001 From: tinysec Date: Wed, 8 Jul 2026 15:25:19 +0800 Subject: [PATCH] fix: HLIL OperationOperands undercounts + ROR bogus Carry (#26) The OperationOperands count table in Struct/BNHighLevelILInstruction.cs sized the per-instruction RawOperands[] array too small for 21 operations, so accessing the affected typed-accessor properties threw IndexOutOfRangeException at runtime. The undercounts fell into groups: - TwoOperandWithCarry ops (ADC/SBB/RLC/RRC) omitted the carry operand (2->3) - SSA stores omitted the dest memory-version slot (VAR_INIT_SSA, ASSIGN_MEM_SSA, ASSIGN_UNPACK_MEM_SSA, CALL_SSA, INTRINSIC_SSA, SYSCALL_SSA) - SSAVariable-occupying ops omitted the version's second raw slot (FORCE_VER_SSA, ASSERT_SSA, VAR_PHI) - Phi/control ops omitted loop and phi operands (MEM_PHI, WHILE_SSA, DO_WHILE_SSA, FOR_SSA, CASE, ASSIGN_UNPACK) - Plain non-SSA force/assert omitted their second operand (FORCE_VER, ASSERT) HLIL_ROR additionally exposed a bogus Carry property that read operands[2] past its two operands -- C++ ROR is TwoOperandInstruction (no carry; only ADC/SBB/RLC/RRC are TwoOperandWithCarry). Removed. Counts verified 1:1 against binaryninja-api/highlevelilinstruction.h raw operand layouts; SSAVariable occupies two raw slots (variable, version). --- HighLevelIL/HLILRotateRight.cs | 8 ------ Struct/BNHighLevelILInstruction.cs | 42 +++++++++++++++--------------- 2 files changed, 21 insertions(+), 29 deletions(-) diff --git a/HighLevelIL/HLILRotateRight.cs b/HighLevelIL/HLILRotateRight.cs index 69623ca..e0b106c 100644 --- a/HighLevelIL/HLILRotateRight.cs +++ b/HighLevelIL/HLILRotateRight.cs @@ -26,13 +26,5 @@ public HighLevelILInstruction Right return this.GetOperandAsExpression((OperandIndex)1); } } - - public HighLevelILInstruction Carry - { - get - { - return this.GetOperandAsExpression((OperandIndex)2); - } - } } } diff --git a/Struct/BNHighLevelILInstruction.cs b/Struct/BNHighLevelILInstruction.cs index 60c91b0..5d87ef1 100644 --- a/Struct/BNHighLevelILInstruction.cs +++ b/Struct/BNHighLevelILInstruction.cs @@ -77,7 +77,7 @@ public abstract class HighLevelILInstruction : { HighLevelILOperation.HLIL_DO_WHILE, 2 }, // body, cond { HighLevelILOperation.HLIL_FOR, 4 }, // init, cond, update, body { HighLevelILOperation.HLIL_SWITCH, 3 }, // expr, caseList, default - { HighLevelILOperation.HLIL_CASE, 2 }, // valueList, body + { HighLevelILOperation.HLIL_CASE, 3 }, // valueExprs(list), trueExpr { HighLevelILOperation.HLIL_BREAK, 0 }, { HighLevelILOperation.HLIL_CONTINUE, 0 }, { HighLevelILOperation.HLIL_JUMP, 1 }, // dest @@ -89,9 +89,9 @@ public abstract class HighLevelILInstruction : { HighLevelILOperation.HLIL_VAR_DECLARE, 1 }, // var { HighLevelILOperation.HLIL_VAR_INIT, 2 }, // var, value { HighLevelILOperation.HLIL_ASSIGN, 2 }, // dst, src - { HighLevelILOperation.HLIL_ASSIGN_UNPACK, 2 }, // dstList, src - { HighLevelILOperation.HLIL_FORCE_VER, 1 }, // var - { HighLevelILOperation.HLIL_ASSERT, 1 }, // cond + { HighLevelILOperation.HLIL_ASSIGN_UNPACK, 3 }, // destExprs(list), sourceExpr + { HighLevelILOperation.HLIL_FORCE_VER, 2 }, // destVariable, variable + { HighLevelILOperation.HLIL_ASSERT, 2 }, // variable, constraint { HighLevelILOperation.HLIL_VAR, 1 }, // var { HighLevelILOperation.HLIL_STRUCT_FIELD, 3 }, // base, fieldOffset, memberIndex @@ -109,9 +109,9 @@ public abstract class HighLevelILInstruction : { HighLevelILOperation.HLIL_IMPORT, 1 }, // symbol/id { HighLevelILOperation.HLIL_ADD, 2 }, - { HighLevelILOperation.HLIL_ADC, 2 }, + { HighLevelILOperation.HLIL_ADC, 3 }, // left, right, carry { HighLevelILOperation.HLIL_SUB, 2 }, - { HighLevelILOperation.HLIL_SBB, 2 }, + { HighLevelILOperation.HLIL_SBB, 3 }, // left, right, carry { HighLevelILOperation.HLIL_AND, 2 }, { HighLevelILOperation.HLIL_OR, 2 }, { HighLevelILOperation.HLIL_XOR, 2 }, @@ -119,9 +119,9 @@ public abstract class HighLevelILInstruction : { HighLevelILOperation.HLIL_LSR, 2 }, { HighLevelILOperation.HLIL_ASR, 2 }, { HighLevelILOperation.HLIL_ROL, 2 }, - { HighLevelILOperation.HLIL_RLC, 2 }, + { HighLevelILOperation.HLIL_RLC, 3 }, // left, right, carry { HighLevelILOperation.HLIL_ROR, 2 }, - { HighLevelILOperation.HLIL_RRC, 2 }, + { HighLevelILOperation.HLIL_RRC, 3 }, // left, right, carry { HighLevelILOperation.HLIL_MUL, 2 }, { HighLevelILOperation.HLIL_MULU_DP, 2 }, { HighLevelILOperation.HLIL_MULS_DP, 2 }, @@ -189,26 +189,26 @@ public abstract class HighLevelILInstruction : { HighLevelILOperation.HLIL_UNREACHABLE, 0 }, - { HighLevelILOperation.HLIL_WHILE_SSA, 2 }, // cond, body - { HighLevelILOperation.HLIL_DO_WHILE_SSA, 2 }, // body, cond - { HighLevelILOperation.HLIL_FOR_SSA, 4 }, // init, cond, update, body - { HighLevelILOperation.HLIL_VAR_INIT_SSA, 2 }, // var(versioned), value - { HighLevelILOperation.HLIL_ASSIGN_MEM_SSA, 3 }, // dst(addr), src, dstMem - { HighLevelILOperation.HLIL_ASSIGN_UNPACK_MEM_SSA, 3 }, // dstList, src, dstMem - { HighLevelILOperation.HLIL_FORCE_VER_SSA, 2 }, // var, newVersion - { HighLevelILOperation.HLIL_ASSERT_SSA, 2 }, // cond, mem/reg ver + { HighLevelILOperation.HLIL_WHILE_SSA, 3 }, // conditionPhi, condition, loop + { HighLevelILOperation.HLIL_DO_WHILE_SSA, 3 }, // loop, conditionPhi, condition + { HighLevelILOperation.HLIL_FOR_SSA, 5 }, // init, conditionPhi, condition, update, loop + { HighLevelILOperation.HLIL_VAR_INIT_SSA, 3 }, // destSSAVariable(var,version), sourceExpr + { HighLevelILOperation.HLIL_ASSIGN_MEM_SSA, 4 }, // dest, destMem, source, srcMem + { HighLevelILOperation.HLIL_ASSIGN_UNPACK_MEM_SSA, 5 }, // destExprs(list), [reserved], destMem, source, srcMem + { HighLevelILOperation.HLIL_FORCE_VER_SSA, 4 }, // destSSAVariable(var,version), ssaVariable(var,version) + { HighLevelILOperation.HLIL_ASSERT_SSA, 3 }, // ssaVariable(var,version), constraint { HighLevelILOperation.HLIL_VAR_SSA, 2 }, // var, version { HighLevelILOperation.HLIL_ARRAY_INDEX_SSA, 3 }, // base, index, srcMem { HighLevelILOperation.HLIL_DEREF_SSA, 2 }, // addr, srcMem { HighLevelILOperation.HLIL_DEREF_FIELD_SSA, 4 }, // addr, srcMem, fieldOffset, memberIndex - { HighLevelILOperation.HLIL_CALL_SSA, 4 }, // dest, params(list), outputs(list), srcMem - { HighLevelILOperation.HLIL_SYSCALL_SSA, 3 }, // params(list), outputs(list), srcMem - { HighLevelILOperation.HLIL_INTRINSIC_SSA, 4 }, // intrinsicId, params(list), outputs(list), srcMem + { HighLevelILOperation.HLIL_CALL_SSA, 5 }, // dest, params(list), [reserved], destMem, srcMem + { HighLevelILOperation.HLIL_SYSCALL_SSA, 4 }, // params(list), [reserved], destMem, srcMem + { HighLevelILOperation.HLIL_INTRINSIC_SSA, 5 }, // intrinsic, params(list), [reserved], destMem, srcMem - { HighLevelILOperation.HLIL_VAR_PHI, 1 }, // varVersions(list) - { HighLevelILOperation.HLIL_MEM_PHI, 1 }, // memVersions(list) + { HighLevelILOperation.HLIL_VAR_PHI, 3 }, // destSSAVariable(var,version), sourceSSAVariableList + { HighLevelILOperation.HLIL_MEM_PHI, 2 }, // destMemoryVersion, sourceMemoryVersions(list) { HighLevelILOperation.HLIL_ABS, 1 }, // src { HighLevelILOperation.HLIL_BSWAP, 1 }, // src