Correctly handle mis-placed REX prefix

This commit is contained in:
Alexis Engelke
2019-11-02 17:32:40 +01:00
parent d728f8f4af
commit e43ec050af

View File

@@ -81,6 +81,8 @@ decode_prefixes(const uint8_t* buffer, int len, DecodeMode mode,
{ {
int off = 0; int off = 0;
PrefixSet prefixes = 0; PrefixSet prefixes = 0;
PrefixSet rex_prefix = 0;
int rex_off = -1;
uint8_t rep = 0; uint8_t rep = 0;
*out_mandatory = 0; *out_mandatory = 0;
@@ -111,18 +113,16 @@ decode_prefixes(const uint8_t* buffer, int len, DecodeMode mode,
case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45:
case 0x46: case 0x47: case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x46: case 0x47: case 0x48: case 0x49: case 0x4a: case 0x4b:
case 0x4c: case 0x4d: case 0x4e: case 0x4f: case 0x4c: case 0x4d: case 0x4e: case 0x4f:
if (mode == DECODE_64) if (mode != DECODE_64)
{
prefixes |= PREFIX_REX;
prefixes |= prefix & 0x1 ? PREFIX_REXB : 0;
prefixes |= prefix & 0x2 ? PREFIX_REXX : 0;
prefixes |= prefix & 0x4 ? PREFIX_REXR : 0;
prefixes |= prefix & 0x8 ? PREFIX_REXW : 0;
off++;
}
// If in 64-bit mode, the REX prefix is always the last prefix. In
// 32-bit mode these are regular opcodes, so exit without consuming.
goto out; goto out;
rex_prefix |= PREFIX_REX;
rex_prefix |= prefix & 0x1 ? PREFIX_REXB : 0;
rex_prefix |= prefix & 0x2 ? PREFIX_REXX : 0;
rex_prefix |= prefix & 0x4 ? PREFIX_REXR : 0;
rex_prefix |= prefix & 0x8 ? PREFIX_REXW : 0;
rex_off = off;
off++;
break;
#endif #endif
case 0xc4: case 0xc5: // VEX case 0xc4: case 0xc5: // VEX
if (UNLIKELY(off + 1 >= len)) if (UNLIKELY(off + 1 >= len))
@@ -169,6 +169,10 @@ decode_prefixes(const uint8_t* buffer, int len, DecodeMode mode,
} }
out: out:
// REX prefix is only considered if it is the last prefix.
if (rex_off == off - 1)
prefixes |= rex_prefix;
// If there is no REP/REPNZ prefix and implied opcode extension from a VEX // If there is no REP/REPNZ prefix and implied opcode extension from a VEX
// prefix, offer 66h as mandatory prefix. If there is a REP prefix, then the // prefix, offer 66h as mandatory prefix. If there is a REP prefix, then the
// 66h prefix is ignored when evaluating mandatory prefixes. // 66h prefix is ignored when evaluating mandatory prefixes.