5983 - fix an emulator bounds-check bug

It was possible for an instruction to write out of bounds of the memory
data structure. Most of the time this worked fine. However if the block
ever got resized and moved the out-of-bounds bytes no longer went along.
This commit is contained in:
Kartik Agaram 2020-02-05 10:33:28 -08:00
parent b9d666eff5
commit 9ee351f37f
5 changed files with 7 additions and 7 deletions

View File

@ -108,7 +108,7 @@ struct vma {
uint8_t& data(uint32_t a) {
assert(match(a));
uint32_t result_index = a-start;
if (_data.size() <= result_index) {
if (_data.size() <= result_index+/*largest word size that can be accessed in one instruction*/sizeof(int)) {
const int align = 0x1000;
uint32_t result_size = result_index + 1; // size needed for result_index to be valid
uint32_t new_size = align_upwards(result_size, align);

View File

@ -986,7 +986,7 @@ case 0x89: { // copy r32 to r/m32
const uint8_t rsrc = (modrm>>3)&0x7;
trace(Callstack_depth+1, "run") << "copy " << rname(rsrc) << " to r/m32" << end();
int32_t* dest = effective_address(modrm);
*dest = Reg[rsrc].i;
*dest = Reg[rsrc].i; // Write multiple elements of vector<uint8_t> at once. Assumes sizeof(int) == 4 on the host as well.
trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << *dest << end();
break;
}

View File

@ -818,7 +818,7 @@ case 0x8f: { // pop stack into r/m32
case 0: {
trace(Callstack_depth+1, "run") << "pop into r/m32" << end();
int32_t* dest = effective_address(modrm);
*dest = pop();
*dest = pop(); // Write multiple elements of vector<uint8_t> at once. Assumes sizeof(int) == 4 on the host as well.
break;
}
}

View File

@ -1235,7 +1235,7 @@ case 0xc7: { // copy imm32 to r32
int32_t* dest = effective_address(modrm);
const int32_t src = next32();
trace(Callstack_depth+1, "run") << "imm32 is 0x" << HEXWORD << src << end();
*dest = src;
*dest = src; // Write multiple elements of vector<uint8_t> at once. Assumes sizeof(int) == 4 on the host as well.
break;
}

View File

@ -68,7 +68,7 @@ case 0x88: { // copy r8 to r/m8
// use unsigned to zero-extend 8-bit value to 32 bits
uint8_t* dest = reinterpret_cast<uint8_t*>(effective_byte_address(modrm));
const uint8_t* src = reg_8bit(rsrc);
*dest = *src;
*dest = *src; // Read/write multiple elements of vector<uint8_t> at once. Assumes sizeof(int) == 4 on the host as well.
trace(Callstack_depth+1, "run") << "storing 0x" << HEXBYTE << NUM(*dest) << end();
break;
}
@ -108,7 +108,7 @@ case 0x8a: { // copy r/m8 to r8
const uint8_t* src = reinterpret_cast<uint8_t*>(effective_byte_address(modrm));
uint8_t* dest = reg_8bit(rdest);
trace(Callstack_depth+1, "run") << "storing 0x" << HEXBYTE << NUM(*src) << end();
*dest = *src;
*dest = *src; // Read/write multiple elements of vector<uint8_t> at once. Assumes sizeof(int) == 4 on the host as well.
const uint8_t rdest_32bit = rdest & 0x3;
trace(Callstack_depth+1, "run") << rname(rdest_32bit) << " now contains 0x" << HEXWORD << Reg[rdest_32bit].u << end();
break;
@ -170,7 +170,7 @@ case 0xc6: { // copy imm8 to r/m8
}
// use unsigned to zero-extend 8-bit value to 32 bits
uint8_t* dest = reinterpret_cast<uint8_t*>(effective_byte_address(modrm));
*dest = src;
*dest = src; // Write multiple elements of vector<uint8_t> at once. Assumes sizeof(int) == 4 on the host as well.
trace(Callstack_depth+1, "run") << "storing 0x" << HEXBYTE << NUM(*dest) << end();
break;
}