From d99df1eb2f8d1cf13a46419d756c69bf3974b13b Mon Sep 17 00:00:00 2001 From: bibi samina Date: Sun, 5 Jul 2026 19:19:52 +0530 Subject: [PATCH] fix swapped isIntN arguments in xtensa decodeOffset_16_16Operand --- arch/Xtensa/XtensaDisassembler.c | 2 +- tests/integration/test_poc.c | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/arch/Xtensa/XtensaDisassembler.c b/arch/Xtensa/XtensaDisassembler.c index 2c1e117f53..1f2c6d9fd7 100644 --- a/arch/Xtensa/XtensaDisassembler.c +++ b/arch/Xtensa/XtensaDisassembler.c @@ -788,7 +788,7 @@ static DecodeStatus decodeOffset_16_16Operand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { - CS_ASSERT_RET_VAL(isIntN(Imm, 8) && "Invalid immediate", + CS_ASSERT_RET_VAL(isIntN(8, Imm) && "Invalid immediate", MCDisassembler_Fail); if ((Imm & 0xf) != 0) MCOperand_CreateImm0(Inst, (Imm << 4)); diff --git a/tests/integration/test_poc.c b/tests/integration/test_poc.c index f461de4f47..6ba1ad98a7 100644 --- a/tests/integration/test_poc.c +++ b/tests/integration/test_poc.c @@ -130,12 +130,36 @@ static void test_ub_shift_sh_dsp_p(void) return; } +/// Swapped isIntN() arguments in Xtensa decodeOffset_16_16Operand. The +/// decoded immediate was passed as the bit width, so isIntN(Imm, 8) +/// shifted by Imm - 1. Small Imm values make Imm - 1 wrap to a huge +/// unsigned shift count and the signed shift/negation is UB. +static void test_ub_isintn_xtensa_offset(void) +{ + static const uint8_t code[] = { + 0x07, 0x75, 0x5d, 0xce, 0x50, 0x2b, 0x87 + }; + + csh handle; + if (cs_open(CS_ARCH_XTENSA, CS_MODE_LITTLE_ENDIAN, &handle) != + CS_ERR_OK) + return; + cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON); + + cs_insn *insn = NULL; + size_t count = cs_disasm(handle, code, sizeof(code), 0x1000, 0, &insn); + cs_free(insn, count); + cs_close(&handle); + return; +} + int main() { test_overflow_cs_insn_bytes(); test_overflow_cs_insn_bytes_iter(); test_overflow_set_reg_mem_n(); test_ub_shift_sh_dsp_p(); + test_ub_isintn_xtensa_offset(); return 0; }