mirror of
https://github.com/bitdefender/bddisasm.git
synced 2024-11-18 05:28:09 +00:00
Fix potential division error in bdshemu, when the destination operand is not large enough to hold the result.
This commit is contained in:
parent
d61a6fa5dd
commit
ea28907359
@ -663,7 +663,7 @@ ShemuSetGprValue(
|
||||
if (High8)
|
||||
{
|
||||
// AH, CH, DH or BH accessed.
|
||||
*((uint8_t *)(&Context->Registers.RegRax + Reg - 4) + 1) = Value & 0xff;
|
||||
*((uint8_t *)(&Context->Registers.RegRax + Reg - 4) + 1) = Value & 0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1509,6 +1509,116 @@ ShemuMultiply64Signed(
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// ShemuCheckDiv
|
||||
//
|
||||
static bool
|
||||
ShemuCheckDiv(
|
||||
uint64_t Divident,
|
||||
uint64_t Divider,
|
||||
uint8_t Size // The size of the Source (Divider). The Divident is twice as large.
|
||||
)
|
||||
{
|
||||
// Returns true if all checks are OK, and Divident / Divider will not cause #DE.
|
||||
|
||||
if (Divider == 0)
|
||||
{
|
||||
// Division by zero.
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the result won't fit in the destination, a #DE would be generated.
|
||||
switch (Size)
|
||||
{
|
||||
case 1:
|
||||
if (((Divident >> 8) & 0xFF) >= Divider)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (((Divident >> 16) & 0xFFFF) >= Divider)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
if (((Divident >> 32) & 0xFFFFFFFF) >= Divider)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// 64 bit source division is not supported.
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// ShemuCheckIdiv
|
||||
//
|
||||
static bool
|
||||
ShemuCheckIdiv(
|
||||
int64_t Divident,
|
||||
int64_t Divider,
|
||||
uint8_t Size // The size of the Source (Divider).
|
||||
)
|
||||
{
|
||||
bool neg1, neg2;
|
||||
uint64_t quotient, max;
|
||||
|
||||
neg1 = Divident < 0;
|
||||
neg2 = Divider < 0;
|
||||
|
||||
if (neg1)
|
||||
{
|
||||
Divident = -Divident;
|
||||
}
|
||||
|
||||
if (neg2)
|
||||
{
|
||||
Divider = -Divider;
|
||||
}
|
||||
|
||||
// Do checks when dividing positive values.
|
||||
if (!ShemuCheckDiv(Divident, Divider, Size))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the positive quotient.
|
||||
quotient = (uint64_t)Divident / (uint64_t)Divider;
|
||||
|
||||
max = (Size == 1) ? 0x80 : (Size == 2) ? 0x8000 : (Size == 4) ? 0x80000000 : 0x8000000000000000;
|
||||
|
||||
if (neg1 ^ neg2)
|
||||
{
|
||||
// The Divident and the Divider have different signs, the quotient must be negative. If it's positive => #DE.
|
||||
if (ND_GET_SIGN(Size, quotient) && quotient != max)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Both the Divident and the Divider are positive/negative, so a positive result must be produced. If it's
|
||||
// negative => #DE.
|
||||
if (ND_GET_SIGN(Size, quotient))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// ShemuPrintContext
|
||||
//
|
||||
@ -2417,22 +2527,31 @@ ShemuEmulate(
|
||||
|
||||
if (src.Size == 1)
|
||||
{
|
||||
if (src.Value.Bytes[0] == 0)
|
||||
{
|
||||
// Division by zero, force emulation stop.
|
||||
stop = true;
|
||||
break;
|
||||
}
|
||||
uint16_t divident;
|
||||
|
||||
divident = (uint16_t)Context->Registers.RegRax;
|
||||
|
||||
if (ND_INS_DIV == Context->Instruction.Instruction)
|
||||
{
|
||||
res.Value.Bytes[0] = (uint8_t)((uint16_t)Context->Registers.RegRax / (uint8_t)src.Value.Bytes[0]);
|
||||
res.Value.Bytes[1] = (uint8_t)((uint16_t)Context->Registers.RegRax % (uint8_t)src.Value.Bytes[0]);
|
||||
if (!ShemuCheckDiv(divident, src.Value.Bytes[0], 1))
|
||||
{
|
||||
stop = true;
|
||||
break;
|
||||
}
|
||||
|
||||
res.Value.Bytes[0] = (uint8_t)(divident / src.Value.Bytes[0]);
|
||||
res.Value.Bytes[1] = (uint8_t)(divident % src.Value.Bytes[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
res.Value.Bytes[0] = (int8_t)((int16_t)Context->Registers.RegRax / (int8_t)src.Value.Bytes[0]);
|
||||
res.Value.Bytes[1] = (int8_t)((int16_t)Context->Registers.RegRax % (int8_t)src.Value.Bytes[0]);
|
||||
if (!ShemuCheckIdiv((int64_t)(int16_t)divident, (int64_t)(int8_t)src.Value.Bytes[0], 1))
|
||||
{
|
||||
stop = true;
|
||||
break;
|
||||
}
|
||||
|
||||
res.Value.Bytes[0] = (int8_t)((int16_t)divident / (int8_t)src.Value.Bytes[0]);
|
||||
res.Value.Bytes[1] = (int8_t)((int16_t)divident % (int8_t)src.Value.Bytes[0]);
|
||||
}
|
||||
|
||||
// Result in AX (AL - quotient, AH - reminder).
|
||||
@ -2442,23 +2561,28 @@ ShemuEmulate(
|
||||
{
|
||||
uint32_t divident;
|
||||
|
||||
if (src.Value.Words[0] == 0)
|
||||
{
|
||||
// Division by zero, force emulation stop.
|
||||
stop = true;
|
||||
break;
|
||||
}
|
||||
|
||||
divident = ((uint32_t)(uint16_t)Context->Registers.RegRdx << 16) |
|
||||
(uint32_t)(uint16_t)Context->Registers.RegRax;
|
||||
|
||||
if (ND_INS_DIV == Context->Instruction.Instruction)
|
||||
{
|
||||
res.Value.Words[0] = (uint16_t)((uint32_t)divident / (uint16_t)src.Value.Words[0]);
|
||||
res.Value.Words[1] = (uint16_t)((uint32_t)divident % (uint16_t)src.Value.Words[0]);
|
||||
if (!ShemuCheckDiv(divident, src.Value.Words[0], 2))
|
||||
{
|
||||
stop = true;
|
||||
break;
|
||||
}
|
||||
|
||||
res.Value.Words[0] = (uint16_t)(divident / src.Value.Words[0]);
|
||||
res.Value.Words[1] = (uint16_t)(divident % src.Value.Words[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ShemuCheckIdiv((int64_t)(int32_t)divident, (int64_t)(int16_t)src.Value.Words[0], 2))
|
||||
{
|
||||
stop = true;
|
||||
break;
|
||||
}
|
||||
|
||||
res.Value.Words[0] = (int16_t)((int32_t)divident / (int16_t)src.Value.Words[0]);
|
||||
res.Value.Words[1] = (int16_t)((int32_t)divident % (int16_t)src.Value.Words[0]);
|
||||
}
|
||||
@ -2470,23 +2594,28 @@ ShemuEmulate(
|
||||
{
|
||||
uint64_t divident;
|
||||
|
||||
if (src.Value.Dwords[0] == 0)
|
||||
{
|
||||
// Division by zero, force emulation stop.
|
||||
stop = true;
|
||||
break;
|
||||
}
|
||||
|
||||
divident = ((uint64_t)(uint32_t)Context->Registers.RegRdx << 32) |
|
||||
(uint64_t)(uint32_t)Context->Registers.RegRax;
|
||||
|
||||
if (ND_INS_DIV == Context->Instruction.Instruction)
|
||||
{
|
||||
res.Value.Dwords[0] = (uint32_t)((uint64_t)divident / (uint32_t)src.Value.Dwords[0]);
|
||||
res.Value.Dwords[1] = (uint32_t)((uint64_t)divident % (uint32_t)src.Value.Dwords[0]);
|
||||
if (!ShemuCheckDiv(divident, src.Value.Dwords[0], 4))
|
||||
{
|
||||
stop = true;
|
||||
break;
|
||||
}
|
||||
|
||||
res.Value.Dwords[0] = (uint32_t)(divident / src.Value.Dwords[0]);
|
||||
res.Value.Dwords[1] = (uint32_t)(divident % src.Value.Dwords[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ShemuCheckIdiv((int64_t)divident, (int64_t)(int32_t)src.Value.Dwords[0], 4))
|
||||
{
|
||||
stop = true;
|
||||
break;
|
||||
}
|
||||
|
||||
res.Value.Dwords[0] = (int32_t)((int64_t)divident / (int32_t)src.Value.Dwords[0]);
|
||||
res.Value.Dwords[1] = (int32_t)((int64_t)divident % (int32_t)src.Value.Dwords[0]);
|
||||
}
|
||||
|
BIN
bdshemu_test/basic/test_64_div2
Normal file
BIN
bdshemu_test/basic/test_64_div2
Normal file
Binary file not shown.
6
bdshemu_test/basic/test_64_div2.asm
Normal file
6
bdshemu_test/basic/test_64_div2.asm
Normal file
@ -0,0 +1,6 @@
|
||||
bits 64
|
||||
|
||||
MOV edx, 0x80000000
|
||||
NOT edi
|
||||
IDIV edi
|
||||
RETN
|
19
bdshemu_test/basic/test_64_div2.result
Normal file
19
bdshemu_test/basic/test_64_div2.result
Normal file
@ -0,0 +1,19 @@
|
||||
RAX = 0x0000000000000000 RCX = 0x0000000000000000 RDX = 0x0000000000000000 RBX = 0x0000000000000000
|
||||
RSP = 0x0000000000101000 RBP = 0x0000000000000000 RSI = 0x0000000000000000 RDI = 0x0000000000000000
|
||||
R8 = 0x0000000000000000 R9 = 0x0000000000000000 R10 = 0x0000000000000000 R11 = 0x0000000000000000
|
||||
R12 = 0x0000000000000000 R13 = 0x0000000000000000 R14 = 0x0000000000000000 R15 = 0x0000000000000000
|
||||
RIP = 0x0000000000200000 RFLAGS = 0x0000000000000202
|
||||
Emulating: 0x0000000000200000 MOV edx, 0x80000000
|
||||
RAX = 0x0000000000000000 RCX = 0x0000000000000000 RDX = 0x0000000080000000 RBX = 0x0000000000000000
|
||||
RSP = 0x0000000000101000 RBP = 0x0000000000000000 RSI = 0x0000000000000000 RDI = 0x0000000000000000
|
||||
R8 = 0x0000000000000000 R9 = 0x0000000000000000 R10 = 0x0000000000000000 R11 = 0x0000000000000000
|
||||
R12 = 0x0000000000000000 R13 = 0x0000000000000000 R14 = 0x0000000000000000 R15 = 0x0000000000000000
|
||||
RIP = 0x0000000000200005 RFLAGS = 0x0000000000000202
|
||||
Emulating: 0x0000000000200005 NOT edi
|
||||
RAX = 0x0000000000000000 RCX = 0x0000000000000000 RDX = 0x0000000080000000 RBX = 0x0000000000000000
|
||||
RSP = 0x0000000000101000 RBP = 0x0000000000000000 RSI = 0x0000000000000000 RDI = 0x00000000ffffffff
|
||||
R8 = 0x0000000000000000 R9 = 0x0000000000000000 R10 = 0x0000000000000000 R11 = 0x0000000000000000
|
||||
R12 = 0x0000000000000000 R13 = 0x0000000000000000 R14 = 0x0000000000000000 R15 = 0x0000000000000000
|
||||
RIP = 0x0000000000200007 RFLAGS = 0x0000000000000202
|
||||
Emulating: 0x0000000000200007 IDIV edi
|
||||
Emulation terminated with status 0x0000000a, flags: 0x0, 0 NOPs
|
@ -7,6 +7,6 @@
|
||||
|
||||
#define DISASM_VERSION_MAJOR 1
|
||||
#define DISASM_VERSION_MINOR 28
|
||||
#define DISASM_VERSION_REVISION 1
|
||||
#define DISASM_VERSION_REVISION 2
|
||||
|
||||
#endif // DISASM_VER_H
|
||||
|
@ -12,7 +12,7 @@ from setuptools import find_packages, setup, Command, Extension, Distribution
|
||||
from codecs import open
|
||||
|
||||
VERSION = (0, 1, 3)
|
||||
LIBRARY_VERSION = (1, 28, 1)
|
||||
LIBRARY_VERSION = (1, 28, 2)
|
||||
LIBRARY_INSTRUX_SIZE = 856
|
||||
|
||||
packages = ['pybddisasm']
|
||||
|
Loading…
Reference in New Issue
Block a user