decode: Don't walk escape opcodes in tables

This commit is contained in:
Alexis Engelke
2020-06-25 16:51:21 +02:00
parent 3ad518e22e
commit 1b5461036e
2 changed files with 23 additions and 24 deletions

View File

@@ -83,7 +83,7 @@ decode_prefixes(const uint8_t* buffer, int len, DecodeMode mode,
uint8_t rep = 0; uint8_t rep = 0;
*out_mandatory = 0; *out_mandatory = 0;
*out_segment = FD_REG_NONE; *out_segment = FD_REG_NONE;
*out_opcode_escape = -1; *out_opcode_escape = 0;
while (LIKELY(off < len)) while (LIKELY(off < len))
{ {
@@ -373,24 +373,28 @@ fd_decode(const uint8_t* buffer, size_t len_sz, int mode_int, uintptr_t address,
uint32_t kind = ENTRY_TABLE_ROOT; uint32_t kind = ENTRY_TABLE_ROOT;
if (LIKELY(!(prefixes & PREFIX_VEX))) if (UNLIKELY(prefixes & PREFIX_VEX))
{ {
// "Legacy" walk through table and escape opcodes
ENTRY_UNPACK(table, kind, table[0]);
if (kind == ENTRY_TABLE256 && LIKELY(off < len))
ENTRY_UNPACK(table, kind, table[buffer[off++]]);
if (UNLIKELY(kind == ENTRY_TABLE256) && LIKELY(off < len))
ENTRY_UNPACK(table, kind, table[buffer[off++]]);
}
else
{
// VEX/EVEX compact escapes; the prefix precedes the single opcode byte
if (opcode_escape < 0 || opcode_escape > 3) if (opcode_escape < 0 || opcode_escape > 3)
return FD_ERR_UD; return FD_ERR_UD;
ENTRY_UNPACK(table, kind, table[4 | opcode_escape]); opcode_escape |= 4;
if (LIKELY(off < len))
ENTRY_UNPACK(table, kind, table[buffer[off++]]);
} }
else if (buffer[off] == 0x0f)
{
if (UNLIKELY(off + 1 >= len))
return FD_ERR_PARTIAL;
if (buffer[off + 1] == 0x38)
opcode_escape = 2;
else if (buffer[off + 1] == 0x3a)
opcode_escape = 3;
else
opcode_escape = 1;
off += opcode_escape >= 2 ? 2 : 1;
}
ENTRY_UNPACK(table, kind, table[opcode_escape]);
if (LIKELY(off < len))
ENTRY_UNPACK(table, kind, table[buffer[off++]]);
// Then, walk through ModR/M-encoded opcode extensions. // Then, walk through ModR/M-encoded opcode extensions.
if ((kind == ENTRY_TABLE8 || kind == ENTRY_TABLE72) && LIKELY(off < len)) if ((kind == ENTRY_TABLE8 || kind == ENTRY_TABLE72) && LIKELY(off < len))

View File

@@ -214,16 +214,11 @@ def parse_opcode(opcode_string):
opcode = [] opcode = []
opcode_bytes = unhexlify(match.group("opcode")) opcode_bytes = unhexlify(match.group("opcode"))
# root table, VEX prefix already consumes escape opcode bytes idx = [b"", b"\x0f", b"\x0f\x38", b"\x0f\x3a"].index(opcode_bytes[:-1])
if match.group("vex"): if match.group("vex"):
idx = [b"", b"\x0f", b"\x0f\x38", b"\x0f\x3a"].index(opcode_bytes[:-1]) idx |= 4
opcode.append((EntryKind.TABLE_ROOT, [4 | idx])) opcode.append((EntryKind.TABLE_ROOT, [idx]))
opcode_bytes = opcode_bytes[-1:] opcode.append((EntryKind.TABLE256, [opcode_bytes[-1]]))
else:
opcode.append((EntryKind.TABLE_ROOT, [0]))
# normal opcode bytes
opcode += [(EntryKind.TABLE256, [x]) for x in opcode_bytes]
opcext = match.group("modrm") opcext = match.group("modrm")
if opcext: if opcext: