From cc4f73f89bc8996cd8f26667a6856d81977c173d Mon Sep 17 00:00:00 2001 From: bibi samina Date: Tue, 7 Jul 2026 12:19:26 +0530 Subject: [PATCH 1/2] mips: fix left shift of negative value in DecodeMemMMReglistImm4Lsl2 --- arch/Mips/MipsDisassembler.c | 2 +- tests/integration/test_poc.c | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/arch/Mips/MipsDisassembler.c b/arch/Mips/MipsDisassembler.c index e9d4f06a54..953a9302a2 100644 --- a/arch/Mips/MipsDisassembler.c +++ b/arch/Mips/MipsDisassembler.c @@ -2429,7 +2429,7 @@ static DecodeStatus DecodeMemMMReglistImm4Lsl2(MCInst *Inst, uint32_t Insn, return MCDisassembler_Fail; MCOperand_CreateReg0(Inst, (Mips_SP)); - MCOperand_CreateImm0(Inst, (Offset << 2)); + MCOperand_CreateImm0(Inst, (Offset * 4)); return MCDisassembler_Success; } diff --git a/tests/integration/test_poc.c b/tests/integration/test_poc.c index f461de4f47..ba306686be 100644 --- a/tests/integration/test_poc.c +++ b/tests/integration/test_poc.c @@ -130,12 +130,35 @@ static void test_ub_shift_sh_dsp_p(void) return; } +/// Signed left shift of a negative value when decoding a microMIPS +/// LWM16/SWM16 offset. The 4-bit field is sign-extended to a negative int +/// and then shifted left by 2, which is UB whenever the field's top bit +/// is set (offset field >= 8). +static void test_ub_shift_mips_mm_reglist(void) +{ + static const uint8_t code[] = { 0x45, 0x08 }; + + csh handle; + if (cs_open(CS_ARCH_MIPS, + CS_MODE_MICRO | CS_MODE_MIPS32 | CS_MODE_BIG_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_shift_mips_mm_reglist(); return 0; } From 00c9c4d6485369af7e6bdca04724573c7b32deed Mon Sep 17 00:00:00 2001 From: bibi samina Date: Wed, 8 Jul 2026 10:12:11 +0530 Subject: [PATCH 2/2] mips: zero-extend microMIPS LWM16/SWM16 reglist offset The ISA defines the offset as zero_extend(offset||0^2), but the non-MMR6 path sign-extended the 4-bit field before the << 2. That both triggered a left-shift-of-negative-value UB (field top bit set) and produced a wrong negative offset. Zero-extend the field to match the ISA and the MMR6 path; the shift is now UB-free. Signed-off-by: bibi samina --- arch/Mips/MipsDisassembler.c | 4 ++-- tests/integration/test_poc.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/Mips/MipsDisassembler.c b/arch/Mips/MipsDisassembler.c index 953a9302a2..efd2faf386 100644 --- a/arch/Mips/MipsDisassembler.c +++ b/arch/Mips/MipsDisassembler.c @@ -2420,7 +2420,7 @@ static DecodeStatus DecodeMemMMReglistImm4Lsl2(MCInst *Inst, uint32_t Insn, Offset = fieldFromInstruction_4(Insn, 4, 4); break; default: - Offset = SignExtend32((Insn & 0xf), 4); + Offset = (Insn & 0xf); break; } @@ -2429,7 +2429,7 @@ static DecodeStatus DecodeMemMMReglistImm4Lsl2(MCInst *Inst, uint32_t Insn, return MCDisassembler_Fail; MCOperand_CreateReg0(Inst, (Mips_SP)); - MCOperand_CreateImm0(Inst, (Offset * 4)); + MCOperand_CreateImm0(Inst, (Offset << 2)); return MCDisassembler_Success; } diff --git a/tests/integration/test_poc.c b/tests/integration/test_poc.c index ba306686be..51472d7c3b 100644 --- a/tests/integration/test_poc.c +++ b/tests/integration/test_poc.c @@ -131,9 +131,9 @@ static void test_ub_shift_sh_dsp_p(void) } /// Signed left shift of a negative value when decoding a microMIPS -/// LWM16/SWM16 offset. The 4-bit field is sign-extended to a negative int -/// and then shifted left by 2, which is UB whenever the field's top bit -/// is set (offset field >= 8). +/// LWM16/SWM16 offset. The ISA defines the offset as zero_extend(offset||0^2), +/// but the 4-bit field was sign-extended to a negative int and then shifted +/// left by 2, which is UB whenever the field's top bit is set (field >= 8). static void test_ub_shift_mips_mm_reglist(void) { static const uint8_t code[] = { 0x45, 0x08 };