[comp.binaries.ibm.pc.d] MS-DOS 3.30 Absolute Disk I/O bug

maa@nbires.nbi.com (Mark Armbrust) (06/09/89)

There is a bug in MS-DOS 3.30 that causes the INTR 25/26 Absolute Disk I/O
functions to trash memory if they are issued for invalid drive numbers.
I have not checked any other version of DOS to see if they also have the
bug.

What happens is that if the drive number in AL refers to an invalid drive,
MS-DOS writes a word of 0FFFFh at ES:[BP+1Eh].

There are two ways to get around the problem; one is to make sure that you
never call INTR 25/26 with invalid drive numbers or that you set ES:BP to
point to a buffer that you don't mind having trashed (can be the read buffer
since the bug occurs before the actual read operation).  The other is to
patch MS-DOS to fix the problem.

What follows it a patch for MS-DOS 3.30's MSDOS.SYS file to fix the bug.  This
has not been checked on any other version of DOS and will most likely NOT work
on any version of DOS other than MS-DOS 3.30.


FC /B MSDOS.MS MSDOS.SYS
	  +------- MS-DOS 3.30 MSDOS.SYS
	  |  +---- Patched MSDOS.SYS
	  |  |
000015AD: 26 1F
000015AE: C7 73
000015AF: 46 01
000015B0: 1E C3
000015B1: FF 26
000015B2: FF C7
000015B3: 1F 46
000015B4: 73 1E
000015B5: 01 FF
000015B6: C3 FF
000015D3: E2 DC


For those of you who want to know what you are changing:

ABSSETUP:
        INC     BYTE PTR SS:INDOS               ;15A0 36 FE 06 CF 02
        STI                                     ;15A5 FB
        CLD                                     ;15A6 FC
        PUSH    DS                              ;15A7 1E
        PUSH    SS                              ;15A8 16
        POP     DS                              ;15A9 1F
        CALL    GETBP                           ;15AA E8 8D 00
GETBP routine sets up ES and BP to point to an internal
data structure ONLY if the drive number in AL is valid.
It returns with carry set if the drive number is not
valid and ES and BP are unchanged.
        MOV     WORD PTR ES:[BP+1EH],0FFFF      ;15AD 26 C7 46 1E FF FF
        POP     DS                              ;15B3 1F
        JNB     L15B7                           ;15B4 73 01
                                                ;L15B6    L15D2 CJ
L15B6:  RET_NEAR                                ;15B6 C3

The fix is to move the MOV instruction above down to here
so that is is only executed for valid drive numbers.
                                                ;L15B7    L15B4 CJ
L15B7:  PUSH    DS                              ;15B7 1E
        PUSH    SI                              ;15B8 56
        PUSH    AX                              ;15B9 50
        PUSH    SS                              ;15BA 16
        POP     DS                              ;15BB 1F
        MOV     SI,OFFSET OPENBUF               ;15BC BE 60 03
        MOV     [SI],AL                         ;15BF 88 04
        ADD     BYTE PTR [SI],41H       ;'A'    ;15C1 80 04 41
        MOV     WORD PTR [SI+1],OFFSET L003A    ;15C4 C7 44 01 3A 00
        MOV     AX,OFFSET DAYCNT                ;15C9 B8 00 03
        CLC                                     ;15CC F8
        INT     2AH                             ;15CD CD 2A
        POP     AX                              ;15CF 58
        POP     SI                              ;15D0 5E
        POP     DS                              ;15D1 1F
        JNB     L15B6                           ;15D2 73 E2
note that the target of this jump moves because of the
code patch.
        MOV     WORD PTR SS:EXTERR,OFFSET BCON  ;15D4 36 C7 06 D2 02 32 00
                                                ;L15DB    L1643 CJ
L15DB:  RET_NEAR                                ;15DB C3

This is the entry print for INTR 25H
                                                ;L15DC    L73D9 DI
ABSDRD: CLI                                     ;15DC FA
        MOV     CS:USER_SS,SS                   ;15DD 2E 8C 16 20 05
        MOV     CS:USER_SP,SP                   ;15E2 2E 89 26 1E 05
        PUSH    CS                              ;15E7 0E
        POP     SS                              ;15E8 17
        MOV     SP,OFFSET DSKSTACK              ;15E9 BC 86 08
        PUSH    ES                              ;15EC 06
        CALL    ABSSETUP                        ;15ED E8 B0 FF
        JB      L160C                           ;15F0 72 1A
        CALL    DSKREAD                         ;15F2 E8 B1 2A
                                                ;L15F5    L1638 CJ
L15F5:  JZ      L160C                           ;15F5 74 15
        PUSH    ES                              ;15F7 06
        PUSH    CS                              ;15F8 0E
        POP     ES                              ;15F9 07
        XOR     AH,AH                           ;15FA 32 E4
        MOV     CX,OFFSET L0006                 ;15FC B9 06 00
        MOV     DI,OFFSET MSC001S               ;15FF BF 89 0F
        REPNZ   SCASB                           ;1602 F2 AE
        JNZ     L160A                           ;1604 75 04
        MOV     AH,ES:[DI+5]                    ;1606 26 8A 65 05
                                                ;L160A    L1604 CJ
L160A:  POP     ES                              ;160A 07
        STC                                     ;160B F9
                                                ;L160C    L15F0 CJ  L15F5 CJ  
							  L1633 CJ
L160C:  POP     ES                              ;160C 07
        CLI                                     ;160D FA
        DEC     BYTE PTR SS:INDOS               ;160E 36 FE 0E CF 02
        MOV     SS,SS:USER_SS                   ;1613 36 8E 16 20 05
        MOV     SP,CS:USER_SP                   ;1618 2E 8B 26 1E 05
        STI                                     ;161D FB
        RET_FAR                                 ;161E CB



Mark Armbrust
maa@nbires.nbi.com
maa@nbires.UUCP
-- 

Mark Armbrust
maa@nbires.nbi.com
maa@nbires.UUCP

maa@nbires.nbi.com (Mark Armbrust) (06/10/89)

In article <410@nbires.nbi.com> maa@nbires.nbi.com (Mark Armbrust) writes:
>
>There is a bug in MS-DOS 3.30 that causes the INTR 25/26 Absolute Disk I/O
>functions to trash memory if they are issued for invalid drive numbers.
>I have not checked any other version of DOS to see if they also have the
>bug.
>
>What happens is that if the drive number in AL refers to an invalid drive,
>MS-DOS writes a word of 0FFFFh at ES:[BP+1Eh].

I did a bit of looking at various version of DOS that we have around here
and the bug seems to have been introduced in MS/PC-DOS 3.1; it has been fixed
in MS-DOS 4.0 (I didn't check PC-DOS 4.0).

It seems that the easiest way to deal with this problem is to set ES to 0F000h.
This makes DOS do the erroneous write into the ROM.

For example, from DF.C where I first found the problem:


        int DriveReady (int drive, char *buffer)
        {
        union REGS regs;
    +   struct SREGS sregs;

    +       segread (&sregs);
    +       sregs.es = 0xF000;
            regs.h.al = (unsigned char) drive;
            regs.x.bx = (int) buffer;
            regs.x.cx = 1;
            regs.x.dx = 0;
    -       int86 (0x25, &regs, &regs);
    +       int86x (0x25, &regs, &regs, &sregs);
            return ! (regs.x.cflag);
            }


>This is the entry print for INTR 25H
		   ^^^^^
		   POINT!  My fingers sometimes have a life of their own.  8-(
-- 

Mark Armbrust
maa@nbires.nbi.com
maa@nbires.UUCP