From 971c1f31d4aea860dfb48a55be92b3e882409206 Mon Sep 17 00:00:00 2001 From: 0xd4d Date: Thu, 16 Jul 2020 18:24:29 +0200 Subject: [PATCH] Assume PTWRITE isn't an opsize instruction --- src/UnitTests/Intel/Decoder/DecoderTest16.txt | 2 ++ src/UnitTests/Intel/Decoder/DecoderTest32.txt | 2 ++ src/UnitTests/Intel/Decoder/DecoderTest64.txt | 8 ++++++-- .../Intel/Generator/Enums/Decoder/StateFlags.cs | 1 + src/csharp/Intel/Iced/Intel/Decoder.cs | 2 ++ .../Intel/DecoderInternal/OpCodeHandlers_Legacy.cs | 13 +++---------- .../Intel/IcedFuzzer/IcedFuzzer.Core/FuzzerGen.cs | 11 ++++++++++- src/rust/iced-x86/src/decoder/handlers_legacy.rs | 13 +++---------- src/rust/iced-x86/src/decoder/mod.rs | 2 ++ 9 files changed, 31 insertions(+), 23 deletions(-) diff --git a/src/UnitTests/Intel/Decoder/DecoderTest16.txt b/src/UnitTests/Intel/Decoder/DecoderTest16.txt index 4e4c1401c..797da9756 100644 --- a/src/UnitTests/Intel/Decoder/DecoderTest16.txt +++ b/src/UnitTests/Intel/Decoder/DecoderTest16.txt @@ -8951,6 +8951,8 @@ F3 0FAE 20, Ptwrite_rm32, Ptwrite, 1, op0=m;ds;bx;si;1;0;0;UInt32 F3 0FAE E5, Ptwrite_rm32, Ptwrite, 1, op0=r;ebp 66 F3 0FAE 20, INVALID, INVALID, 0, code=Ptwrite_rm32 66 F3 0FAE E5, INVALID, INVALID, 0, code=Ptwrite_rm32 +66 F3 0FAE 20, Ptwrite_rm32, Ptwrite, 1, op0=m;ds;bx;si;1;0;0;UInt32 noinvalidcheck enc=F30FAE20 +66 F3 0FAE E5, Ptwrite_rm32, Ptwrite, 1, op0=r;ebp noinvalidcheck enc=F30FAEE5 0FAE 28, Xrstor_mem, Xrstor, 1, op0=m;ds;bx;si;1;0;0;Xsave diff --git a/src/UnitTests/Intel/Decoder/DecoderTest32.txt b/src/UnitTests/Intel/Decoder/DecoderTest32.txt index 83fd317f9..6bd40d110 100644 --- a/src/UnitTests/Intel/Decoder/DecoderTest32.txt +++ b/src/UnitTests/Intel/Decoder/DecoderTest32.txt @@ -8952,6 +8952,8 @@ F3 0FAE 20, Ptwrite_rm32, Ptwrite, 1, op0=m;ds;eax;;1;0;0;UInt32 F3 0FAE E5, Ptwrite_rm32, Ptwrite, 1, op0=r;ebp 66 F3 0FAE 20, INVALID, INVALID, 0, code=Ptwrite_rm32 66 F3 0FAE E5, INVALID, INVALID, 0, code=Ptwrite_rm32 +66 F3 0FAE 20, Ptwrite_rm32, Ptwrite, 1, op0=m;ds;eax;;1;0;0;UInt32 noinvalidcheck enc=F30FAE20 +66 F3 0FAE E5, Ptwrite_rm32, Ptwrite, 1, op0=r;ebp noinvalidcheck enc=F30FAEE5 0FAE 28, Xrstor_mem, Xrstor, 1, op0=m;ds;eax;;1;0;0;Xsave diff --git a/src/UnitTests/Intel/Decoder/DecoderTest64.txt b/src/UnitTests/Intel/Decoder/DecoderTest64.txt index 202d739a0..5c1e8b37b 100644 --- a/src/UnitTests/Intel/Decoder/DecoderTest64.txt +++ b/src/UnitTests/Intel/Decoder/DecoderTest64.txt @@ -14739,13 +14739,17 @@ F3 41 0FAE E5, Ptwrite_rm32, Ptwrite, 1, op0=r;r13d F3 46 0FAE E5, Ptwrite_rm32, Ptwrite, 1, op0=r;ebp enc=F30FAEE5 66 F3 0FAE 20, INVALID, INVALID, 0, code=Ptwrite_rm32 66 F3 0FAE E5, INVALID, INVALID, 0, code=Ptwrite_rm32 +66 F3 0FAE 20, Ptwrite_rm32, Ptwrite, 1, op0=m;ds;rax;;1;0;0;UInt32 noinvalidcheck enc=F30FAE20 +66 F3 0FAE E5, Ptwrite_rm32, Ptwrite, 1, op0=r;ebp noinvalidcheck enc=F30FAEE5 F3 48 0FAE 20, Ptwrite_rm64, Ptwrite, 1, op0=m;ds;rax;;1;0;0;UInt64 F3 48 0FAE E5, Ptwrite_rm64, Ptwrite, 1, op0=r;rbp F3 49 0FAE E5, Ptwrite_rm64, Ptwrite, 1, op0=r;r13 F3 4E 0FAE E5, Ptwrite_rm64, Ptwrite, 1, op0=r;rbp enc=F3480FAEE5 -66 F3 48 0FAE 20, Ptwrite_rm64, Ptwrite, 1, op0=m;ds;rax;;1;0;0;UInt64 enc=F3480FAE20 -66 F3 48 0FAE E5, Ptwrite_rm64, Ptwrite, 1, op0=r;rbp enc=F3480FAEE5 +66 F3 48 0FAE 20, INVALID, INVALID, 0, code=Ptwrite_rm64 +66 F3 48 0FAE E5, INVALID, INVALID, 0, code=Ptwrite_rm64 +66 F3 48 0FAE 20, Ptwrite_rm64, Ptwrite, 1, op0=m;ds;rax;;1;0;0;UInt64 noinvalidcheck enc=F3480FAE20 +66 F3 48 0FAE E5, Ptwrite_rm64, Ptwrite, 1, op0=r;rbp noinvalidcheck enc=F3480FAEE5 0FAE 28, Xrstor_mem, Xrstor, 1, op0=m;ds;rax;;1;0;0;Xsave 44 0FAE 28, Xrstor_mem, Xrstor, 1, op0=m;ds;rax;;1;0;0;Xsave enc=0FAE28 diff --git a/src/csharp/Intel/Generator/Enums/Decoder/StateFlags.cs b/src/csharp/Intel/Generator/Enums/Decoder/StateFlags.cs index 365894240..ac18db885 100644 --- a/src/csharp/Intel/Generator/Enums/Decoder/StateFlags.cs +++ b/src/csharp/Intel/Generator/Enums/Decoder/StateFlags.cs @@ -41,6 +41,7 @@ enum StateFlags : uint { Lock = 0x00001000, AllowLock = 0x00002000, NoMoreBytes = 0x00004000, + Has66 = 0x00008000, } [TypeGen(TypeGenOrders.NoDeps)] diff --git a/src/csharp/Intel/Iced/Intel/Decoder.cs b/src/csharp/Intel/Iced/Intel/Decoder.cs index b90894994..e7e2eed4d 100644 --- a/src/csharp/Intel/Iced/Intel/Decoder.cs +++ b/src/csharp/Intel/Iced/Intel/Decoder.cs @@ -56,6 +56,7 @@ enum StateFlags : uint { Lock = 0x00001000, AllowLock = 0x00002000, NoMoreBytes = 0x00004000, + Has66 = 0x00008000, } // GENERATOR-END: StateFlags @@ -372,6 +373,7 @@ public void Decode(out Instruction instruction) { break; case 0x66: + state.flags |= StateFlags.Has66; state.operandSize = defaultInvertedOperandSize; if (state.mandatoryPrefix == MandatoryPrefixByte.None) state.mandatoryPrefix = MandatoryPrefixByte.P66; diff --git a/src/csharp/Intel/Iced/Intel/DecoderInternal/OpCodeHandlers_Legacy.cs b/src/csharp/Intel/Iced/Intel/DecoderInternal/OpCodeHandlers_Legacy.cs index ab99937a3..86e9a72d1 100644 --- a/src/csharp/Intel/Iced/Intel/DecoderInternal/OpCodeHandlers_Legacy.cs +++ b/src/csharp/Intel/Iced/Intel/DecoderInternal/OpCodeHandlers_Legacy.cs @@ -779,16 +779,9 @@ public override void Decode(Decoder decoder, ref Instruction instruction) { instruction.InternalCode = code64; else instruction.InternalCode = code32; - if ((flags & 4) != 0) { - if (decoder.Bitness != 16) { - if (state.operandSize == OpSize.Size16) - decoder.SetInvalidInstruction(); - } - else { - if (state.operandSize != OpSize.Size16) - decoder.SetInvalidInstruction(); - } - } + Static.Assert((uint)StateFlags.Has66 != 4 ? 0 : -1); + if ((((flags & 4) | (uint)(state.flags & StateFlags.Has66)) & decoder.invalidCheckMask) == (4 | (uint)StateFlags.Has66)) + decoder.SetInvalidInstruction(); if (state.mod == 3) { Static.Assert(OpKind.Register == 0 ? 0 : -1); //instruction.InternalOp0Kind = OpKind.Register; diff --git a/src/csharp/Intel/IcedFuzzer/IcedFuzzer.Core/FuzzerGen.cs b/src/csharp/Intel/IcedFuzzer/IcedFuzzer.Core/FuzzerGen.cs index dbc8dce05..8f5bcc05a 100644 --- a/src/csharp/Intel/IcedFuzzer/IcedFuzzer.Core/FuzzerGen.cs +++ b/src/csharp/Intel/IcedFuzzer/IcedFuzzer.Core/FuzzerGen.cs @@ -409,7 +409,16 @@ public override IEnumerable Generate(FuzzerGenContext context) throw ThrowHelpers.Unreachable; } - bool no66 = context.Instruction.Code == Code.Ptwrite_rm32; + bool no66; + switch (context.Instruction.Code) { + case Code.Ptwrite_rm32: + case Code.Ptwrite_rm64: + no66 = true; + break; + default: + no66 = false; + break; + } var writePrefixes = context.WritePrefixes; var prefixesTmp1 = context.PrefixesTmp1; diff --git a/src/rust/iced-x86/src/decoder/handlers_legacy.rs b/src/rust/iced-x86/src/decoder/handlers_legacy.rs index 468df0be9..a06a391b5 100644 --- a/src/rust/iced-x86/src/decoder/handlers_legacy.rs +++ b/src/rust/iced-x86/src/decoder/handlers_legacy.rs @@ -948,16 +948,9 @@ impl OpCodeHandler_Ev_REXW { } else { super::instruction_internal::internal_set_code_u32(instruction, this.code32); } - if (this.flags & 4) != 0 { - if decoder.bitness != 16 { - if decoder.state.operand_size == OpSize::Size16 { - decoder.set_invalid_instruction(); - } - } else { - if decoder.state.operand_size != OpSize::Size16 { - decoder.set_invalid_instruction(); - } - } + const_assert_ne!(4, StateFlags::HAS66); + if (((this.flags & 4) | (decoder.state.flags & StateFlags::HAS66)) & decoder.invalid_check_mask) == (4 | StateFlags::HAS66) { + decoder.set_invalid_instruction(); } if decoder.state.mod_ == 3 { const_assert_eq!(0, OpKind::Register as u32); diff --git a/src/rust/iced-x86/src/decoder/mod.rs b/src/rust/iced-x86/src/decoder/mod.rs index 0e8fd8b7b..16ef7826a 100644 --- a/src/rust/iced-x86/src/decoder/mod.rs +++ b/src/rust/iced-x86/src/decoder/mod.rs @@ -215,6 +215,7 @@ impl StateFlags { pub(crate) const LOCK: u32 = 0x0000_1000; pub(crate) const ALLOW_LOCK: u32 = 0x0000_2000; pub(crate) const NO_MORE_BYTES: u32 = 0x0000_4000; + pub(crate) const HAS66: u32 = 0x0000_8000; } // GENERATOR-END: StateFlags @@ -1010,6 +1011,7 @@ impl<'a> Decoder<'a> { rex_prefix = 0; } 0x66 => { + self.state.flags |= StateFlags::HAS66; self.state.operand_size = self.default_inverted_operand_size; if self.state.mandatory_prefix == MandatoryPrefixByte::None as u32 { self.state.mandatory_prefix = MandatoryPrefixByte::P66 as u32;