Skip to content

Commit 88fd72d

Browse files
authored
x86: fix near RET decoding with 0x66 and REX.W (#3049)
1 parent aa91e73 commit 88fd72d

2 files changed

Lines changed: 56 additions & 2 deletions

File tree

arch/X86/X86DisassemblerDecoder.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1143,6 +1143,13 @@ static int getID(struct InternalInstruction *insn)
11431143
{
11441144
uint16_t attrMask;
11451145
uint16_t instructionID;
1146+
bool rexWOverridesOpSize;
1147+
1148+
/* REX.W overrides the operand-sized prefix for near RET in 64-bit mode */
1149+
rexWOverridesOpSize = insn->mode == MODE_64BIT && insn->hasOpSize &&
1150+
insn->opcodeType == ONEBYTE &&
1151+
(insn->opcode == 0xC2 || insn->opcode == 0xC3) &&
1152+
(insn->rexPrefix & 0x08);
11461153

11471154
attrMask = ATTR_NONE;
11481155

@@ -1227,7 +1234,8 @@ static int getID(struct InternalInstruction *insn)
12271234
return -1;
12281235
}
12291236
} else {
1230-
if (insn->hasOpSize && insn->mode != MODE_16BIT) {
1237+
if (insn->hasOpSize && insn->mode != MODE_16BIT &&
1238+
!rexWOverridesOpSize) {
12311239
attrMask |= ATTR_OPSIZE;
12321240
}
12331241
if (insn->hasAdSize)
@@ -1380,7 +1388,8 @@ static int getID(struct InternalInstruction *insn)
13801388
return -1;
13811389
}
13821390

1383-
if ((insn->mode == MODE_16BIT || insn->hasOpSize) &&
1391+
if ((insn->mode == MODE_16BIT ||
1392+
(insn->hasOpSize && !rexWOverridesOpSize)) &&
13841393
!(attrMask & ATTR_OPSIZE)) {
13851394
/*
13861395
* The instruction tables make no distinction between instructions that

tests/issues/issues.yaml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6967,3 +6967,48 @@ test_cases:
69676967
mem_disp: 0x100cdc408
69686968
access: CS_AC_READ
69696969
regs_write: [ x8 ]
6970+
-
6971+
input:
6972+
name: "issue 3038 x86-64 RET imm16 with operand-size override and REX.W"
6973+
bytes: [ 0x66, 0x48, 0xc2, 0x3b, 0x01 ]
6974+
arch: "CS_ARCH_X86"
6975+
options: [ CS_MODE_64, CS_OPT_DETAIL ]
6976+
address: 0x0
6977+
expected:
6978+
insns:
6979+
-
6980+
asm_text: "ret 0x13b"
6981+
details:
6982+
x86:
6983+
prefix: [ X86_PREFIX_0, X86_PREFIX_0, X86_PREFIX_OPSIZE, X86_PREFIX_0 ]
6984+
opcode: [ 0xc2, 0x00, 0x00, 0x00 ]
6985+
rex: 0x48
6986+
enc_imm_offset: 0x3
6987+
enc_imm_size: 0x2
6988+
operands:
6989+
-
6990+
type: X86_OP_IMM
6991+
imm: 0x13b
6992+
regs_read: [ rsp, ss ]
6993+
regs_write: [ rsp, rip ]
6994+
groups: [ ret, mode64 ]
6995+
6996+
-
6997+
input:
6998+
name: "issue 3038 x86-64 RET with operand-size override and REX.W"
6999+
bytes: [ 0x66, 0x48, 0xc3 ]
7000+
arch: "CS_ARCH_X86"
7001+
options: [ CS_MODE_64, CS_OPT_DETAIL ]
7002+
address: 0x0
7003+
expected:
7004+
insns:
7005+
-
7006+
asm_text: "ret"
7007+
details:
7008+
x86:
7009+
prefix: [ X86_PREFIX_0, X86_PREFIX_0, X86_PREFIX_OPSIZE, X86_PREFIX_0 ]
7010+
opcode: [ 0xc3, 0x00, 0x00, 0x00 ]
7011+
rex: 0x48
7012+
regs_read: [ rsp, ss ]
7013+
regs_write: [ rsp, rip ]
7014+
groups: [ ret, mode64 ]

0 commit comments

Comments
 (0)