Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 40 additions & 8 deletions arch/X86/X86DisassemblerDecoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -523,20 +523,52 @@ static int readPrefixes(struct InternalInstruction *insn)
case 0x65: /* GS segment override */
switch (byte) {
case 0x2e:
insn->segmentOverride = SEG_OVERRIDE_CS;
insn->prefix1 = byte;
if (insn->mode != MODE_64BIT ||
(insn->prefix1 != 0x64 &&
insn->prefix1 != 0x65)) {
if (insn->mode != MODE_64BIT) {
insn->segmentOverride =
SEG_OVERRIDE_CS;
}

insn->prefix1 = byte;
}
break;
case 0x36:
insn->segmentOverride = SEG_OVERRIDE_SS;
insn->prefix1 = byte;
if (insn->mode != MODE_64BIT ||
(insn->prefix1 != 0x64 &&
insn->prefix1 != 0x65)) {
if (insn->mode != MODE_64BIT) {
insn->segmentOverride =
SEG_OVERRIDE_SS;
}

insn->prefix1 = byte;
}
break;
case 0x3e:
insn->segmentOverride = SEG_OVERRIDE_DS;
insn->prefix1 = byte;
if (insn->mode != MODE_64BIT ||
(insn->prefix1 != 0x64 &&
insn->prefix1 != 0x65)) {
if (insn->mode != MODE_64BIT) {
insn->segmentOverride =
SEG_OVERRIDE_DS;
}

insn->prefix1 = byte;
}
break;
case 0x26:
insn->segmentOverride = SEG_OVERRIDE_ES;
insn->prefix1 = byte;
if (insn->mode != MODE_64BIT ||
(insn->prefix1 != 0x64 &&
insn->prefix1 != 0x65)) {
if (insn->mode != MODE_64BIT) {
insn->segmentOverride =
SEG_OVERRIDE_ES;
}

insn->prefix1 = byte;
}
break;
case 0x64:
insn->segmentOverride = SEG_OVERRIDE_FS;
Expand Down
293 changes: 293 additions & 0 deletions tests/issues/x86-prefixes.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,293 @@
test_cases:
# Test segment override priority
-
input:
name: "x86-16: rightmost segment override should take priority"
bytes: [ 0x26, 0x65, 0x64, 0x3E, 0x65, 0x2E, 0x00, 0x00 ]
arch: "CS_ARCH_X86"
options: [ CS_OPT_DETAIL, CS_MODE_16 ]
expected:
insns:
-
asm_text: "add byte ptr cs:[bx + si], al"
details:
x86:
prefix: [ X86_PREFIX_0, X86_PREFIX_CS, X86_PREFIX_0, X86_PREFIX_0 ]
-
input:
name: "x86-32: rightmost segment override should take priority"
bytes: [ 0x26, 0x65, 0x64, 0x3E, 0x65, 0x2E, 0x00, 0x00 ]
arch: "CS_ARCH_X86"
options: [ CS_OPT_DETAIL, CS_MODE_32 ]
expected:
insns:
-
asm_text: "add byte ptr cs:[eax], al"
details:
x86:
prefix: [ X86_PREFIX_0, X86_PREFIX_CS, X86_PREFIX_0, X86_PREFIX_0 ]
-
input:
name: "x86-64: rightmost segment override should take priority"
bytes: [ 0x26, 0x65, 0x64, 0x3E, 0x65, 0x2E, 0x00, 0x00 ]
arch: "CS_ARCH_X86"
options: [ CS_OPT_DETAIL, CS_MODE_64 ]
expected:
insns:
-
asm_text: "add byte ptr gs:[rax], al"
details:
x86:
prefix: [ X86_PREFIX_0, X86_PREFIX_GS, X86_PREFIX_0, X86_PREFIX_0 ]
-
input:
name: "x86-16: rightmost segment override should take priority"
bytes: [ 0x3E, 0x3E, 0x26, 0x36, 0x64, 0x36, 0x00, 0x00 ]
arch: "CS_ARCH_X86"
options: [ CS_OPT_DETAIL, CS_MODE_16 ]
expected:
insns:
-
asm_text: "add byte ptr ss:[bx + si], al"
details:
x86:
prefix: [ X86_PREFIX_0, X86_PREFIX_SS, X86_PREFIX_0, X86_PREFIX_0 ]
-
input:
name: "x86-32: rightmost segment override should take priority"
bytes: [ 0x3E, 0x3E, 0x26, 0x36, 0x64, 0x36, 0x00, 0x00 ]
arch: "CS_ARCH_X86"
options: [ CS_OPT_DETAIL, CS_MODE_32 ]
expected:
insns:
-
asm_text: "add byte ptr ss:[eax], al"
details:
x86:
prefix: [ X86_PREFIX_0, X86_PREFIX_SS, X86_PREFIX_0, X86_PREFIX_0 ]
-
input:
name: "x86-64: rightmost segment override should take priority"
bytes: [ 0x3E, 0x3E, 0x26, 0x36, 0x64, 0x36, 0x00, 0x00 ]
arch: "CS_ARCH_X86"
options: [ CS_OPT_DETAIL, CS_MODE_64 ]
expected:
insns:
-
asm_text: "add byte ptr fs:[rax], al"
details:
x86:
prefix: [ X86_PREFIX_0, X86_PREFIX_FS, X86_PREFIX_0, X86_PREFIX_0 ]
# Test segment override differences between 16/32 and 64-bit mode with ECDS and FS/GS
-
input:
name: "x86-16: ECSD segment overrides should override FS/GS segment overrides"
bytes: [ 0x64, 0x3E, 0x00, 0x00 ]
arch: "CS_ARCH_X86"
options: [ CS_OPT_DETAIL, CS_MODE_16 ]
expected:
insns:
-
asm_text: "add byte ptr ds:[bx + si], al"
details:
x86:
prefix: [ X86_PREFIX_0, X86_PREFIX_DS, X86_PREFIX_0, X86_PREFIX_0 ]
-
input:
name: "x86-32: ECSD segment overrides should override FS/GS segment overrides"
bytes: [ 0x64, 0x3E, 0x00, 0x00 ]
arch: "CS_ARCH_X86"
options: [ CS_OPT_DETAIL, CS_MODE_32 ]
expected:
insns:
-
asm_text: "add byte ptr ds:[eax], al"
details:
x86:
prefix: [ X86_PREFIX_0, X86_PREFIX_DS, X86_PREFIX_0, X86_PREFIX_0 ]
-
input:
name: "x86-64: ECSD segment overrides should be ignored and leave FS override intact"
bytes: [ 0x64, 0x3E, 0x00, 0x00 ]
arch: "CS_ARCH_X86"
options: [ CS_OPT_DETAIL, CS_MODE_64 ]
expected:
insns:
-
asm_text: "add byte ptr fs:[rax], al"
details:
x86:
prefix: [ X86_PREFIX_0, X86_PREFIX_FS, X86_PREFIX_0, X86_PREFIX_0 ]
-
input:
name: "x86-64: ECSD segment overrides should be ignored"
bytes: [ 0x3E, 0x00, 0x00 ]
arch: "CS_ARCH_X86"
options: [ CS_OPT_DETAIL, CS_MODE_64 ]
expected:
insns:
-
asm_text: "add byte ptr [rax], al"
details:
x86:
prefix: [ X86_PREFIX_0, X86_PREFIX_DS, X86_PREFIX_0, X86_PREFIX_0 ]
# Test duplicate segment override prefixes
-
input:
name: "x86-16: Duplicate ES override prefixes should decode successfully"
bytes: [ 0x26, 0x26, 0x00, 0x00 ]
arch: "CS_ARCH_X86"
options: [ CS_OPT_DETAIL, CS_MODE_16 ]
expected:
insns:
-
asm_text: "add byte ptr es:[bx + si], al"
details:
x86:
prefix: [ X86_PREFIX_0, X86_PREFIX_ES, X86_PREFIX_0, X86_PREFIX_0 ]
-
input:
name: "x86-32: Duplicate ES override prefixes should decode successfully"
bytes: [ 0x26, 0x26, 0x00, 0x00 ]
arch: "CS_ARCH_X86"
options: [ CS_OPT_DETAIL, CS_MODE_32 ]
expected:
insns:
-
asm_text: "add byte ptr es:[eax], al"
details:
x86:
prefix: [ X86_PREFIX_0, X86_PREFIX_ES, X86_PREFIX_0, X86_PREFIX_0 ]
-
input:
name: "x86-64: Duplicate FS override prefixes should decode successfully"
bytes: [ 0x64, 0x64, 0x00, 0x00 ]
arch: "CS_ARCH_X86"
options: [ CS_OPT_DETAIL, CS_MODE_64 ]
expected:
insns:
-
asm_text: "add byte ptr fs:[rax], al"
details:
x86:
prefix: [ X86_PREFIX_0, X86_PREFIX_FS, X86_PREFIX_0, X86_PREFIX_0 ]
# Test invalid REX prefix
-
input:
name: "x86-64: Invalid REX prefix should preserve previous segment override"
bytes: [ 0x64, 0x40, 0x2E, 0x00, 0x00 ]
arch: "CS_ARCH_X86"
options: [ CS_OPT_DETAIL, CS_MODE_64 ]
expected:
insns:
-
asm_text: "add byte ptr fs:[rax], al"
details:
x86:
prefix: [ X86_PREFIX_0, X86_PREFIX_FS, X86_PREFIX_0, X86_PREFIX_0 ]
-
input:
name: "x86-64: Invalid REX prefix should not add ECDS segment override"
bytes: [ 0x2E, 0x40, 0x2E, 0x00, 0x00 ]
arch: "CS_ARCH_X86"
options: [ CS_OPT_DETAIL, CS_MODE_64 ]
expected:
insns:
-
asm_text: "add byte ptr [rax], al"
details:
x86:
prefix: [ X86_PREFIX_0, X86_PREFIX_CS, X86_PREFIX_0, X86_PREFIX_0 ]
# Test whether `notrack` is correctly decoded
-
input:
name: "x86-16: notrack should decode correctly"
bytes: [ 0x3E, 0xE8, 0x00, 0x00 ]
arch: "CS_ARCH_X86"
options: [ CS_OPT_DETAIL, CS_MODE_16 ]
expected:
insns:
-
asm_text: "notrack call 4"
details:
x86:
prefix: [ X86_PREFIX_0, X86_PREFIX_DS, X86_PREFIX_0, X86_PREFIX_0 ]
-
input:
name: "x86-32: notrack should decode correctly"
bytes: [ 0x3E, 0xE8, 0x00, 0x00, 0x00, 0x00 ]
arch: "CS_ARCH_X86"
options: [ CS_OPT_DETAIL, CS_MODE_32 ]
expected:
insns:
-
asm_text: "notrack call 6"
details:
x86:
prefix: [ X86_PREFIX_0, X86_PREFIX_DS, X86_PREFIX_0, X86_PREFIX_0 ]
-
input:
name: "x86-64: notrack should decode correctly"
bytes: [ 0x3E, 0xE8, 0x00, 0x00, 0x00, 0x00 ]
arch: "CS_ARCH_X86"
options: [ CS_OPT_DETAIL, CS_MODE_64 ]
expected:
insns:
-
asm_text: "notrack call 6"
details:
x86:
prefix: [ X86_PREFIX_0, X86_PREFIX_DS, X86_PREFIX_0, X86_PREFIX_0 ]

-
input:
name: "x86-16: notrack should be applied when 0x3E is last segment override prefix"
bytes: [ 0x26, 0x64, 0x3E, 0xE8, 0x00, 0x00 ]
arch: "CS_ARCH_X86"
options: [ CS_OPT_DETAIL, CS_MODE_16 ]
expected:
insns:
-
asm_text: "notrack call 6"
details:
x86:
prefix: [ X86_PREFIX_0, X86_PREFIX_DS, X86_PREFIX_0, X86_PREFIX_0 ]
-
input:
name: "x86-32: notrack should be applied when 0x3E is last segment override prefix"
bytes: [ 0x26, 0x64, 0x3E, 0xE8, 0x00, 0x00, 0x00, 0x00 ]
arch: "CS_ARCH_X86"
options: [ CS_OPT_DETAIL, CS_MODE_32 ]
expected:
insns:
-
asm_text: "notrack call 8"
details:
x86:
prefix: [ X86_PREFIX_0, X86_PREFIX_DS, X86_PREFIX_0, X86_PREFIX_0 ]
-
input:
name: "x86-64: workaround: notrack should only be applied when 0x3E is last segment override prefix and no FS/GS segment override prefix is active"
bytes: [ 0x26, 0x64, 0x3E, 0xE8, 0x00, 0x00, 0x00, 0x00 ]
arch: "CS_ARCH_X86"
options: [ CS_OPT_DETAIL, CS_MODE_64 ]
expected:
insns:
-
asm_text: "call 8"
details:
x86:
prefix: [ X86_PREFIX_0, X86_PREFIX_FS, X86_PREFIX_0, X86_PREFIX_0 ]
-
input:
name: "x86-64: workaround: notrack should only be applied when 0x3E is last segment override prefix and no FS/GS segment override prefix is active"
bytes: [ 0x26, 0x2E, 0x3E, 0xE8, 0x00, 0x00, 0x00, 0x00 ]
arch: "CS_ARCH_X86"
options: [ CS_OPT_DETAIL, CS_MODE_64 ]
expected:
insns:
-
asm_text: "notrack call 8"
details:
x86:
prefix: [ X86_PREFIX_0, X86_PREFIX_DS, X86_PREFIX_0, X86_PREFIX_0 ]
Loading