From f523478b3c6f5f29f600368afb1b84c9f5a41eba Mon Sep 17 00:00:00 2001 From: iximeow Date: Sun, 9 Aug 2020 19:47:08 -0700 Subject: reject instructions made invalid by lock prefixes --- src/long_mode/mod.rs | 28 ++++++++++++++++++++++++++++ src/protected_mode/mod.rs | 27 +++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) (limited to 'src') diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs index 4d663d3..3d6dc2b 100644 --- a/src/long_mode/mod.rs +++ b/src/long_mode/mod.rs @@ -3828,6 +3828,28 @@ pub enum OperandCode { Yv_AX = OperandCodeBuilder::new().special_case(101).bits(), } +const LOCKABLE_INSTRUCTIONS: &[Opcode] = &[ + Opcode::ADD, + Opcode::ADC, + Opcode::AND, + Opcode::BTC, + Opcode::BTR, + Opcode::BTS, + Opcode::CMPXCHG, + Opcode::CMPXCHG8B, + Opcode::CMPXCHG16B, + Opcode::DEC, + Opcode::INC, + Opcode::NEG, + Opcode::NOT, + Opcode::OR, + Opcode::SBB, + Opcode::SUB, + Opcode::XOR, + Opcode::XADD, + Opcode::XCHG, +]; + fn base_opcode_map(v: u8) -> Opcode { match v { 0 => Opcode::ADD, @@ -5650,6 +5672,12 @@ fn read_instr>(decoder: &InstDecoder, mut bytes_iter: T, in } instruction.length = length; + if instruction.prefixes.lock() { + if !LOCKABLE_INSTRUCTIONS.contains(&instruction.opcode) || !instruction.operands[0].is_memory() { + return Err(DecodeError::InvalidPrefixes); + } + } + if decoder != &InstDecoder::default() { // we might have to fix up or reject this instruction under whatever cpu features we need to // pretend to have. diff --git a/src/protected_mode/mod.rs b/src/protected_mode/mod.rs index 42595a8..1517c7c 100644 --- a/src/protected_mode/mod.rs +++ b/src/protected_mode/mod.rs @@ -3777,6 +3777,27 @@ pub enum OperandCode { DS = OperandCodeBuilder::new().special_case(106).bits(), } +const LOCKABLE_INSTRUCTIONS: &[Opcode] = &[ + Opcode::ADD, + Opcode::ADC, + Opcode::AND, + Opcode::BTC, + Opcode::BTR, + Opcode::BTS, + Opcode::CMPXCHG, + Opcode::CMPXCHG8B, + Opcode::DEC, + Opcode::INC, + Opcode::NEG, + Opcode::NOT, + Opcode::OR, + Opcode::SBB, + Opcode::SUB, + Opcode::XOR, + Opcode::XADD, + Opcode::XCHG, +]; + fn base_opcode_map(v: u8) -> Opcode { match v { 0 => Opcode::ADD, @@ -5571,6 +5592,12 @@ fn read_instr>(decoder: &InstDecoder, mut bytes_iter: T, in } instruction.length = length; + if instruction.prefixes.lock() { + if !LOCKABLE_INSTRUCTIONS.contains(&instruction.opcode) || !instruction.operands[0].is_memory() { + return Err(DecodeError::InvalidPrefixes); + } + } + if decoder != &InstDecoder::default() { // we might have to fix up or reject this instruction under whatever cpu features we need to // pretend to have. -- cgit v1.1