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;
*out_mandatory = 0;
*out_segment = FD_REG_NONE;
*out_opcode_escape = -1;
*out_opcode_escape = 0;
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;
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)
return FD_ERR_UD;
ENTRY_UNPACK(table, kind, table[4 | opcode_escape]);
if (LIKELY(off < len))
ENTRY_UNPACK(table, kind, table[buffer[off++]]);
opcode_escape |= 4;
}
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.
if ((kind == ENTRY_TABLE8 || kind == ENTRY_TABLE72) && LIKELY(off < len))

View File

@@ -214,16 +214,11 @@ def parse_opcode(opcode_string):
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"):
idx = [b"", b"\x0f", b"\x0f\x38", b"\x0f\x3a"].index(opcode_bytes[:-1])
opcode.append((EntryKind.TABLE_ROOT, [4 | idx]))
opcode_bytes = opcode_bytes[-1:]
else:
opcode.append((EntryKind.TABLE_ROOT, [0]))
# normal opcode bytes
opcode += [(EntryKind.TABLE256, [x]) for x in opcode_bytes]
idx |= 4
opcode.append((EntryKind.TABLE_ROOT, [idx]))
opcode.append((EntryKind.TABLE256, [opcode_bytes[-1]]))
opcext = match.group("modrm")
if opcext: