-
Notifications
You must be signed in to change notification settings - Fork 166
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CauseWay DOS-extender bugs #1361
Comments
Thank you for your bug report and analysis. |
The code seems a bit strange. Why is there a movzx ebp,bp in it? This will mean that the stack must be less than 64k, otherwise it will read random garbage. I thought CauseWay was a 32-bit DOS extender, and thus should not use a 16-bit stack. Reading the IF flag from the stack implies it's trying to read it from the interrupt frame generated by int 31h, but why would the positions differ based on DpmiEmuSystemsFlags? |
OW uses CauseWay just to create 32-bit zero-based flat binaries, but the original CauseWay extender is more powerful - has support for 16- and 32-bit small model and 32-bit flat model. The CW linker, WL32, is a 16-bit "small" app, for example. |
Another issue of the CauseWay extender: it may "jump into the wild", that is, jump to a code address that is in a conventional memory region that has been released to DOS. Such errors often vary in their appearance, depending on the DOS memory structure. Here's a test case:
This sample generates an exception 0x0B, after allocating - and "clearing" - all free DOS memory. The problem is in file interrup.asm:
Problem with the current code is that it tries to jump to a function in _cwInit - this segment is only present during intialization. |
Thank you again for bug report and issue analysis. |
One more issue about exceptions. The previous test case was about exceptions that generate an error code. Some do not, and CauseWay "tends" to handle those as simple interrupts, that is, if they aren't handled by a protected-mode interrupt handler, they are routed to real-mode. Interrupts 0 and 1 are handled differently, they are always treated as exceptions. This is - at least - a problem with interrupt 6 ( invalid opcode ). This is a fault, not a trap, so it MUST be handled, and it cannot be handled properly in real-mode ( DOS or the V86 monitor program may simply terminate the application, leaving the system in an unstable state ). The - rather simple - test case reveals the problem if the program runs in raw/vcpi mode:
compiled as before with "wcc386 sample.c", linked with "wlink system causeway f sample.obj". As for now, to fix this I'd suggest to handle int 6 - equally to int 0 - as an exception. The default CauseWay exception handler will then terminate the application in protected-mode, with an error msg ( and file cw.err written ). A few other exceptions without error code ( int 4, 5, 7 ) may perhaps need further investigation... This would be the proposed fix, in file interrup.asm:
|
Thanks for your next bug report. |
preparation to fix issue open-watcom#1361
preparation to fix issue open-watcom#1361
Well, yes, it's not exactly what DPMI host do - hdpmi also tries to distinguish between exception 06 and interrupt 06, just to be compatible with what the Win9x host does. But is it really worth it? CauseWay isn't a DPMI host, and the important thing is that an unhandled exc 06 should terminate the app, safely. |
Here's a CauseWay memory management bug that should make the machine either freeze or reboot:
The problem is that the causeway kernel encounters an "out of address space" error here, but is unable to detect it. Proposed fix in memory.asm, proc ExtendLinearMemory:
EDIT: I forgot to mention: the test case assumes that the first alloc ( 512 MB ) succeeds. So - in case you want to try it on a VM - you'll have to setup the machine with at least 520 MB |
A problem with CauseWays DPMI emulation, again causing a crash:
The problem is that the CauseWay "DPMI emulator", if it doesn't know how to handle the Int 31h, routes it to "the previous" handler". Since there is no real "previous handler", the interrupt finally arrives in real-mode ... and the real-mode IVT vector 31h is not an address supposed to be called. IMO the fix would be in raw_vcpi.asm
|
Thanks for your info and analysis again. |
I'm not disappointed that you didn't find a proper solution - I'm also convinced that a 100% safe distinction between exception 06 and a coded INT 06 doesn't exist. Long ago I even wrote a little test program just to see what all the DPMI host do in thoses cases - cwsdpmi is the strangest beast in this regard, btw. Back to CauseWay: there's a (minor) bug in proc RawCallBack (file raw_vcpi.asm):
It's interesting that Michael Devore cared about Win3 enhanced mode - however, his "fix" surely was never tested: proc RawCallBack is always called NEAR ( to have a means to calculate the callback number ), so the stack has to be adjusted before the RETF. Inside RawCallBack one could do a small optimization
The code to calculate the callback number exists twice - one can remove one of the instances ( register BX is never modified by the code between, so the second calculation is redundant ). |
Another (small) bug in CauseWay's DPMI emulator - function "release descriptor" ( int 31h, ax=1 ). The test case:
Currently '1' is returned by function ReleaseDescriptor if the program runs in raw/vcpi mode. In a Windows DOS box, '0' will be returned. The problem is: the function that handles the request doesn't check if the descriptor that's to be released is a valid one and if it has been allocated at all.
The line "cmp esi,GDT_Entries ;don't release GDT entries" perhaps deserves an explanation: CauseWay maps GDT and LDT to the very same linear address space - no idea why. The first entries (about 20) in the LDT are therefore actually "GDT descriptors" - to "release" them most likely causes an immediate crash. |
You are right there is some redundant and odd code. |
There's no hurry - none of the bugs described so far are critical. Another issue ( or at least something for discussion ): CauseWay emits DOS int 21h calls for its swapfile support without checking if the InDos flag is set. Usually the swapfile is only accessed when memory conditions are "low", but there is one exception: for DPMI function 0x500 (get free memory info), CauseWay emits an int 21h, ah=36h to detect the current free disk space ( unless the NOVM option has been set ). This should probably be fixed , IMO. |
Back to exceptions versus interrupt detection I am afraid that we need to prefer exception handling as you proposed, probably nobody will be raise appropriate interrupt. |
Hello,
since OW 2.0 has apparently switched to CauseWay as its preferred DOS extender, and since the source of the app is available, it's probably time to fix some bugs in it.
This small test program ( compiled with wcc386, linked with "wlink system causeway" )
should print the current state of the CPU's interrupt flag, using DPMI function 0x902. In Open Watcom, it causes page faults if it runs in a "raw" or VCPI environment ( that is, NOT in a Windows DOS box or DosEmu ).
It's because of a bug in the CauseWay extender, file raw_vcpi.asm, function RawDPMIPatch():
There's an uninitialized register (EBP) and wrong displacements, the code parts probably have been copied from somewhere and then weren't tested. The very same bug occurs for DPMI functions 0x900 and 0x901 - althouth those are a bit more severe, since the interrupt flag is modified by them, meaning a hazardous write to memory.
The text was updated successfully, but these errors were encountered: