PATCH: pread() return non-zero if read beyond end of file

Xiaofeng Liu via cygwin-patches
Mon Nov 6 19:20:00 GMT 2017

pread() return 0 if read beyond end of file in linux, but not zero in cygwin. 
I have a small code to show the problem:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>

int main()
  const char* file = "/home/xliu/work/exome/a.bam";
  struct stat st;
  stat(file, &st);
  char buf[65536];
  int fd = open(file, O_RDONLY);
  int ret = pread(fd, buf, sizeof buf, st.st_size);
  fprintf(stderr, "filesize %ld, after eof pread() return = %d, errno = %d\n", st.st_size, ret, errno);
  lseek(fd, st.st_size, SEEK_SET);
  ret = read(fd, buf, sizeof buf);
  fprintf(stderr, "filesize %ld, after eof read() return = %d, errno = %d\n", st.st_size, ret, errno);
$ ./a.exe
filesize 6126093048, after eof pread() return = 3, errno = 0
filesize 6126093048, after eof read() return = 0, errno = 0
The issue is that NtReadFile() return EOF status, but doesn't set io.information to 0. As a result, the current pread() implementation could return an arbitrary number in the stack. The fix is a one line fix: reset io status block. 
diff --git a/winsup/cygwin/ b/winsup/cygwin/fhandler_disk_file.ccindex bc8fead..525cb32 100644--- a/winsup/cygwin/ b/winsup/cygwin/ -1525,6 +1525,7 @@ fhandler_disk_file::pread (void *buf, size_t count, off_t offset)       IO_STATUS_BLOCK io;       LARGE_INTEGER off = { QuadPart:offset };
+      memset(&io, 0, sizeof(io));       if (!prw_handle && prw_open (false))        goto non_atomic;       status = NtReadFile (prw_handle, NULL, NULL, NULL, &io, buf, count,

More information about the Cygwin-patches mailing list