Skip to content

Commit

Permalink
Fixed hidden operand scaling regression (Fixes zyantific#309)
Browse files Browse the repository at this point in the history
  • Loading branch information
mappzor authored and flobernd committed Feb 8, 2022
1 parent b44ec34 commit 91742f4
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 25 deletions.
12 changes: 6 additions & 6 deletions include/Zydis/Encoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,12 +147,12 @@ typedef enum ZydisAddressSizeHint_
/**
* Maximum value of this enum.
*/
ZYDIS_ADDRESS_SIZE_MAX_VALUE = ZYDIS_ADDRESS_SIZE_HINT_64,
ZYDIS_ADDRESS_SIZE_HINT_MAX_VALUE = ZYDIS_ADDRESS_SIZE_HINT_64,
/**
* The minimum number of bits required to represent all values of this enum.
*/
ZYDIS_ADDRESS_SIZE_MAX_REQUIRED_BITS =
ZYAN_BITS_TO_REPRESENT(ZYDIS_ADDRESS_SIZE_MAX_VALUE)
ZYDIS_ADDRESS_SIZE_HINT_MAX_REQUIRED_BITS =
ZYAN_BITS_TO_REPRESENT(ZYDIS_ADDRESS_SIZE_HINT_MAX_VALUE)
} ZydisAddressSizeHint;

/**
Expand All @@ -170,12 +170,12 @@ typedef enum ZydisOperandSizeHint_
/**
* Maximum value of this enum.
*/
ZYDIS_OPERAND_SIZE_MAX_VALUE = ZYDIS_OPERAND_SIZE_HINT_64,
ZYDIS_OPERAND_SIZE_HINT_MAX_VALUE = ZYDIS_OPERAND_SIZE_HINT_64,
/**
* The minimum number of bits required to represent all values of this enum.
*/
ZYDIS_OPERAND_SIZE_REQUIRED_BITS =
ZYAN_BITS_TO_REPRESENT(ZYDIS_OPERAND_SIZE_MAX_VALUE)
ZYDIS_OPERAND_SIZE_HINT_REQUIRED_BITS =
ZYAN_BITS_TO_REPRESENT(ZYDIS_OPERAND_SIZE_HINT_MAX_VALUE)
} ZydisOperandSizeHint;

/**
Expand Down
29 changes: 12 additions & 17 deletions src/Encoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -311,29 +311,23 @@ ZyanU8 ZydisGetMachineModeWidth(ZydisMachineMode machine_mode)
*/
ZyanU8 ZydisGetAszFromHint(ZydisAddressSizeHint hint)
{
ZYAN_ASSERT((ZyanUSize)hint <= ZYDIS_ADDRESS_SIZE_MAX_VALUE);
static const ZyanU8 lookup[ZYDIS_ADDRESS_SIZE_MAX_VALUE + 1] = { 0, 16, 32, 64 };
ZYAN_ASSERT((ZyanUSize)hint <= ZYDIS_ADDRESS_SIZE_HINT_MAX_VALUE);
static const ZyanU8 lookup[ZYDIS_ADDRESS_SIZE_HINT_MAX_VALUE + 1] = { 0, 16, 32, 64 };
return lookup[hint];
}

/**
* Converts `ZydisOperandSizeHint` to operand size expressed in bits.
*
* @param hint Operand size hint.
* @param mode_width Default width for desired machine mode.
* @param hint Operand size hint.
*
* @return Operand size in bits.
*/
ZyanU8 ZydisGetOszFromHint(ZydisOperandSizeHint hint, ZydisWidthFlag mode_width)
ZyanU8 ZydisGetOszFromHint(ZydisOperandSizeHint hint)
{
ZYAN_ASSERT((ZyanUSize)hint <= ZYDIS_OPERAND_SIZE_MAX_VALUE);
ZYAN_ASSERT((ZyanUSize)mode_width <= ZYDIS_WIDTH_MAX_VALUE);
if (hint == ZYDIS_OPERAND_SIZE_HINT_NONE)
{
return (ZyanU8)(mode_width << 4);
}

return 4 << hint;
ZYAN_ASSERT((ZyanUSize)hint <= ZYDIS_OPERAND_SIZE_HINT_MAX_VALUE);
static const ZyanU8 lookup[ZYDIS_OPERAND_SIZE_HINT_MAX_VALUE + 1] = { 0, 8, 16, 32, 64 };
return lookup[hint];
}

/**
Expand All @@ -353,7 +347,8 @@ ZyanU8 ZydisGetOperandSizeFromElementSize(ZydisEncoderInstructionMatch *match,
if ((match->base_definition->operand_size_map == ZYDIS_OPSIZE_MAP_DEFAULT64) &&
(match->request->machine_mode == ZYDIS_MACHINE_MODE_LONG_64))
{
if (size_table[2] == desired_size)
if ((exact_match_mode && (size_table[2] == desired_size)) ||
(!exact_match_mode && (size_table[2] >= desired_size)))
{
return 64;
}
Expand Down Expand Up @@ -2925,7 +2920,7 @@ ZyanStatus ZydisFindMatchingDefinition(const ZydisEncoderRequest *request,
(request->machine_mode == ZYDIS_MACHINE_MODE_LONG_COMPAT_16) ||
(request->machine_mode == ZYDIS_MACHINE_MODE_LONG_COMPAT_32);
const ZyanU8 default_asz = ZydisGetAszFromHint(request->address_size_hint);
const ZyanU8 default_osz = ZydisGetOszFromHint(request->operand_size_hint, mode_width);
const ZyanU8 default_osz = ZydisGetOszFromHint(request->operand_size_hint);
const ZyanU16 operand_mask = ZydisGetOperandMask(request);

for (ZyanU8 i = 0; i < definition_count; ++i, ++definition)
Expand Down Expand Up @@ -4098,8 +4093,8 @@ ZyanStatus ZydisEncoderCheckRequestSanity(const ZydisEncoderRequest *request)
((ZyanUSize)request->mnemonic > ZYDIS_MNEMONIC_MAX_VALUE) ||
((ZyanUSize)request->branch_type > ZYDIS_BRANCH_TYPE_MAX_VALUE) ||
((ZyanUSize)request->branch_width > ZYDIS_BRANCH_WIDTH_MAX_VALUE) ||
((ZyanUSize)request->address_size_hint > ZYDIS_ADDRESS_SIZE_MAX_VALUE) ||
((ZyanUSize)request->operand_size_hint > ZYDIS_OPERAND_SIZE_MAX_VALUE) ||
((ZyanUSize)request->address_size_hint > ZYDIS_ADDRESS_SIZE_HINT_MAX_VALUE) ||
((ZyanUSize)request->operand_size_hint > ZYDIS_OPERAND_SIZE_HINT_MAX_VALUE) ||
((ZyanUSize)request->evex.broadcast > ZYDIS_BROADCAST_MODE_MAX_VALUE) ||
((ZyanUSize)request->evex.rounding > ZYDIS_ROUNDING_MODE_MAX_VALUE) ||
((ZyanUSize)request->mvex.broadcast > ZYDIS_BROADCAST_MODE_MAX_VALUE) ||
Expand Down
32 changes: 32 additions & 0 deletions tests/enc_test_cases.json
Original file line number Diff line number Diff line change
Expand Up @@ -2071,5 +2071,37 @@
"sae": true,
"eviction_hint": true
}
},
{
"machine_mode": "ZYDIS_MACHINE_MODE_LONG_64",
"allowed_encodings": "ZYDIS_ENCODABLE_ENCODING_DEFAULT",
"mnemonic": "ZYDIS_MNEMONIC_PUSH",
"prefixes": "ZYDIS_ATTRIB_NONE",
"branch_type": "ZYDIS_BRANCH_TYPE_NONE",
"branch_width": "ZYDIS_BRANCH_WIDTH_NONE",
"address_size_hint": "ZYDIS_ADDRESS_SIZE_HINT_NONE",
"operand_size_hint": "ZYDIS_OPERAND_SIZE_HINT_NONE",
"operands": [
{
"operand_type": "ZYDIS_OPERAND_TYPE_IMMEDIATE",
"imm": {
"value": "1953184666629517322"
}
}
],
"evex": {
"broadcast": "ZYDIS_BROADCAST_MODE_INVALID",
"rounding": "ZYDIS_ROUNDING_MODE_INVALID",
"sae": false,
"zeroing_mask": false
},
"mvex": {
"broadcast": "ZYDIS_BROADCAST_MODE_INVALID",
"conversion": "ZYDIS_CONVERSION_MODE_INVALID",
"rounding": "ZYDIS_ROUNDING_MODE_INVALID",
"swizzle": "ZYDIS_SWIZZLE_MODE_DCBA",
"sae": false,
"eviction_hint": false
}
}
]
1 change: 1 addition & 0 deletions tests/zydis_encoder_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
'ZYDIS_BRANCH_WIDTH_8',
'ZYDIS_BRANCH_WIDTH_16',
'ZYDIS_BRANCH_WIDTH_32',
'ZYDIS_BRANCH_WIDTH_64',
], start=0)


Expand Down
4 changes: 2 additions & 2 deletions tools/ZydisFuzzEncoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -220,9 +220,9 @@ int ZydisFuzzTarget(ZydisStreamRead read_fn, void *stream_ctx)
ZYDIS_SANITIZE_ENUM(request.branch_type, ZydisBranchType, ZYDIS_BRANCH_TYPE_MAX_VALUE);
ZYDIS_SANITIZE_ENUM(request.branch_width, ZydisBranchWidth, ZYDIS_BRANCH_WIDTH_MAX_VALUE);
ZYDIS_SANITIZE_ENUM(request.address_size_hint, ZydisAddressSizeHint,
ZYDIS_ADDRESS_SIZE_MAX_VALUE);
ZYDIS_ADDRESS_SIZE_HINT_MAX_VALUE);
ZYDIS_SANITIZE_ENUM(request.operand_size_hint, ZydisOperandSizeHint,
ZYDIS_OPERAND_SIZE_MAX_VALUE);
ZYDIS_OPERAND_SIZE_HINT_MAX_VALUE);
ZYDIS_SANITIZE_ENUM(request.evex.broadcast, ZydisBroadcastMode, ZYDIS_BROADCAST_MODE_MAX_VALUE);
ZYDIS_SANITIZE_ENUM(request.evex.rounding, ZydisRoundingMode, ZYDIS_ROUNDING_MODE_MAX_VALUE);
ZYDIS_SANITIZE_ENUM(request.mvex.broadcast, ZydisBroadcastMode, ZYDIS_BROADCAST_MODE_MAX_VALUE);
Expand Down

0 comments on commit 91742f4

Please sign in to comment.