x86seg.c: Make sure not to read beyond the end of the stack segment on stack transfers, fixes erroneous page faults when transferring 16-bit stacks to 32-bit stacks, fixes OS/2 2.0 build 6.141.
This commit is contained in:
@@ -896,7 +896,7 @@ loadcscall(uint16_t seg)
|
|||||||
uint32_t oldsp;
|
uint32_t oldsp;
|
||||||
uint32_t newsp;
|
uint32_t newsp;
|
||||||
uint32_t oldsp2;
|
uint32_t oldsp2;
|
||||||
uint16_t tempw;
|
uint32_t oldss_limit_high = cpu_state.seg_ss.limit_high;
|
||||||
const x86seg *dt;
|
const x86seg *dt;
|
||||||
|
|
||||||
if ((msw & 1) && !(cpu_state.eflags & VM_FLAG)) {
|
if ((msw & 1) && !(cpu_state.eflags & VM_FLAG)) {
|
||||||
@@ -1125,7 +1125,31 @@ loadcscall(uint16_t seg)
|
|||||||
}
|
}
|
||||||
if (count) {
|
if (count) {
|
||||||
while (count--) {
|
while (count--) {
|
||||||
|
uint32_t temp_val;
|
||||||
|
switch (oldss_limit_high - oldsp - (count << 2)) {
|
||||||
|
default:
|
||||||
|
case 3:
|
||||||
|
/* We are at least an entire DWORD away from the limit,
|
||||||
|
read long. */
|
||||||
PUSHL(readmeml(oldssbase, oldsp + (count << 2)));
|
PUSHL(readmeml(oldssbase, oldsp + (count << 2)));
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
/* We are 3 bytes away from the limit,
|
||||||
|
read word + byte. */
|
||||||
|
temp_val = readmemw(oldssbase, oldsp + (count << 2));
|
||||||
|
temp_val |= (readmemb(oldssbase, oldsp +
|
||||||
|
(count << 2) + 2) << 16);
|
||||||
|
PUSHL(temp_val);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
/* We are a WORD away from the limit, read word. */
|
||||||
|
PUSHL(readmemw(oldssbase, oldsp + (count << 2)));
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
/* We are a BYTE away from the limit, read byte. */
|
||||||
|
PUSHL(readmemb(oldssbase, oldsp + (count << 2)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (cpu_state.abrt) {
|
if (cpu_state.abrt) {
|
||||||
SS = oldss;
|
SS = oldss;
|
||||||
ESP = oldsp2;
|
ESP = oldsp2;
|
||||||
@@ -1152,9 +1176,20 @@ loadcscall(uint16_t seg)
|
|||||||
x86seg_log("Write SP to %04X:%04X\n", SS, SP);
|
x86seg_log("Write SP to %04X:%04X\n", SS, SP);
|
||||||
if (count) {
|
if (count) {
|
||||||
while (count--) {
|
while (count--) {
|
||||||
tempw = readmemw(oldssbase, (oldsp & 0xffff) + (count << 1));
|
switch (oldss_limit_high - (oldsp & 0xffff) - (count << 1)) {
|
||||||
x86seg_log("PUSH %04X\n", tempw);
|
default:
|
||||||
PUSHW(tempw);
|
case 1:
|
||||||
|
/* We are at least an entire WORD away from the limit,
|
||||||
|
read word. */
|
||||||
|
PUSHW(readmemw(oldssbase, (oldsp & 0xffff) +
|
||||||
|
(count << 1)));
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
/* We are a BYTE away from the limit, read byte. */
|
||||||
|
PUSHW(readmemb(oldssbase, (oldsp & 0xffff) +
|
||||||
|
(count << 1)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (cpu_state.abrt) {
|
if (cpu_state.abrt) {
|
||||||
SS = oldss;
|
SS = oldss;
|
||||||
ESP = oldsp2;
|
ESP = oldsp2;
|
||||||
|
Reference in New Issue
Block a user