FDOS/kernel

Exec syscall on empty (0 byte) executable file results in NC, nothing loaded

ecm-pushbx opened this issue · 2 comments

This is the tail of the task.c DosExec call:

  rc = (int)DosRWSft(fd, sizeof(exe_header), (BYTE FAR *)&ExeHeader, XFR_READ);

  if (rc == sizeof(exe_header) &&
      (ExeHeader.exSignature == MAGIC || ExeHeader.exSignature == OLD_MAGIC))
  {
    rc = DosExeLoader(lp, &TempExeBlock, mode, fd);
  }
  else if (rc != 0)
  {
    rc = DosComLoader(lp, &TempExeBlock, mode, fd);
  }

  DosCloseSft(fd, FALSE);

  if (mode == LOAD && rc == SUCCESS)
    fmemcpy(ep, &TempExeBlock, sizeof(exec_blk));

  return rc;
}

This particular line is in error:

else if (rc != 0)

rc here holds the size of the attempted read of 1Ch bytes to determine whether the executable is in MZ .EXE format. So for 0-byte files rc is 0. That means in this case both DosExeLoader and DosComLoader are skipped. Then rc equal to zero is interpreted as SUCCESS.

The result is that the syscall returns success (NC, ax unchanged) to the int 21h caller. However, no new process is created and in the case of function 4B01h the cs:ip and ss:sp fields in the exec block are unchanged.

Expected behaviour, as tested on MS-DOS version 5: int 21h should returm CY, error code in ax equal to 000Bh. This is the corresponding internal error code in the kernel:

#define DE_INVLDFMT     -11     /* Invalid format               */

Debugging log: https://pushbx.org/ecm/test/20220505/fdbug.txt

I assume the if tree should be expanded with another branch like else { rc = DE_INVLDFMT; }.

Thank you