Skip to content

Busy SFT (during open) has a reference count of 0FFFFh on MS-DOS, lDOS, EDR-DOS #214

@ecm-pushbx

Description

@ecm-pushbx

This is the test input to enter:

callver show
ldebug /t
bp new ptr ri2Fp when ax == 1116
install indos
tsr
g
type ldos.ini
d es:di l 3B

The ldos.ini file in the redirected current directory is expected to be opened using int 21h function 3Dh which calls int 2Fh redirector function 1116h.

FreeDOS is the odd one out: Its busy SFT has a reference count field of zero. All other DOS versions set the count to 0FFFFh during the (redirector) open operation.

Exhausting SFTs with busy marker

MS-DOS v4, v5, v7, and lDOS will all free busy SFTs in the process termination (except for TSR or self-parented termination), but only if the machine ID and process ID match the current ones. MS-DOS v4 will also allocate a busy SFT if found during search, but again only if the machine ID and process ID match the current ones.

Both MS-DOS v5, v7, and current lDOS can exhaust their SFTs. If an open fails because no Process Handles are left available, then the allocated SFT entry is left in the busy state (reference count 0FFFFh). If the process then terminates using TSR terminate function 31h, the SFT entry leaks permanently. (Or until the TSR PSP is freed, re-used for another PSP, and that one allocates an SFT entry or terminates in a way other than TSR terminate or self-parented terminate.)

The following test program will leak one SFT entry on these DOS versions (but not on FreeDOS or EDR-DOS):

  1. Save away original PHT size, and change it to 1
  2. First PHT entry (stdin) is always in use
  3. Try to open CON
  4. Open fails, leaving an SFT entry busy
  5. Restore PHT size
  6. Close all PHT entries
  7. Get environment segment and zero its PSP field
  8. Free environment, if any
  9. TSR terminate with minimum PSP size (effectively 60h bytes)
	cpu 8086
	org 256
start:
	mov cx, 1
	xchg cx, word [32h]
	mov ax, 3D00h
	mov dx, name
	int 21h
	mov word [32h], cx
	xor bx, bx
.loop:
	mov ah, 3Eh
	int 21h
	inc bx
	loop .loop

	xchg cx, word [2Ch]
	jcxz .skip
	mov es, cx
	mov ah, 49h
	int 21h
.skip:
	xor dx, dx
	mov ax, 3100h
	int 21h

name:
	db "CON",0

Running this program repeatedly, with eg files=10 in config.sys, will make the system unusable:

C:\>callver show
Other kernel, OEM ID FFh, reports DOS version: 5.00
Internal version: 5.00
(Interrupt 21h ax=33FFh not supported.)
C:\>testfill
C:\>testfill
C:\>testfill
C:\>testfill
C:\>testfill
C:\>testfill
C:\>testfill
C:\>testfill
Failed to load the strings resource into memory, the location
pointed to in %COMSPEC% seems to be invalid. Please specify another
location of FreeCOM to try to load the strings from, e.g.:
C:\COMMAND.COM
or just hit enter to cancel to load the strings.


String #39
C:\>

Results

FreeDOS kernel

C:\>callver show
FreeDOS kernel, OEM ID FDh, reports DOS version: 7.10
Internal revision and version: 43 7.10
FreeDOS kernel - GIT (build 2043 OEM:0xfd) [compiled Jun 24 2025]
C:\>ldebug /t
-bp new ptr ri2Fp when ax == 1116
-install indos
-tsr
Patched PSP at 034F, now resident.
-g
C:\>type ldos.ini
Hit permanent breakpoint 00
AX=1116 BX=43C7 CX=0000 DX=0183 SP=089A BP=08BC SI=0183 DI=0183
DS=00D9 ES=00D9 SS=00D9 CS=F000 IP=F8BD NV UP DI PL ZR NA PE NC
F000:F8BD EB12              jmp     F8D1
!-d es:di l 3B
00D9:0180           00 00 00 00 20-00 00 00 00 00 00 00 00    .... ........
00D9:0190  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
00D9:01A0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
00D9:01B0  00 00 00 00 51 C1 FF FF-00 00 00 00 00 00       ....Q.........
!-

lDOS kernel

C:\>callver show
lDOS kernel, OEM ID 26h, reports DOS version: 5.26
Internal version: 5.26
lDOS (2025 March) based on MS-DOS v4.01
C:\>ldebug /t
-bp new ptr ri2Fp when ax == 1116
-install indos
-tsr
Patched PSP at 00B0, now resident.
-g
C:\>type ldos.ini
Hit permanent breakpoint 00
AX=1116 BX=2F3E CX=0000 DX=1000 SP=0912 BP=0444 SI=BB60 DI=0183
DS=B116 ES=B116 SS=B116 CS=F000 IP=F8BD NV UP DI PL ZR NA PE NC
F000:F8BD EB12              jmp     F8D1
!-d es:di l 3B
B116:0180           FF FF 00 00 00-42 99 00 00 02 B0 00 00    .....B.......
B116:0190  E0 B2 86 5A F5 0A 00 00-E6 02 00 00 00 00 17 03 ...Z............
B116:01A0  00 00 00 4C 44 45 42 55-47 20 20 53 4C 44 00 00 ...LDEBUG  SLD..
B116:01B0  00 00 00 00 01 C0 00 00-14 00 00 00 00 00       ..............
!-

MS-DOS v5.00

C:\>callver show
Other kernel, OEM ID FFh, reports DOS version: 5.00
Internal version: 5.00
(Interrupt 21h ax=33FFh not supported.)
C:\>ldebug /t
-bp new ptr ri2Fp when ax == 1116
-install indos
-tsr
Patched PSP at 060D, now resident.
-g
C:\>type ldos.ini
Hit permanent breakpoint 00
AX=1116 BX=6A4C CX=0000 DX=1000 SP=0912 BP=0444 SI=00B0 DI=0183
DS=0177 ES=0177 SS=0177 CS=F000 IP=F8BD NV UP DI PL ZR NA PE NC
F000:F8BD EB12              jmp     F8D1
!-d es:di l 3B
0177:0180           FF FF 00 00 00-42 99 00 00 02 C0 00 00    .....B.......
0177:0190  E0 B2 86 5A F5 0A 00 00-E6 02 00 00 00 00 17 03 ...Z............
0177:01A0  00 00 00 4C 44 45 42 55-47 20 20 53 4C 44 00 00 ...LDEBUG  SLD..
0177:01B0  00 00 00 00 63 05 00 00-14 00 00 00 00 00       ....c.........
!-

MS-DOS v7.10 (MSW 95 OSR2)

C:\>callver show
Other kernel, OEM ID FFh, reports DOS version: 7.10
Internal version: 7.10
(Interrupt 21h ax=33FFh not supported.)
C:\>ldebug /t
-bp new ptr ri2Fp when ax == 1116
-install indos
-tsr
Patched PSP at 047C, now resident.
-g
C:\>type ldos.ini
Hit permanent breakpoint 00
AX=1116 BX=751F CX=0000 DX=1000 SP=0908 BP=0444 SI=00B0 DI=0183
DS=00C9 ES=00C9 SS=00C9 CS=F000 IP=F8BD NV UP DI PL ZR NA PE NC
F000:F8BD EB12              jmp     F8D1
!-d es:di l 3B
00C9:0180           FF FF 00 00 00-42 99 00 00 02 C0 00 00    .....B.......
00C9:0190  E0 B2 86 5A F5 0A 00 00-E6 02 00 00 00 00 17 03 ...Z............
00C9:01A0  00 00 00 4C 44 45 42 55-47 20 20 53 4C 44 00 00 ...LDEBUG  SLD..
00C9:01B0  00 00 00 00 D2 03 00 00-14 00 00 00 00 00       ..............
!-

Enhanced DR-DOS

C:\>callver show
EDR-DOS kernel, OEM ID EEh, reports DOS version: 6.00
Internal version: 7.01
Enhanced DR-DOS 7.01.08 lDOS (2025 February) based on Caldera OpenDOS 7.01
C:\>ldebug /t
-bp new ptr ri2Fp when ax == 1116
-install indos
-tsr
Patched PSP at 0277, now resident.
-g
C:\>type ldos.ini
Hit permanent breakpoint 00
AX=1116 BX=0006 CX=000E DX=03C0 SP=08F2 BP=090A SI=0005 DI=0006
DS=B15A ES=0171 SS=B15A CS=F000 IP=F8BD NV UP DI PL ZR NA PE NC
F000:F8BD EB12              jmp     F8D1
!-d es:di l 3B
0171:0000                    FF FF-00 00 00 42 99 00 00 02       .....B....
0171:0010  C0 00 00 E0 B2 86 5A F5-0A 00 00 E6 02 00 00 00 ......Z.........
0171:0020  00 00 00 00 00 00 4C 44-45 42 55 47 20 20 53 4C ......LDEBUG  SL
0171:0030  44 00 00 00 00 00 00 CD-01 00 00 00 00 00 00 00 D...............
0171:0040  00                     -                        .
!-

Metadata

Metadata

Assignees

No one assigned

    Labels

    compatibilityissue may effect compatibility

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions