mirror of https://github.com/x64dbg/zydis
Optimized detection of bad register values
This commit is contained in:
parent
44bbc7cea2
commit
57ccc70415
|
@ -199,8 +199,8 @@ typedef ZydisU8 ZydisRegisterConstraint;
|
||||||
*/
|
*/
|
||||||
enum ZydisRegisterConstraints
|
enum ZydisRegisterConstraints
|
||||||
{
|
{
|
||||||
ZYDIS_REG_CONSTRAINTS_NONE,
|
|
||||||
ZYDIS_REG_CONSTRAINTS_UNUSED,
|
ZYDIS_REG_CONSTRAINTS_UNUSED,
|
||||||
|
ZYDIS_REG_CONSTRAINTS_NONE,
|
||||||
ZYDIS_REG_CONSTRAINTS_GPR,
|
ZYDIS_REG_CONSTRAINTS_GPR,
|
||||||
ZYDIS_REG_CONSTRAINTS_SR_DEST,
|
ZYDIS_REG_CONSTRAINTS_SR_DEST,
|
||||||
ZYDIS_REG_CONSTRAINTS_SR,
|
ZYDIS_REG_CONSTRAINTS_SR,
|
||||||
|
@ -208,8 +208,9 @@ enum ZydisRegisterConstraints
|
||||||
ZYDIS_REG_CONSTRAINTS_DR,
|
ZYDIS_REG_CONSTRAINTS_DR,
|
||||||
ZYDIS_REG_CONSTRAINTS_MASK,
|
ZYDIS_REG_CONSTRAINTS_MASK,
|
||||||
ZYDIS_REG_CONSTRAINTS_BND,
|
ZYDIS_REG_CONSTRAINTS_BND,
|
||||||
|
ZYDIS_REG_CONSTRAINTS_VSIB,
|
||||||
|
|
||||||
ZYDIS_REG_CONSTRAINTS_MAX_VALUE = ZYDIS_REG_CONSTRAINTS_BND,
|
ZYDIS_REG_CONSTRAINTS_MAX_VALUE = ZYDIS_REG_CONSTRAINTS_VSIB,
|
||||||
ZYDIS_REG_CONSTRAINTS_MIN_BITS = 4
|
ZYDIS_REG_CONSTRAINTS_MIN_BITS = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -595,7 +596,7 @@ enum ZydisMaskPolicies
|
||||||
|
|
||||||
#define ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR_INTEL \
|
#define ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR_INTEL \
|
||||||
ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR; \
|
ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR; \
|
||||||
ZydisBool hasVSIB ZYDIS_BITFIELD( 1)
|
ZydisBool isGather ZYDIS_BITFIELD( 1)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Defines the `ZydisInstructionDefinition` struct.
|
* @brief Defines the `ZydisInstructionDefinition` struct.
|
||||||
|
|
|
@ -1337,31 +1337,14 @@ static ZydisStatus ZydisDecodeOperandRegister(ZydisDecodedInstruction* instructi
|
||||||
{
|
{
|
||||||
operand->reg.value = ZYDIS_REGISTER_AL + registerId;
|
operand->reg.value = ZYDIS_REGISTER_AL + registerId;
|
||||||
}
|
}
|
||||||
if (operand->reg.value > ZYDIS_REGISTER_R15B)
|
|
||||||
{
|
|
||||||
return ZYDIS_STATUS_BAD_REGISTER;
|
|
||||||
}
|
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
operand->reg.value = ZydisRegisterEncode(registerClass, registerId);
|
operand->reg.value = ZydisRegisterEncode(registerClass, registerId);
|
||||||
if (!operand->reg.value)
|
ZYDIS_ASSERT(operand->reg.value);
|
||||||
|
/*if (!operand->reg.value)
|
||||||
{
|
{
|
||||||
return ZYDIS_STATUS_BAD_REGISTER;
|
return ZYDIS_STATUS_BAD_REGISTER;
|
||||||
}
|
}*/
|
||||||
if ((operand->reg.value == ZYDIS_REGISTER_CR1) ||
|
|
||||||
((operand->reg.value >= ZYDIS_REGISTER_CR5) &&
|
|
||||||
(operand->reg.value <= ZYDIS_REGISTER_CR15) &&
|
|
||||||
(operand->reg.value != ZYDIS_REGISTER_CR8)))
|
|
||||||
{
|
|
||||||
return ZYDIS_STATUS_BAD_REGISTER;
|
|
||||||
}
|
|
||||||
if ((operand->reg.value == ZYDIS_REGISTER_DR4) ||
|
|
||||||
(operand->reg.value == ZYDIS_REGISTER_DR5) ||
|
|
||||||
((operand->reg.value >= ZYDIS_REGISTER_DR8) &&
|
|
||||||
(operand->reg.value <= ZYDIS_REGISTER_DR15)))
|
|
||||||
{
|
|
||||||
return ZYDIS_STATUS_BAD_REGISTER;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ZYDIS_STATUS_SUCCESS;
|
return ZYDIS_STATUS_SUCCESS;
|
||||||
|
@ -4017,11 +4000,14 @@ static ZydisStatus ZydisCheckErrorConditions(ZydisDecoderContext* context,
|
||||||
{
|
{
|
||||||
const ZydisRegisterConstraint constrREG = definition->constrREG;
|
const ZydisRegisterConstraint constrREG = definition->constrREG;
|
||||||
const ZydisRegisterConstraint constrRM = definition->constrRM;
|
const ZydisRegisterConstraint constrRM = definition->constrRM;
|
||||||
|
// We set this to `NONE` instead of `UNUSED` to save up some unnecessary runtime checks
|
||||||
ZydisRegisterConstraint constrNDSNDD = ZYDIS_REG_CONSTRAINTS_NONE;
|
ZydisRegisterConstraint constrNDSNDD = ZYDIS_REG_CONSTRAINTS_NONE;
|
||||||
ZydisBool hasVSIB = ZYDIS_FALSE;
|
ZydisBool hasVSIB = ZYDIS_FALSE;
|
||||||
|
ZydisBool isGather = ZYDIS_FALSE;
|
||||||
#if !defined(ZYDIS_DISABLE_EVEX) || !defined(ZYDIS_DISABLE_MVEX)
|
#if !defined(ZYDIS_DISABLE_EVEX) || !defined(ZYDIS_DISABLE_MVEX)
|
||||||
ZydisMaskPolicy maskPolicy = ZYDIS_MASK_POLICY_INVALID;
|
ZydisMaskPolicy maskPolicy = ZYDIS_MASK_POLICY_INVALID;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
switch (instruction->encoding)
|
switch (instruction->encoding)
|
||||||
{
|
{
|
||||||
case ZYDIS_INSTRUCTION_ENCODING_DEFAULT:
|
case ZYDIS_INSTRUCTION_ENCODING_DEFAULT:
|
||||||
|
@ -4057,7 +4043,7 @@ static ZydisStatus ZydisCheckErrorConditions(ZydisDecoderContext* context,
|
||||||
const ZydisInstructionDefinitionVEX* def =
|
const ZydisInstructionDefinitionVEX* def =
|
||||||
(const ZydisInstructionDefinitionVEX*)definition;
|
(const ZydisInstructionDefinitionVEX*)definition;
|
||||||
constrNDSNDD = def->constrNDSNDD;
|
constrNDSNDD = def->constrNDSNDD;
|
||||||
hasVSIB = def->hasVSIB;
|
isGather = def->isGather;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ZYDIS_INSTRUCTION_ENCODING_EVEX:
|
case ZYDIS_INSTRUCTION_ENCODING_EVEX:
|
||||||
|
@ -4066,7 +4052,7 @@ static ZydisStatus ZydisCheckErrorConditions(ZydisDecoderContext* context,
|
||||||
const ZydisInstructionDefinitionEVEX* def =
|
const ZydisInstructionDefinitionEVEX* def =
|
||||||
(const ZydisInstructionDefinitionEVEX*)definition;
|
(const ZydisInstructionDefinitionEVEX*)definition;
|
||||||
constrNDSNDD = def->constrNDSNDD;
|
constrNDSNDD = def->constrNDSNDD;
|
||||||
hasVSIB = def->hasVSIB;
|
isGather = def->isGather;
|
||||||
maskPolicy = def->maskPolicy;
|
maskPolicy = def->maskPolicy;
|
||||||
|
|
||||||
// Check for invalid zero-mask
|
// Check for invalid zero-mask
|
||||||
|
@ -4085,7 +4071,7 @@ static ZydisStatus ZydisCheckErrorConditions(ZydisDecoderContext* context,
|
||||||
const ZydisInstructionDefinitionMVEX* def =
|
const ZydisInstructionDefinitionMVEX* def =
|
||||||
(const ZydisInstructionDefinitionMVEX*)definition;
|
(const ZydisInstructionDefinitionMVEX*)definition;
|
||||||
constrNDSNDD = def->constrNDSNDD;
|
constrNDSNDD = def->constrNDSNDD;
|
||||||
hasVSIB = def->hasVSIB;
|
isGather = def->isGather;
|
||||||
maskPolicy = def->maskPolicy;
|
maskPolicy = def->maskPolicy;
|
||||||
|
|
||||||
// Check for invalid MVEX.SSS values
|
// Check for invalid MVEX.SSS values
|
||||||
|
@ -4162,8 +4148,8 @@ static ZydisStatus ZydisCheckErrorConditions(ZydisDecoderContext* context,
|
||||||
// Validate register constraints
|
// Validate register constraints
|
||||||
switch (constrREG)
|
switch (constrREG)
|
||||||
{
|
{
|
||||||
case ZYDIS_REG_CONSTRAINTS_NONE:
|
|
||||||
case ZYDIS_REG_CONSTRAINTS_UNUSED:
|
case ZYDIS_REG_CONSTRAINTS_UNUSED:
|
||||||
|
case ZYDIS_REG_CONSTRAINTS_NONE:
|
||||||
break;
|
break;
|
||||||
case ZYDIS_REG_CONSTRAINTS_GPR:
|
case ZYDIS_REG_CONSTRAINTS_GPR:
|
||||||
if (context->cache.R2)
|
if (context->cache.R2)
|
||||||
|
@ -4180,7 +4166,7 @@ static ZydisStatus ZydisCheckErrorConditions(ZydisDecoderContext* context,
|
||||||
ZYDIS_FALLTHROUGH;
|
ZYDIS_FALLTHROUGH;
|
||||||
case ZYDIS_REG_CONSTRAINTS_SR:
|
case ZYDIS_REG_CONSTRAINTS_SR:
|
||||||
{
|
{
|
||||||
if (instruction->raw.modrm.reg > 6)
|
if (instruction->raw.modrm.reg > 5)
|
||||||
{
|
{
|
||||||
return ZYDIS_STATUS_BAD_REGISTER;
|
return ZYDIS_STATUS_BAD_REGISTER;
|
||||||
}
|
}
|
||||||
|
@ -4230,8 +4216,8 @@ static ZydisStatus ZydisCheckErrorConditions(ZydisDecoderContext* context,
|
||||||
}
|
}
|
||||||
switch (constrRM)
|
switch (constrRM)
|
||||||
{
|
{
|
||||||
case ZYDIS_REG_CONSTRAINTS_NONE:
|
|
||||||
case ZYDIS_REG_CONSTRAINTS_UNUSED:
|
case ZYDIS_REG_CONSTRAINTS_UNUSED:
|
||||||
|
case ZYDIS_REG_CONSTRAINTS_NONE:
|
||||||
break;
|
break;
|
||||||
case ZYDIS_REG_CONSTRAINTS_SR_DEST:
|
case ZYDIS_REG_CONSTRAINTS_SR_DEST:
|
||||||
// `ZYDIS_REGISTER_CR` is not allowed as `MOV` target
|
// `ZYDIS_REGISTER_CR` is not allowed as `MOV` target
|
||||||
|
@ -4249,7 +4235,6 @@ static ZydisStatus ZydisCheckErrorConditions(ZydisDecoderContext* context,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ZYDIS_REG_CONSTRAINTS_MASK:
|
case ZYDIS_REG_CONSTRAINTS_MASK:
|
||||||
// TODO: `.X`?
|
|
||||||
break;
|
break;
|
||||||
case ZYDIS_REG_CONSTRAINTS_BND:
|
case ZYDIS_REG_CONSTRAINTS_BND:
|
||||||
ZYDIS_ASSERT(!context->cache.X);
|
ZYDIS_ASSERT(!context->cache.X);
|
||||||
|
@ -4258,13 +4243,14 @@ static ZydisStatus ZydisCheckErrorConditions(ZydisDecoderContext* context,
|
||||||
return ZYDIS_STATUS_BAD_REGISTER;
|
return ZYDIS_STATUS_BAD_REGISTER;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ZYDIS_REG_CONSTRAINTS_VSIB:
|
||||||
|
hasVSIB = ZYDIS_TRUE;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ZYDIS_UNREACHABLE;
|
ZYDIS_UNREACHABLE;
|
||||||
}
|
}
|
||||||
switch (constrNDSNDD)
|
switch (constrNDSNDD)
|
||||||
{
|
{
|
||||||
case ZYDIS_REG_CONSTRAINTS_NONE:
|
|
||||||
break;
|
|
||||||
case ZYDIS_REG_CONSTRAINTS_UNUSED:
|
case ZYDIS_REG_CONSTRAINTS_UNUSED:
|
||||||
// `.vvvv` is not allowed, if the instruction does not encode a NDS/NDD operand
|
// `.vvvv` is not allowed, if the instruction does not encode a NDS/NDD operand
|
||||||
if (context->cache.v_vvvv & 0x0F)
|
if (context->cache.v_vvvv & 0x0F)
|
||||||
|
@ -4277,6 +4263,10 @@ static ZydisStatus ZydisCheckErrorConditions(ZydisDecoderContext* context,
|
||||||
return ZYDIS_STATUS_BAD_REGISTER;
|
return ZYDIS_STATUS_BAD_REGISTER;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ZYDIS_REG_CONSTRAINTS_NONE:
|
||||||
|
ZYDIS_ASSERT(!hasVSIB || ((instruction->encoding != ZYDIS_INSTRUCTION_ENCODING_EVEX) &&
|
||||||
|
(instruction->encoding != ZYDIS_INSTRUCTION_ENCODING_MVEX)));
|
||||||
|
break;
|
||||||
case ZYDIS_REG_CONSTRAINTS_GPR:
|
case ZYDIS_REG_CONSTRAINTS_GPR:
|
||||||
// `.v'` is invalid for GPR-registers
|
// `.v'` is invalid for GPR-registers
|
||||||
if (context->cache.V2)
|
if (context->cache.V2)
|
||||||
|
@ -4295,8 +4285,9 @@ static ZydisStatus ZydisCheckErrorConditions(ZydisDecoderContext* context,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check gather/scatter registers
|
// Check gather/scatter registers
|
||||||
if (hasVSIB)
|
if (isGather)
|
||||||
{
|
{
|
||||||
|
ZYDIS_ASSERT(hasVSIB);
|
||||||
ZYDIS_ASSERT(instruction->raw.modrm.mod != 3);
|
ZYDIS_ASSERT(instruction->raw.modrm.mod != 3);
|
||||||
ZYDIS_ASSERT(instruction->raw.modrm.rm == 4);
|
ZYDIS_ASSERT(instruction->raw.modrm.rm == 4);
|
||||||
const ZydisU8 dest = instruction->raw.modrm.reg | (context->cache.R << 3) |
|
const ZydisU8 dest = instruction->raw.modrm.reg | (context->cache.R << 3) |
|
||||||
|
@ -4308,12 +4299,16 @@ static ZydisStatus ZydisCheckErrorConditions(ZydisDecoderContext* context,
|
||||||
switch (instruction->encoding)
|
switch (instruction->encoding)
|
||||||
{
|
{
|
||||||
case ZYDIS_INSTRUCTION_ENCODING_VEX:
|
case ZYDIS_INSTRUCTION_ENCODING_VEX:
|
||||||
ZYDIS_ASSERT(!constrREG && !constrRM && !constrNDSNDD);
|
ZYDIS_ASSERT((constrREG == ZYDIS_REG_CONSTRAINTS_NONE) &&
|
||||||
|
(constrRM == ZYDIS_REG_CONSTRAINTS_VSIB) &&
|
||||||
|
(constrNDSNDD == ZYDIS_REG_CONSTRAINTS_NONE));
|
||||||
mask = context->cache.v_vvvv;
|
mask = context->cache.v_vvvv;
|
||||||
break;
|
break;
|
||||||
case ZYDIS_INSTRUCTION_ENCODING_EVEX:
|
case ZYDIS_INSTRUCTION_ENCODING_EVEX:
|
||||||
case ZYDIS_INSTRUCTION_ENCODING_MVEX:
|
case ZYDIS_INSTRUCTION_ENCODING_MVEX:
|
||||||
ZYDIS_ASSERT(!constrREG && !constrRM && constrNDSNDD == ZYDIS_REG_CONSTRAINTS_UNUSED);
|
ZYDIS_ASSERT((constrREG == ZYDIS_REG_CONSTRAINTS_NONE) &&
|
||||||
|
(constrRM == ZYDIS_REG_CONSTRAINTS_VSIB) &&
|
||||||
|
(constrNDSNDD == ZYDIS_REG_CONSTRAINTS_UNUSED));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ZYDIS_UNREACHABLE;
|
ZYDIS_UNREACHABLE;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue