On Wednesday 25 February 2026 19:16:27 Lasse Collin wrote:
> 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.
Thanks.
> 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.
That is really an issue. On failure the stat buffer is untouched. I will
move that code block as you suggested.
> 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))) {
This is also an issue, I forgot about that ret == 0 part. I will add it.
> * * *
>
> 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.
Ok, I will include this description. That makes sense.
> In a comment a few lines later, there is a typo. "id" should be "fd":
>
> ...and return id if CRT _stat failed...
I spotted this type after I send an email.
I will send new version of this change with all those fixes later.
> > 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
Or better, people can be told to not use underscored _*stat* functions.
_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public