about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2020-02-05 10:33:28 -0800
committerKartik Agaram <vc@akkartik.com>2020-02-05 14:57:52 -0800
commit9ee351f37fbf78aa408f60c0d2c7ec49e625f109 (patch)
treeed55ef4c9cfcbedefda64767164855b576748c75
parentb9d666eff51659a62dab7b746e5ae40431127e9b (diff)
downloadmu-9ee351f37fbf78aa408f60c0d2c7ec49e625f109.tar.gz
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.
-rw-r--r--010---vm.cc2
-rw-r--r--013direct_addressing.cc2
-rw-r--r--014indirect_addressing.cc2
-rw-r--r--015immediate_addressing.cc2
-rw-r--r--021byte_addressing.cc6
5 files changed, 7 insertions, 7 deletions
diff --git a/010---vm.cc b/010---vm.cc
index a0724760..472990a0 100644
--- a/010---vm.cc
+++ b/010---vm.cc
@@ -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);
diff --git a/013direct_addressing.cc b/013direct_addressing.cc
index 38e00665..729b4d08 100644
--- a/013direct_addressing.cc
+++ b/013direct_addressing.cc
@@ -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;
 }
diff --git a/014indirect_addressing.cc b/014indirect_addressing.cc
index 9c50c129..19d4d509 100644
--- a/014indirect_addressing.cc
+++ b/014indirect_addressing.cc
@@ -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;
     }
   }
diff --git a/015immediate_addressing.cc b/015immediate_addressing.cc
index c264d5d3..a2923b7a 100644
--- a/015immediate_addressing.cc
+++ b/015immediate_addressing.cc
@@ -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;
 }
 
diff --git a/021byte_addressing.cc b/021byte_addressing.cc
index a0b36776..36287e38 100644
--- a/021byte_addressing.cc
+++ b/021byte_addressing.cc
@@ -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;
 }