On 2026-02-24 Pali Rohár wrote:
> Hello, in attachment I'm sending a change which fixes mingw-w64 POSIX
> non-underscored stat() and wstat() function(s) (including large file
> and 64-bit time variants) for msvcrt.dll builds when calling stat on
> various Win32 device files (like "NUL") or when using "\\?\\\\"
> prefix. The MS underscored _stat / _wstat functions are untouched and
> stay as it.

I didn't test anything, but by reading the code:

The first commit looks good. It reduces code duplication.

In the second patch, if __MINGW_FIX_STAT_PATH returns NULL when
filename != NULL, it means that malloc failed, and the contents of
struct stat (or whatever the exact type of *obj is) are undefined. It
would be good to just return the error instead of calling
__MINGW_FIX_STAT_FALLBACK_FD. That is, move the
__MINGW_FIX_STAT_FALLBACK_FD inside the else-block:

#define __MINGW_FIXED_STAT(fstat_func, stat_func, filename, obj) ({ \
  /* First call CRT _stat function with mingw path correction */ \
  int _stat_ret; \
  __MINGW_PATH_PTR_TYPE(filename) path = __MINGW_FIX_STAT_PATH(filename); \
  if (path == NULL && (filename) != NULL) { \
    _stat_ret = -1; \
  } else { \
    _stat_ret = (stat_func)(path, (obj)); \
    _stat_ret = __mingw_fix_stat_finish(_stat_ret, (filename), path, 
(obj)->st_mode); \
    /* If the CRT _stat function failed then fallback to mingw fstat function 
*/ \
    int _stat_fd = __MINGW_FIX_STAT_FALLBACK_FD(_stat_ret, (filename), 
(obj)->st_mode); \
    if (_stat_fd >= 0) { \
      _stat_ret = fstat_func(_stat_fd, (void*)(obj)); \
      int _stat_errno = errno; \
      close(_stat_fd); \
      errno = _stat_errno; \
    } \
  } \
  _stat_ret; \
})

Without this change, the "mode" in S_ISREG(mode) in
__mingw_fix_stat_fallback_fd.c will have an undefined value after
__MINGW_FIX_STAT_PATH failure.

Even with this change, S_ISREG(mode) can be executed after stat_func
has failed. I suspect that the stat_funcs don't necessarily initialize
*obj on failure. Thus, the condition in __mingw_fix_stat_fallback_fd.c
should check ret before S_ISREG(mode):

    if ((ret < 0 && errno == ENOENT && __MINGW_STR_PBRK((filename), "?*")) || 
(ret == 0 && S_ISREG(mode))) {

* * *

In __mingw_fix_stat_fallback_fd.c, this comment is confusing:

    CRT _stat does not handle paths with wildcard ? and * and returns ENOENT.

Assuming it's about \\?\ paths, a few extra words would help:

    CRT _stat does not handle paths with ? and * characters and returns
    ENOENT. This prevents _stat from working on paths like
    \\?\C:\foo.txt.

In a comment a few lines later, there is a typo. "id" should be "fd":

    ...and return id if CRT _stat failed...

> Note that UCRT build does not have these issues and it is verified by
> automated test, part of change. So this change does not touch UCRT
> builds.

Since UCRT isn't new anymore, hopefully these MSVCRT issues can soon be
declared as features, and people can be told to use UCRT when the
MSVCRT oddities are a problem.

-- 
Lasse Collin


_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to