aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2021-07-03 15:51:22 -0700
committeriximeow <me@iximeow.net>2021-07-03 15:51:22 -0700
commit7e154da8e2bd7b8892bdefe2f71c111c2135b0a3 (patch)
treeb1b945803f37c48a7dd7e5a23e0656ee1d9c83b9
parent582c4e44579d4bbb9dcec9d12c23c8b774db3cfb (diff)
be more strict about denying invalid operands
-rw-r--r--src/long_mode/mod.rs2
-rw-r--r--src/long_mode/vex.rs6
-rw-r--r--src/protected_mode/mod.rs2
-rw-r--r--src/protected_mode/vex.rs6
-rw-r--r--src/shared/evex.in96
-rw-r--r--test/long_mode/mod.rs8
-rw-r--r--test/long_mode/reuse_test.rs9
-rw-r--r--test/protected_mode/mod.rs2
8 files changed, 102 insertions, 29 deletions
diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs
index f8704c0..f2b2b57 100644
--- a/src/long_mode/mod.rs
+++ b/src/long_mode/mod.rs
@@ -6943,7 +6943,7 @@ fn read_0f38_opcode(opcode: u8, prefixes: &mut Prefixes) -> OpcodeRecord {
fn read_0f3a_opcode(opcode: u8, prefixes: &mut Prefixes) -> OpcodeRecord {
if prefixes.rep() {
- if prefixes.operand_size() || prefixes.repnz() {
+ if prefixes != &Prefixes::new(0x10) {
return OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing);
}
return match opcode {
diff --git a/src/long_mode/vex.rs b/src/long_mode/vex.rs
index 7f8252f..d69a411 100644
--- a/src/long_mode/vex.rs
+++ b/src/long_mode/vex.rs
@@ -1599,7 +1599,11 @@ fn read_vex_instruction<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch a
} else {
VEXOperandCode::G_V_E_xmm
}),
- 0x16 => (Opcode::VMOVHPD, VEXOperandCode::G_V_M_xmm),
+ 0x16 => (Opcode::VMOVHPD, if L {
+ return Err(DecodeError::InvalidOpcode);
+ } else {
+ VEXOperandCode::G_V_M_xmm
+ }),
0x17 => (Opcode::VMOVHPD, if L {
instruction.opcode = Opcode::Invalid;
return Err(DecodeError::InvalidOpcode);
diff --git a/src/protected_mode/mod.rs b/src/protected_mode/mod.rs
index c9ba9f2..589d7a3 100644
--- a/src/protected_mode/mod.rs
+++ b/src/protected_mode/mod.rs
@@ -6868,7 +6868,7 @@ fn read_0f38_opcode(opcode: u8, prefixes: &mut Prefixes) -> OpcodeRecord {
fn read_0f3a_opcode(opcode: u8, prefixes: &mut Prefixes) -> OpcodeRecord {
if prefixes.rep() {
- if prefixes.operand_size() || prefixes.repnz() {
+ if prefixes != &Prefixes::new(0x10) {
return OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing);
}
return match opcode {
diff --git a/src/protected_mode/vex.rs b/src/protected_mode/vex.rs
index 7c55ef1..36ccc66 100644
--- a/src/protected_mode/vex.rs
+++ b/src/protected_mode/vex.rs
@@ -1528,7 +1528,11 @@ fn read_vex_instruction<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch a
} else {
VEXOperandCode::G_V_E_xmm
}),
- 0x16 => (Opcode::VMOVHPD, VEXOperandCode::G_V_M_xmm),
+ 0x16 => (Opcode::VMOVHPD, if L {
+ return Err(DecodeError::InvalidOpcode);
+ } else {
+ VEXOperandCode::G_V_M_xmm
+ }),
0x17 => (Opcode::VMOVHPD, if L {
instruction.opcode = Opcode::Invalid;
return Err(DecodeError::InvalidOpcode);
diff --git a/src/shared/evex.in b/src/shared/evex.in
index 98006ca..f848808 100644
--- a/src/shared/evex.in
+++ b/src/shared/evex.in
@@ -1488,6 +1488,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
if mem_oper == OperandSpec::RegMMM {
instruction.mem_size = 0;
} else {
+ deny_broadcast(instruction)?;
instruction.mem_size = 4;
}
set_reg_sizes(instruction, RegisterBank::X);
@@ -1588,6 +1589,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
}
generated::EVEXOperandCode::Gm_V_zmm_E_xmm_imm8 => {
check_mask_reg(instruction)?;
+ deny_broadcast(instruction)?;
instruction.opcode = if instruction.prefixes.evex_unchecked().vex().w() {
Opcode::VINSERTI64X2
@@ -1614,6 +1616,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
}
generated::EVEXOperandCode::Gm_V_ymm_E_xmm_imm8 => {
check_mask_reg(instruction)?;
+ deny_broadcast(instruction)?;
instruction.opcode = if instruction.prefixes.evex_unchecked().vex().w() {
Opcode::VINSERTI64X2
@@ -1640,6 +1643,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
}
generated::EVEXOperandCode::Gm_V_zmm_E_ymm_imm8 => {
check_mask_reg(instruction)?;
+ deny_broadcast(instruction)?;
if instruction.prefixes.evex_unchecked().vex().w() {
if instruction.opcode == Opcode::VINSERTF32X8 {
@@ -1665,6 +1669,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
generated::EVEXOperandCode::Em_ymm_G_zmm_imm8 => {
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
+ deny_broadcast(instruction)?;
if instruction.prefixes.evex_unchecked().vex().w() {
if instruction.opcode == Opcode::VEXTRACTF32X8 {
@@ -1688,6 +1693,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
generated::EVEXOperandCode::Gm_zmm_Eq_xmm => {
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
+ deny_broadcast(instruction)?;
let modrm = read_modrm(words)?;
set_rrr(instruction, modrm);
@@ -1705,6 +1711,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
generated::EVEXOperandCode::Gm_ymm_Ed_xmm => {
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
+ deny_broadcast(instruction)?;
let modrm = read_modrm(words)?;
set_rrr(instruction, modrm);
@@ -1722,6 +1729,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
generated::EVEXOperandCode::Gm_xmm_Ew_xmm => {
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
+ deny_broadcast(instruction)?;
let modrm = read_modrm(words)?;
set_rrr(instruction, modrm);
@@ -1739,6 +1747,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
generated::EVEXOperandCode::Gm_zmm_E_xmm => {
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
+ deny_broadcast(instruction)?;
let modrm = read_modrm(words)?;
set_rrr(instruction, modrm);
@@ -1756,6 +1765,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
generated::EVEXOperandCode::Gm_ymm_Eq_xmm => {
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
+ deny_broadcast(instruction)?;
let modrm = read_modrm(words)?;
set_rrr(instruction, modrm);
@@ -1773,6 +1783,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
generated::EVEXOperandCode::Gm_xmm_Ed_xmm => {
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
+ deny_broadcast(instruction)?;
let modrm = read_modrm(words)?;
set_rrr(instruction, modrm);
@@ -1790,6 +1801,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
generated::EVEXOperandCode::Gm_zmm_E_ymm_W0 => {
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
+ deny_broadcast(instruction)?;
let modrm = read_modrm(words)?;
set_rrr(instruction, modrm);
@@ -1807,6 +1819,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
generated::EVEXOperandCode::Gm_zmm_E_ymm => {
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
+ deny_broadcast(instruction)?;
let modrm = read_modrm(words)?;
set_rrr(instruction, modrm);
@@ -1825,6 +1838,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
ensure_W(instruction, 0)?;
+ deny_broadcast(instruction)?;
let modrm = read_modrm(words)?;
set_rrr(instruction, modrm);
@@ -1842,6 +1856,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
generated::EVEXOperandCode::Gm_ymm_E_xmm => {
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
+ deny_broadcast(instruction)?;
let modrm = read_modrm(words)?;
set_rrr(instruction, modrm);
@@ -1859,6 +1874,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
generated::EVEXOperandCode::Gm_xmm_Eq_xmm_W0 => {
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
+ deny_broadcast(instruction)?;
let modrm = read_modrm(words)?;
set_rrr(instruction, modrm);
@@ -1876,6 +1892,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
generated::EVEXOperandCode::Gm_xmm_Eq_xmm => {
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
+ deny_broadcast(instruction)?;
let modrm = read_modrm(words)?;
set_rrr(instruction, modrm);
@@ -1894,6 +1911,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
ensure_W(instruction, 0)?;
+ deny_broadcast(instruction)?;
let modrm = read_modrm(words)?;
set_rrr(instruction, modrm);
@@ -1908,6 +1926,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
ensure_W(instruction, 0)?;
+ deny_broadcast(instruction)?;
let modrm = read_modrm(words)?;
set_rrr(instruction, modrm);
@@ -1922,6 +1941,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
ensure_W(instruction, 0)?;
+ deny_broadcast(instruction)?;
let modrm = read_modrm(words)?;
set_rrr(instruction, modrm);
@@ -1936,6 +1956,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
ensure_W(instruction, 0)?;
+ deny_broadcast(instruction)?;
let modrm = read_modrm(words)?;
set_rrr(instruction, modrm);
@@ -1950,6 +1971,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
ensure_W(instruction, 0)?;
+ deny_broadcast(instruction)?;
let modrm = read_modrm(words)?;
set_rrr(instruction, modrm);
@@ -1964,6 +1986,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
ensure_W(instruction, 0)?;
+ deny_broadcast(instruction)?;
let modrm = read_modrm(words)?;
set_rrr(instruction, modrm);
@@ -1978,6 +2001,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
ensure_W(instruction, 0)?;
+ deny_broadcast(instruction)?;
let modrm = read_modrm(words)?;
set_rrr(instruction, modrm);
@@ -1992,6 +2016,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
ensure_W(instruction, 0)?;
+ deny_broadcast(instruction)?;
let modrm = read_modrm(words)?;
set_rrr(instruction, modrm);
@@ -2006,6 +2031,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
ensure_W(instruction, 0)?;
+ deny_broadcast(instruction)?;
let modrm = read_modrm(words)?;
set_rrr(instruction, modrm);
@@ -2020,6 +2046,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
ensure_W(instruction, 0)?;
+ deny_broadcast(instruction)?;
let modrm = read_modrm(words)?;
set_rrr(instruction, modrm);
@@ -2038,6 +2065,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
ensure_W(instruction, 0)?;
+ deny_broadcast(instruction)?;
let modrm = read_modrm(words)?;
set_rrr(instruction, modrm);
@@ -2055,6 +2083,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
generated::EVEXOperandCode::Gm_zmm_M_ymm => {
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
+ deny_broadcast(instruction)?;
if instruction.prefixes.evex_unchecked().vex().w() {
if instruction.opcode == Opcode::VBROADCASTF32X8 {
@@ -2080,6 +2109,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
generated::EVEXOperandCode::Gm_zmm_M_xmm => {
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
+ deny_broadcast(instruction)?;
if instruction.prefixes.evex_unchecked().vex().w() {
if instruction.opcode == Opcode::VBROADCASTF32X4 {
@@ -2105,6 +2135,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
generated::EVEXOperandCode::Gm_ymm_M_xmm => {
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
+ deny_broadcast(instruction)?;
if instruction.prefixes.evex_unchecked().vex().w() {
if instruction.opcode == Opcode::VBROADCASTF32X4 {
@@ -2130,6 +2161,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
generated::EVEXOperandCode::Gm_zmm_Ed_xmm => {
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
+ deny_broadcast(instruction)?;
if instruction.prefixes.evex_unchecked().vex().w() {
instruction.opcode = Opcode::VBROADCASTSD;
@@ -2151,6 +2183,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
generated::EVEXOperandCode::VBROADCASTF32X2_Gm_ymm_Ed_xmm => {
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
+ deny_broadcast(instruction)?;
if instruction.prefixes.evex_unchecked().vex().w() {
instruction.opcode = Opcode::VBROADCASTSD;
@@ -2173,6 +2206,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
ensure_W(instruction, 0)?;
+ deny_broadcast(instruction)?;
let modrm = read_modrm(words)?;
set_rrr(instruction, modrm);
@@ -2190,6 +2224,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
generated::EVEXOperandCode::Em_xmm_G_LL_imm8 => {
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
+ deny_broadcast(instruction)?;
if instruction.prefixes.evex_unchecked().vex().w() {
instruction.opcode = if instruction.opcode == Opcode::VEXTRACTF32X4 {
@@ -2218,6 +2253,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
}
generated::EVEXOperandCode::Gm_V_LL_E_xmm_imm8 => {
check_mask_reg(instruction)?;
+ deny_broadcast(instruction)?;
instruction.opcode = if instruction.prefixes.evex_unchecked().vex().w() {
Opcode::VINSERTF64X2
@@ -2240,6 +2276,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
generated::EVEXOperandCode::Gm_V_LL_E_xmm_W0 => {
check_mask_reg(instruction)?;
ensure_W(instruction, 0)?;
+ deny_broadcast(instruction)?;
let modrm = read_modrm(words)?;
set_rrr(instruction, modrm);
@@ -2254,6 +2291,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
generated::EVEXOperandCode::Gm_V_LL_E_xmm_W1 => {
check_mask_reg(instruction)?;
ensure_W(instruction, 1)?;
+ deny_broadcast(instruction)?;
let modrm = read_modrm(words)?;
set_rrr(instruction, modrm);
@@ -2267,6 +2305,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
}
generated::EVEXOperandCode::Gm_V_LL_E_xmm => {
check_mask_reg(instruction)?;
+ deny_broadcast(instruction)?;
if instruction.prefixes.evex_unchecked().vex().w() {
instruction.opcode = if instruction.opcode == Opcode::VPSRAD {
@@ -2289,6 +2328,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
generated::EVEXOperandCode::VPEXTRW => {
deny_mask_reg(instruction)?;
deny_z(instruction)?;
+ deny_broadcast(instruction)?;
let modrm = read_modrm(words)?;
set_rrr(instruction, modrm);
@@ -2310,6 +2350,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
generated::EVEXOperandCode::VPINSRW => {
deny_mask_reg(instruction)?;
deny_z(instruction)?;
+ deny_broadcast(instruction)?;
let modrm = read_modrm(words)?;
set_rrr(instruction, modrm);
@@ -2333,6 +2374,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
deny_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
ensure_W(instruction, 1)?;
+ deny_broadcast(instruction)?;
let modrm = read_modrm(words)?;
set_rrr(instruction, modrm);
@@ -2353,6 +2395,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
deny_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
ensure_W(instruction, 1)?;
+ deny_broadcast(instruction)?;
let modrm = read_modrm(words)?;
set_rrr(instruction, modrm);
@@ -2373,6 +2416,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
deny_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
ensure_W(instruction, 1)?;
+ deny_broadcast(instruction)?;
let modrm = read_modrm(words)?;
set_rrr(instruction, modrm);
@@ -2390,6 +2434,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
generated::EVEXOperandCode::VMOVD_7e => {
deny_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
+ deny_broadcast(instruction)?;
let modrm = read_modrm(words)?;
set_rrr(instruction, modrm);
@@ -2420,6 +2465,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
generated::EVEXOperandCode::VMOVD_6e => {
deny_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
+ deny_broadcast(instruction)?;
let modrm = read_modrm(words)?;
set_rrr(instruction, modrm);
@@ -2538,6 +2584,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
generated::EVEXOperandCode::Em_G_LL => {
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
+ deny_broadcast(instruction)?;
let sz = regs_size(instruction);
@@ -2574,6 +2621,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
generated::EVEXOperandCode::Mask_U_LL => {
deny_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
+ deny_broadcast(instruction)?;
let sz = regs_size(instruction);
@@ -2605,6 +2653,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
generated::EVEXOperandCode::G_LL_Mask => {
deny_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
+ deny_broadcast(instruction)?;
let sz = regs_size(instruction);
@@ -2637,6 +2686,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
deny_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
ensure_W(instruction, 1)?;
+ deny_broadcast(instruction)?;
let sz = regs_size(instruction);
@@ -2661,6 +2711,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
deny_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
ensure_W(instruction, 0)?;
+ deny_broadcast(instruction)?;
let sz = regs_size(instruction);
@@ -2684,6 +2735,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
generated::EVEXOperandCode::G_E_LL_W0 => {
deny_mask_reg(instruction)?;
ensure_W(instruction, 0)?;
+ deny_broadcast(instruction)?;
let sz = regs_size(instruction);
@@ -2704,6 +2756,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
generated::EVEXOperandCode::E_G_LL_W0 => {
deny_mask_reg(instruction)?;
ensure_W(instruction, 0)?;
+ deny_broadcast(instruction)?;
let sz = regs_size(instruction);
@@ -2724,6 +2777,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
generated::EVEXOperandCode::Em_G_LL_W0 => {
check_mask_reg(instruction)?;
ensure_W(instruction, 0)?;
+ deny_broadcast(instruction)?;
let sz = regs_size(instruction);
@@ -2916,6 +2970,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
generated::EVEXOperandCode::Gm_LL_Eq_xmm => {
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
+ deny_broadcast(instruction)?;
if instruction.prefixes.evex_unchecked().vex().w() {
instruction.opcode = Opcode::VPBROADCASTQ;
@@ -2946,6 +3001,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
ensure_W(instruction, 0)?;
+ deny_broadcast(instruction)?;
let sz = regs_size(instruction);
@@ -2970,6 +3026,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
ensure_W(instruction, 0)?;
+ deny_broadcast(instruction)?;
let sz = regs_size(instruction);
@@ -2994,6 +3051,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
ensure_W(instruction, 0)?;
+ deny_broadcast(instruction)?;
let sz = regs_size(instruction);
@@ -3018,6 +3076,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
ensure_W(instruction, 0)?;
+ deny_broadcast(instruction)?;
let sz = regs_size(instruction);
@@ -3038,6 +3097,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
generated::EVEXOperandCode::Gm_E_LL_imm8 => {
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
+ deny_broadcast(instruction)?;
let sz = regs_size(instruction);
@@ -3101,6 +3161,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
if mem_oper == OperandSpec::RegMMM {
instruction.mem_size = 0;
} else {
+ deny_broadcast(instruction)?;
if instruction.opcode == Opcode::VCVTTSD2SI || instruction.opcode == Opcode::VCVTSD2SI || instruction.opcode == Opcode::VCVTTSD2USI || instruction.opcode == Opcode::VCVTSD2USI {
instruction.mem_size = 8;
} else {
@@ -3161,6 +3222,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
generated::EVEXOperandCode::Gm_E_LL => {
deny_vex_reg(instruction)?;
check_mask_reg(instruction)?;
+ deny_broadcast(instruction)?;
let sz = regs_size(instruction);
@@ -3214,6 +3276,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
set_rrr(instruction, modrm);
let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;
if mem_oper == OperandSpec::RegMMM {
+ deny_broadcast(instruction)?;
instruction.mem_size = 0;
}
instruction.operands[0] = OperandSpec::RegRRR_maskmerge;
@@ -3237,6 +3300,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
set_rrr(instruction, modrm);
let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;
if mem_oper == OperandSpec::RegMMM {
+ deny_broadcast(instruction)?;
instruction.mem_size = 0;
}
instruction.operands[0] = OperandSpec::RegRRR_maskmerge;
@@ -3282,6 +3346,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
generated::EVEXOperandCode::Mask_V_E_LL_W0 => {
check_mask_reg(instruction)?;
ensure_W(instruction, 0)?;
+ deny_broadcast(instruction)?;
let sz = regs_size(instruction);
@@ -3307,6 +3372,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
}
generated::EVEXOperandCode::Mask_V_E_LL => {
check_mask_reg(instruction)?;
+ deny_broadcast(instruction)?;
let sz = regs_size(instruction);
@@ -3349,10 +3415,8 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
if mem_oper == OperandSpec::RegMMM {
instruction.mem_size = 0;
} else {
+ deny_broadcast(instruction)?;
instruction.mem_size = 8;
- if instruction.prefixes.evex_unchecked().broadcast() {
- return Err(DecodeError::InvalidOperand);
- }
}
if instruction.prefixes.evex_unchecked().broadcast() {
instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround;
@@ -3384,9 +3448,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
instruction.mem_size = 0;
} else {
instruction.mem_size = 4;
- if instruction.prefixes.evex_unchecked().broadcast() {
- return Err(DecodeError::InvalidOperand);
- }
+ deny_broadcast(instruction)?;
}
if instruction.prefixes.evex_unchecked().broadcast() {
instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround;
@@ -3408,9 +3470,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
}
generated::EVEXOperandCode::Mask_V_E_LL_imm8 => {
check_mask_reg(instruction)?;
- if instruction.prefixes.evex_unchecked().broadcast() {
- return Err(DecodeError::InvalidOperand);
- }
+ deny_broadcast(instruction)?;
let sz = regs_size(instruction);
instruction.mem_size = sz;
@@ -3447,6 +3507,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
check_mask_reg(instruction)?;
deny_vex_reg(instruction)?;
deny_z(instruction)?;
+ deny_broadcast(instruction)?;
if instruction.prefixes.evex_unchecked().vex().w() {
instruction.opcode = if instruction.opcode == Opcode::VFPCLASSSS {
@@ -3510,6 +3571,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
set_rrr(instruction, modrm);
let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;
if mem_oper == OperandSpec::RegMMM {
+ deny_broadcast(instruction)?;
instruction.mem_size = 0;
}
instruction.operands[0] = OperandSpec::RegRRR_maskmerge;
@@ -3601,6 +3663,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
set_rrr(instruction, modrm);
let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;
if mem_oper == OperandSpec::RegMMM {
+ deny_broadcast(instruction)?;
instruction.mem_size = 0;
}
instruction.operands[0] = OperandSpec::RegRRR_maskmerge;
@@ -3665,6 +3728,7 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
generated::EVEXOperandCode::Gm_V_E_LL_imm8_W1 => {
check_mask_reg(instruction)?;
ensure_W(instruction, 1)?;
+ deny_broadcast(instruction)?;
let sz = regs_size(instruction);
instruction.mem_size = sz;
@@ -3726,6 +3790,9 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
let modrm = read_modrm(words)?;
set_rrr(instruction, modrm);
let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;
+ if mem_oper == OperandSpec::RegMMM {
+ deny_broadcast(instruction)?;
+ }
instruction.operands[0] = OperandSpec::RegRRR_maskmerge;
instruction.operands[1] = OperandSpec::RegVex;
instruction.operands[2] = mem_oper;
@@ -3741,15 +3808,14 @@ pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address
let sz = regs_size(instruction);
- if instruction.prefixes.evex_unchecked().broadcast() {
- return Err(DecodeError::InvalidOperand);
- } else {
- instruction.mem_size = sz;
- }
-
let modrm = read_modrm(words)?;
set_rrr(instruction, modrm);
let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;
+ if mem_oper == OperandSpec::RegMMM {
+ deny_broadcast(instruction)?;
+ } else {
+ instruction.mem_size = sz;
+ }
instruction.operands[0] = OperandSpec::RegRRR_maskmerge;
instruction.operands[1] = OperandSpec::RegVex;
instruction.operands[2] = mem_oper;
diff --git a/test/long_mode/mod.rs b/test/long_mode/mod.rs
index 4d44694..f9a3fef 100644
--- a/test/long_mode/mod.rs
+++ b/test/long_mode/mod.rs
@@ -1869,7 +1869,7 @@ fn test_vex() {
test_instr(&[0xc4, 0b000_00001, 0b1_0111_000, 0x16, 0b00_001_010], "vmovhps xmm9, xmm8, qword [r10]");
test_invalid(&[0xc4, 0b000_00001, 0b1_0111_100, 0x16, 0b00_001_010]);
test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0x16, 0b00_001_010], "vmovhpd xmm9, xmm8, qword [r10]");
- test_instr(&[0xc4, 0b000_00001, 0b1_0111_101, 0x16, 0b00_001_010], "vmovhpd xmm9, xmm8, qword [r10]");
+ test_invalid(&[0xc4, 0b000_00001, 0b1_0111_101, 0x16, 0b00_001_010]);
test_invalid(&[0xc4, 0b000_00001, 0b1_0111_001, 0x16, 0b11_001_010]);
test_instr(&[0xc4, 0b000_00001, 0b1_1111_000, 0x17, 0b00_001_010], "vmovhps qword [r10], xmm9");
test_invalid(&[0xc4, 0b000_00001, 0b1_1111_100, 0x17, 0b00_001_010]);
@@ -3147,6 +3147,12 @@ fn test_x87() {
#[test]
fn test_mishegos_finds() {
+ test_invalid(&[0xc5, 0x4d, 0x16, 0x0f]);
+ test_invalid(&[0xf3, 0x67, 0x0f, 0x3a, 0xf0, 0xfb, 0xb4]);
+// XOP is still not supported
+// test_display(&[0xc4, 0x63, 0x91, 0x7f, 0x2f, 0x2e], "vfnmsubsd xmm13, xmm13, xmm2, qword ptr [rdi]");
+ test_invalid(&[0x62, 0xf1, 0x56, 0xfe, 0x58, 0x04, 0xca]);
+ test_invalid(&[0x66, 0xf3, 0x36, 0x65, 0x0f, 0x3a, 0xf0, 0xee, 0x7a]);
test_display(&[0x62, 0x42, 0xd5, 0x9d, 0x97, 0xf6], "vfmsubadd132pd zmm30{k5}{z}{rne-sae}, zmm5, zmm14");
test_invalid(&[0x67, 0x66, 0x42, 0x0f, 0x01, 0xfe]);
test_display(&[0x62, 0x52, 0x05, 0xff, 0xad, 0xfd], "vfnmadd213ss xmm15{k7}{z}{rz-sae}, xmm15, xmm13");
diff --git a/test/long_mode/reuse_test.rs b/test/long_mode/reuse_test.rs
index 60a91e1..ad8e890 100644
--- a/test/long_mode/reuse_test.rs
+++ b/test/long_mode/reuse_test.rs
@@ -1,7 +1,7 @@
use yaxpeax_arch::Decoder;
use yaxpeax_x86::long_mode::InstDecoder;
-const INSTRUCTIONS: [&'static [u8]; 1982] = [
+const INSTRUCTIONS: [&'static [u8]; 1975] = [
&[0xc4, 0b000_00001, 0b0_0111_101, 0x60, 0b11_001_010],
&[0xc4, 0b000_00001, 0b0_0111_101, 0x61, 0b11_001_010],
&[0xc4, 0b000_00001, 0b0_0111_101, 0x62, 0b11_001_010],
@@ -1441,7 +1441,6 @@ const INSTRUCTIONS: [&'static [u8]; 1982] = [
&[0xc4, 0b000_00001, 0b0_1111_111, 0x2d, 0b11_001_010],
&[0xc4, 0b000_00001, 0b1_0111_000, 0x12, 0b00_001_010],
&[0xc4, 0b000_00001, 0b1_0111_000, 0x12, 0b11_001_010],
- &[0xc4, 0b000_00001, 0b1_0111_000, 0x16, 0b00_001_010],
&[0xc4, 0b000_00001, 0b1_0111_000, 0x54, 0b11_001_010],
&[0xc4, 0b000_00001, 0b1_0111_000, 0x55, 0b11_001_010],
&[0xc4, 0b000_00001, 0b1_0111_000, 0x56, 0b00_001_010],
@@ -1454,7 +1453,6 @@ const INSTRUCTIONS: [&'static [u8]; 1982] = [
&[0xc4, 0b000_00001, 0b1_0111_000, 0x5f, 0b00_001_010],
&[0xc4, 0b000_00001, 0b1_0111_000, 0xc2, 0b11_001_010, 0x77],
&[0xc4, 0b000_00001, 0b1_0111_001, 0x12, 0b00_001_010],
- &[0xc4, 0b000_00001, 0b1_0111_001, 0x16, 0b00_001_010],
&[0xc4, 0b000_00001, 0b1_0111_001, 0x54, 0b00_001_010],
&[0xc4, 0b000_00001, 0b1_0111_001, 0x55, 0b00_001_010],
&[0xc4, 0b000_00001, 0b1_0111_001, 0x56, 0b00_001_010],
@@ -1528,7 +1526,6 @@ const INSTRUCTIONS: [&'static [u8]; 1982] = [
&[0xc4, 0b000_00001, 0b1_0111_100, 0x5e, 0b00_001_010],
&[0xc4, 0b000_00001, 0b1_0111_100, 0x5f, 0b00_001_010],
&[0xc4, 0b000_00001, 0b1_0111_100, 0xc2, 0b11_001_010, 0x77],
- &[0xc4, 0b000_00001, 0b1_0111_101, 0x16, 0b00_001_010],
&[0xc4, 0b000_00001, 0b1_0111_101, 0x54, 0b00_001_010],
&[0xc4, 0b000_00001, 0b1_0111_101, 0x55, 0b00_001_010],
&[0xc4, 0b000_00001, 0b1_0111_101, 0x56, 0b00_001_010],
@@ -1600,7 +1597,6 @@ const INSTRUCTIONS: [&'static [u8]; 1982] = [
&[0xc4, 0b000_00001, 0b1_1111_010, 0x10, 0b00_001_010],
&[0xc4, 0b000_00001, 0b1_1111_010, 0x11, 0b00_001_010],
&[0xc4, 0b000_00001, 0b1_1111_010, 0x12, 0b00_001_010],
- &[0xc4, 0b000_00001, 0b1_1111_010, 0x16, 0b11_001_010],
&[0xc4, 0b000_00001, 0b1_1111_010, 0x2a, 0b00_001_010],
&[0xc4, 0b000_00001, 0b1_1111_010, 0x2a, 0b11_001_010],
&[0xc4, 0b000_00001, 0b1_1111_010, 0x51, 0b00_001_010],
@@ -1645,7 +1641,6 @@ const INSTRUCTIONS: [&'static [u8]; 1982] = [
&[0xc4, 0b000_00001, 0b1_1111_110, 0x10, 0b00_001_010],
&[0xc4, 0b000_00001, 0b1_1111_110, 0x11, 0b00_001_010],
&[0xc4, 0b000_00001, 0b1_1111_110, 0x12, 0b00_001_010],
- &[0xc4, 0b000_00001, 0b1_1111_110, 0x16, 0b11_001_010],
&[0xc4, 0b000_00001, 0b1_1111_110, 0x2a, 0b11_001_010],
&[0xc4, 0b000_00001, 0b1_1111_110, 0x2c, 0b11_001_010],
&[0xc4, 0b000_00001, 0b1_1111_110, 0x2d, 0b00_001_010],
@@ -1780,8 +1775,6 @@ const INSTRUCTIONS: [&'static [u8]; 1982] = [
&[0xc4, 0b000_00011, 0b1_0111_001, 0x22, 0b00_001_010, 0x77],
&[0xc4, 0b000_00011, 0b1_0111_001, 0x22, 0b11_001_010, 0x77],
&[0xc4, 0b000_00011, 0b1_0111_101, 0x0f, 0b11_001_010, 0x77],
- &[0xc4, 0b000_00011, 0b1_1111_001, 0x16, 0b00_001_010, 0x77],
- &[0xc4, 0b000_00011, 0b1_1111_001, 0x16, 0b11_001_010, 0x77],
&[0xc4, 0x02, 0x09, 0x9d, 0xcd],
&[0xc4, 0x02, 0x71, 0x00, 0x0f],
&[0xc4, 0x02, 0x71, 0x00, 0xcd],
diff --git a/test/protected_mode/mod.rs b/test/protected_mode/mod.rs
index c742516..04a5676 100644
--- a/test/protected_mode/mod.rs
+++ b/test/protected_mode/mod.rs
@@ -1751,7 +1751,7 @@ fn test_vex() {
test_instr(&[0xc4, 0b110_00001, 0b1_0111_000, 0x16, 0b00_001_010], "vmovhps xmm1, xmm0, qword [edx]");
test_invalid(&[0xc4, 0b110_00001, 0b1_0111_100, 0x16, 0b00_001_010]);
test_instr(&[0xc4, 0b110_00001, 0b1_0111_001, 0x16, 0b00_001_010], "vmovhpd xmm1, xmm0, qword [edx]");
- test_instr(&[0xc4, 0b110_00001, 0b1_0111_101, 0x16, 0b00_001_010], "vmovhpd xmm1, xmm0, qword [edx]");
+ test_invalid(&[0xc4, 0b110_00001, 0b1_0111_101, 0x16, 0b00_001_010]);
test_invalid(&[0xc4, 0b110_00001, 0b1_0111_001, 0x16, 0b11_001_010]);
test_instr(&[0xc4, 0b110_00001, 0b1_1111_000, 0x17, 0b00_001_010], "vmovhps qword [edx], xmm1");
test_invalid(&[0xc4, 0b110_00001, 0b1_1111_100, 0x17, 0b00_001_010]);