VOGONS


First post, by Psyraven

User metadata
Rank Newbie
Rank
Newbie

Hi all

I noticed that r4481 broke the installer of Pacific Strike in some subtle ways. The installer reads the entirety of a 44 kb file into a buffer and then stores the number of read bytes in memory. Before r4481 all was fine but after that, the number of read bytes are written into a location that is INSIDE the read buffer. So the installer ends up writing a file with 2 corrupted bytes to the hard disk. I noticed that just before it reads the file with INT21 0x3f it resizes a memory block with INT21 0x4a. And when I add (reg_ah != 0x4a) to the list of operations that skip the /* Save registers */ code (which was added by r4481), the installer works correctly again.

I'm pretty sure the file read INT21 op being right after the memory block resize INT21 op is related, I just don't quite understand how the saving of registers and stuff is supposed to work.

Here's the result of some logging I added to the code, first two are in DOS_21Handler for op 0x4a (Resize memory block) and op 0x3f (READ Read from file or device), and last is in the MOV instruction whenever the value 0xAE60 is being written:

- BEFORE r4481:
[DOS21] RESIZED MEMORY BLOCK SEGMENT 0x192 FROM 0xD40 BLOCKS (@ 0x1920 ~ 0xED20) TO 0x1840 BLOCKS (@ 0x1920 ~ 0x19D20)
[DOS21] FILE READ 0xAE60 BYTES INTO BUFFER 0xEB14 ~ 0x19974
[MOV] WRITING 0xAE60 to 0x722C2 <--- Address well outside the file read buffer

- AFTER r4481:
[DOS21] RESIZED MEMORY BLOCK SEGMENT 0x192 FROM 0xD40 BLOCKS (@ 0x1920 ~ 0xED20) TO 0x1840 BLOCKS (@ 0x1920 ~ 0x19D20)
[DOS21] FILE READ 0xAE60 BYTES INTO BUFFER 0xEB14 ~ 0x19974
[MOV] WRITING 0xAE60 to 0x11ED2 <--- Address inside the file read buffer

So having the /* Save registers */ code at the top of DOS_21Handler being done for op 0x4a (Resize memory block) seems to cause the installer program to end up writing the number of read bytes to 0x11ED2, which after the memory resize is now inside the read file buffer (0xEB14 ~ 0x19974).

Reply 1 of 2, by ripsaw8080

User metadata
Rank DOSBox Author
Rank
DOSBox Author

Thanks for looking into the issue.

Most DOS functions push registers on entry and pop them on return -- there are a few exceptions, but function 4A is not one of them.

Real DOS usually writes return register values on the stack, to be popped into registers on return; however, DOSBox's internal DOS emulation doesn't use registers for its machinations as real DOS does and just sets return register values directly. The commit in question pushes the function entry register values onto the stack to support buggy programs that incorrectly use "dead" stack space as variable data, but the values are only popped into registers for a process termination.

When I run the install program in MS-DOS 6.22, the AE60 word value is written over some of the installer's text string data, which is obviously dysfunctional, but causes no noticeable problem. So, the install program is apparently buggy, taking a bad pointer from what I called "dead" stack space, and the commit has caused the program's bug to become noticeable where it was not before.

Using the LOADFIX command before running the installer keeps the problematic MOV ES:[BX],AX from overwriting anything important in my testing.

Reply 2 of 2, by Psyraven

User metadata
Rank Newbie
Rank
Newbie

Wow, thank you so much for the fast in-depth response!

It did cross my mind that the bug might be in the installer itself but when I tried it in MS-DOS 6.22 (via VMWare) and a DOSBox build from 2020, it was able to copy its files INSTALL.EXE and PKUNZIP.EXE with no bytes changed. So I somehow convinced myself that r4481 was the culprit. It's interesting how depending on the size of the DOS environment block one can get it to overwrite different parts during the copying and in some cases it will write a defective PKUNZIP.EXE that freezes when being run by the installer afterwards, which is what made me notice it in the first place.

Anyway, sorry for bringing up a non-issue, consider this closed. Thanks again.