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