For example file stdio/mingw_fprintfw.c provides function fwprintf(),
so rename it to stdio/mingw_fwprintf.c.
Signed-off-by: LIU Hao <lh_mouse@126.com>
Implement mingw-w64 emulation of fgetws() via fwscanf() with "%l[^\n]"
format to have C95+ compatibility.
Note that scanf format does not support specifying length of the string
buffer via additional argument (like printf format "*"), so specify length
of the buffer directly in the format generated by swprintf function.
Function fgetws() has to return also the trailing newline if there is a
place for it in buffer, so read it by additional fwscanf() call.
Signed-off-by: Martin Storsjö <martin@martin.st>
All CRT libraries except crtdll.dll and msvcrt10.dll provide fputws
function symbol.
For these two libraries implement simple mingw-w64 emulation of fputws()
via fwprintf() to have C95+ compatibility.
Signed-off-by: Martin Storsjö <martin@martin.st>
All CRT libraries provide fgetwc, _fgetwchar, fputwc and _fputwchar
symbols. They are aliases of the C95 functions getwc, getwchar, putwc and
putwchar.
CRT libraries crtdll.dll and msvcrt10.dll do not export these functions
under C95 names. So define aliases in def files for C95+ compatibility.
Signed-off-by: Martin Storsjö <martin@martin.st>
This is test for MS-specific _stprintf() function. All test variants passes
also when compiled with MSVC compiler and run under msvcrt or UCRT runtime.
Note that gcc throws sprintf format warning for %hs usage in this test.
It is because gcc thinks that %hs takes unsigned short* argument.
But this is incorrect expectation, as all msvcrt and UCRT runtime versions
expect char* argument for %hs format. So this gcc format warning for %hs is
a gcc's bug.
Signed-off-by: Martin Storsjö <martin@martin.st>
Ensure that all these MS specific _*t* macros always expands to MS variant
of scanf and printf functions independently of __USE_MINGW_ANSI_STDIO.
Majority of the _*t* macros expands to MS specific variants of stdio
functions which are not provided by mingw when __USE_MINGW_ANSI_STDIO=1.
But some few are, e.g. _tscanf which currently expands to scanf or wscanf.
And this can cause that _tscanf behaves differently than _tscanf_l (which
does not have __USE_MINGW_ANSI_STDIO=1 replacement.
Another example is %s in _stprintf() macro. MS variant of wide-printf
treats %s as wchar_*t, but C95+ mandates that %s is always char*.
_stprintf() is suppose to be called as:
_stprintf(buffer, _T("%s"), _T("string"));
And wide variant would work correctly only in the case %s takes wchar_t*.
With this change behavior of all _*t* macros would be same and expands
always only to MS function, which also ensures compatibility of %s with
arguments passed to _*t* macros.
Signed-off-by: Martin Storsjö <martin@martin.st>
Per MS documentation, macros _stprintf and _vstprintf always expands to
s(w)printf function variant which does not take buffer size argument.
https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/sprintf-sprintf-l-swprintf-swprintf-l-swprintf-l
So _stprintf() expands either to C89 sprintf() function or to MS-specific
_swprintf() function. C95 swprintf() takes buffer size argument and so, it
is not compatible for _stprintf() and cannot be used.
So replace swprintf by _swprintf in _UNICODE mode of _stprintf expansion.
Signed-off-by: Martin Storsjö <martin@martin.st>
__ms_vsnwprintf() function now calls _vscwprintf() funcion. _vscwprintf()
is not available in older msvcrt.dll version, so provide emulation of
_scwprintf() and _vscwprintf() functions.
This emulation is similar to existing _scprintf and _vscprintf emulation.
Signed-off-by: Martin Storsjö <martin@martin.st>
ISO C does not define (v)snwprintf() function. But ISO C11 in optional
Appendix K defines (v)snwprintf_s() function which has same behavior as
non-wide ISO C11 Appendix K (v)snprintf_s() function (which is secure
variant of (v)snprintf()).
Function (v)snwprintf() is not provided by any MS CRT library and neither
by any MS header file.
mingw32 runtime and mingw-w64 runtime since beginning provide function
named (v)snwprintf (without leading underscore) and define it under symbol
name __mingw_(v)snwprintf. This function differs from ISO C (v)swprintf()
just in return value. ISO C (v)swprintf() when buffer is too small returns
negative value but this (v)snwprintf() returns size of buffer in wide
characters, similarly to non-wide ISO C (v)snprintf() function, and also
similarly to ISO C11 Annex K (v)snwprintf_s(). This non-ISO (v)snwprintf()
and both ISO C (v)snwprintf_s() and (v)snprintf() always fill trailing nul
character.
But when __USE_MINGW_ANSI_STDIO=0 the (v)snwprintf() is redirected to
__ms_(v)snwprintf() function, which is just wrapper around msvcrt
_vsnwprintf() function. And msvcrt _vsnwprintf() function does not fill
trailing nul character and does not return required buffer size when output
buffer is too small.
So fix __ms_(v)snwprintf() functions to properly fill trailing nul
character and return required size of bufer, like ISO C vsnprintf().
Also adjust header files and remove wrong symbol aliases for (v)snwprintf
symbols from def files.
This will make API of (v)snwprintf() function compatible for both
__USE_MINGW_ANSI_STDIO=0 and __USE_MINGW_ANSI_STDIO=1 modes and also to
mimics API of ISO C (v)snwprintf_s() function.
Signed-off-by: Martin Storsjö <martin@martin.st>
C95 compatible (v)swprintf function takes size argument and returns
negative value on error. __mingw_(v)swprintf function (which is called
when __USE_MINGW_ANSI_STDIO=1) does not take size argument at all.
Fix this problem by adjusting mingw_sprintfw.c and mingw_vsprintfw.c
files to include "n" function variant and also adjust mingw_vsnprintf.c
implementation to return correct value on error for ISO C95+ variant.
Fix also header files to provide correct declarations for
__mingw_(v)swprintf() function and then also inline definitions for
(v)swprintf() when __USE_MINGW_ANSI_STDIO=1.
Note that mingw-w64 provides also additional non-ISO C (v)snwprintf()
function which is built from the same mingw_vsnprintf.c source file.
Distinguish between non-ISO C (v)snwprintf() and ISO C95+ (v)swprintf() by
a new __BUILD_WIDEAPI_ISO macro.
With all these changes, functions swprintf() and vswprintf() when
__USE_MINGW_ANSI_STDIO is set to 1 are now compatible with ISO C95+.
Signed-off-by: Martin Storsjö <martin@martin.st>
msvcr80+ has following wide-buffer swprintf like function symbols, none of
them is compatible with C95 (v)swprintf function, differences are:
_(v)swprintf - does not take buffer size argument, like non-wide C89
sprintf
_(v)snwprintf - does not fill nul-term wide char if there is not space
for it, like non-wide msvcr _(v)snprintf
_(v)swprintf_c - clears the first wide character in buffer on error
(error means that there is no space for nul-term or
conversion error occurred)
Version before msvcr80 has following function symbols:
_(v)snwprintf - same as in msvcrt80+
(v)swprintf - same as _(v)swprintf in msvcrt80+
There is no (v)swprintf symbol in msvcr80+ (neither in UCRT) and there are
no _(v)swprintf_c/_(v)swprintf symbols before msvcr80.
Additionally msvcr80+ header files defines (v)swprintf() function as inline
wrapper function around _vswprintf_c_l() with NULL locale, which is same as
_vswprintf_c(). Therefore that msvcr80+ inline function (v)swprintf() is
not C95 compatible.
UCRT header files provides all those msvcr80+ swprintf family functions
defined as inline. But UCRT changed behavior of _(v)swprintf_c function,
on error it does not clear the first wide character in buffer, but instead
puts the nul wide character at current position. So with this change the
(v)swprintf() function definition in UCRT header file is C95 compatible.
mingw-w64 header files declares and defines (v)swprintf() without the
buffer size argument, matching the pre-msvcr80 (v)swprintf symbol. So
mingw-w64 has currently broken C95+ support for swprintf(), vswprintf(),
__ms_swprintf() and __ms_vswprintf() symbols, and for swprintf() and
vswprintf() functions provided by mingw-w64 header files when macro
__USE_MINGW_ANSI_STDIO is set to 0 (which is default for UCRT).
Fix this issue.
Ensure that swprintf and vswprintf symbols are always C95 compatible in
every CRT import library. Function symbols which do not take buffer size
are always under name with underscore prefix.
For non-UCRT import libraries provide mingw-w64 swprintf and vswprintf
implementations which calls _vsnwprintf and fill nul-term wide char. Original
pre-msvcr80 DLL symbols swprintf and vswprintf are renamed to _swprintf and
_vswprintf, for compatibility with msvcr80+ and UCRT.
Fix declarations of __ms_swprintf and __ms_vswprintf functions in header
files to include buffer size argument, to make them C95 compatible too.
crt-aliases.def.in file is updated to reflect this change (which completely
drops incompatible __ms_swprintf and __ms_vswprintf aliases and then also
unused PRE_C95_SWPRINTF macro).
With all these changes, functions swprintf() and vswprintf() when
__USE_MINGW_ANSI_STDIO is set to 0 are now compatible with ISO C95+.
Signed-off-by: Martin Storsjö <martin@martin.st>
Macro _tcstok takes two arguments, so in _UNICODE mode it has to expand to
two-argument _wcstok() function, instead of to three-argument wcstok()
function.
Also in C mode (as opposite of C++ mode), function wcstok() cannot be
called with just two arguments, so fix _wcstok_l macro to call _wcstok()
function.
Signed-off-by: Martin Storsjö <martin@martin.st>
All non-UCRT crt library versions provide wcstok symbol which is not C95+
compatible. Its function prototype is missing the third argument. In UCRT
version this function without third argument is named _wcstok(). So rename
wcstok symbol to _wcstok in all non-UCRT import libraries for compatibility
with UCRT.
msvcr80+ provides wcstok_s symbol which is C95+ compatible wcstok()
function. msvcr80+ wcstok_s() function has same function prototype as C95+
wcstok() and the only difference between MS wcstok_s and C95 wcstok is that
MS wcstok_s validates parameters and sets errno. C95 version has undefined
behavior when called with invalid parameters (e.g. Linux version crashes).
So add appropriate aliases of wcstok_s in msvcr80+ import libraries to have
C95+ compatible wcstok() function under the correct C95 name wcstok.
For pre-msvcr80 import libraries, provide mingw-w64 implementation of
wcstok_s() and C95+ wcstok() functions. So when linking with any crt
library, the wcstok symbol resolve to the correct C95 compatible wcstok()
function. mingw-w64 implementation of wcstok is copied from musl libc which
is very compact and some parts from musl libc are already used in mingw-w64.
Update header files to reflect these changes. With this change, C95+
compatible wcstok() function is available for all builds, not only UCRT as
it was before this change.
For compatibility with C99, add missing restrict keyword for last wcstok()
argument in header files.
mingw-w64 is currently missing MS _wcstok() function for UCRT builds.
So provide it into UCRT import libraries.
Visual Studio 2015+ redefines wcstok() to _wcstok() when macro
_CRT_NON_CONFORMING_WCSTOK is defined. And in C++ mode it provides
overloaded C++ function wcstok() with two arguments unless the macro
_CRT_NO_INLINE_DEPRECATED_WCSTOK is defined. It is documented on:
https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/strtok-strtok-l-wcstok-wcstok-l-mbstok-mbstok-l
Implement same logic for _CRT_NON_CONFORMING_WCSTOK to get the old behavior
by default. And provides C++ inline two-argument function unless define
_CRT_NO_INLINE_DEPRECATED_WCSTOK is set.
With this change mingw-w64 always provides C95+ compatible wcstok()
function and MS two-arg _wcstok() function in all CRT import libraries.
Also every CRT import library provides MS wcstok_s() function.
Signed-off-by: Martin Storsjö <martin@martin.st>
Previously they cast their first enum operands to `int&` and operate on
integers, which is type-punning and maybe not safe. This commit makes them
call the corresponding non-assignment operators instead. As they modify their
arguments, they are only `constexpr` since C++14.
Also regroup them a little.
Signed-off-by: LIU Hao <lh_mouse@126.com>
Function _copysignf is in i386 natively available only in msvcr120 and
UCRT. mingw-w64 already provides emulation in crtdll and msvcrt i386 import
libraries. Include this emulation also into all other i386 CRT import
libraries.
Note that function _copysignf is available in all x64 and arm versions of
msvcrt libraries. So ensure that i386 emulation is not included into
non-i386 builds by adding #if guard for the whole source file. So when it
is compiled for non-i386 build, it would not provide any symbol or
function. Also rename this file to i386__copysignf.c, so it will be clear
that this file i386-only.
Signed-off-by: Martin Storsjö <martin@martin.st>
Source file purecall.c provides emulation of function _set_purecall_handler()
so rename this file to _set_purecall_handler.c. This file does not provide
function named purecall().
Function _set_purecall_handler() is available since msvcr71.dll, so include
source file also into msvcr70.dll import library.
Function _set_purecall_handler() is not available in os system version of
msvcrt.dll therefore it has to be included into msvcrt.dll import library
for all platforms (this was already before this change).
Signed-off-by: Martin Storsjö <martin@martin.st>
First, these intrins read from and write to thread-local memory. The TEB
contains a pointer to itself in the DS segment, known as the `Self` field of
`struct _NT_TIB`, which means the TEB is semantically in the same address
space as other objects, so these asm statements must clobber "memory". If an
asm statement writes to memory that is not passed with "m" constraints, then
the compiler shall be noted that it has unknown side effects, by adding a
`volatile` qualifier.
Second, for Intel syntax, this commit removes superfluous prefixes in front of
segment register names.
Third, previously `Offset` was cast to a pointer and dereferenced, and then
passed to inline assembly as a memory operand using the `m` constraint. This
was a pure hack. GCC assumes that a memory operand should belong in the DS
segment, so it appeared to reference unknown memory, and caused warnings like
intrin-impl.h:849:1: warning: array subscript 0 is outside array bounds of
'long long unsigned int[0]' [-Warray-bounds=]
849 | __buildreadseg(__readgsqword, unsigned __int64, "gs", "q")
| ^~~~~~~~~~~~~~
This commit passes the address by register instead. For Intel syntax, there is
no way to print the `DWORD PTR` thing, so unfortunately the value also has to
be passed by register. It's suboptimal, but should be safe.
For x86-64, the use of a 32-bit address requires an address size override
prefix. However, it's deliberate, as zero-extending a 32-bit register (like
`mov edi, edi`) would require two additional bytes.
Signed-off-by: LIU Hao <lh_mouse@126.com>
libmsvcrtd.a is import library for msvcrtd.dll and therefore it cannot
include libmsvcrt_extra.a library which object files are compiled with
-D__LIBMSVCRT_OS__ which instruct code to access msvcrt.dll library.
Add a new static library libmsvcrtd_extra.a which is compiled source
file names required for msvcrt 6.0 version and compile them without
the -D__LIBMSVCRT_OS__ option. Then use this new static library
libmsvcrtd_extra.a for building the final libmsvcrtd.a import library.
Signed-off-by: Martin Storsjö <martin@martin.st>
Add new helper variables src_pre_msvcr* and then define src_msvcr*
variables based on those helpers. This reduce duplication of source file
names, which decrease maintenance burden and make it easier to track what
is included in which msvcr* import library.
Signed-off-by: Martin Storsjö <martin@martin.st>
__getmainargs() parses the command line from the return value of
GetCommandLineA() which uses best-fit mapping when converting the
native wide-char command line to the process code page. This can
create security issues. For example, fullwidth quotation mark (U+FF02)
may get converted to ASCII quotation mark (U+0022), which will break
argument quoting and can result in argument injection, for example,
if malicious filenames are passed as an argument to a program. There
are other security issues with best-fit mapping too.
Call __wgetmainargs() to get wide-argv and convert it to narrow-argv
without best-fit mapping. If conversion isn't lossless, print an
error message and _exit(255) without calling main() at all. While
this might not be ideal with every application, with most applications
a lossy conversion would be a "garbage in, garbage out" situation.
For example, lossy conversion of filenames doesn't make any sense.
Note that if _dowildcard is set, then filenames from wildcard expansion
can prevent the application from running if those filenames contain
characters that cannot be converted losslessly.
Setting the process code page to UTF-8 using an application manifest
would also fix the issue (apart from unpaired surrogates which are
invalid UTF-16 but legal on Windows command line and in filenames).
Setting UTF-8 in a manifest is only supported on Windows 10 version 1903
and later, and switching to UTF-8 could create new issues in some apps.
The method in this commit works on old Windows versions too. Even with
UTF-8, this commit matters because it blocks unpaired surrogates on the
command line.
The best-fit conversion issue affects a large number of applications
that use main() instead of wmain(). It's better to fix the issue at
toolchain level instead of trying to fix every application separately.
Examples of applications where this has already been reported:
- The report about the issue in curl has more technical details:
https://hackerone.com/reports/2550951
- In XZ Utils the issue was already solved by setting UTF-8 code page:
https://tukaani.org/xz/#_argument_injection_on_windows
(CVE-2024-47611)
Thanks to Orange Tsai and splitline from DEVCORE Research Team
for discovering this issue.
Signed-off-by: Lasse Collin <lasse.collin@tukaani.org>
Signed-off-by: LIU Hao <lh_mouse@126.com>
Using SetThreadDescription has the advantage that on recent Visual
Studio / Windows, the thread name is always available regardless of
whether a debugger was attached, is also available in crash dumps, and
to other tools.
Quoting MSDN at Set a thread name in C/C++:
https://learn.microsoft.com/en-us/visualstudio/debugger/tips-for-debugging-threads?view=vs-2022&tabs=csharp#set-a-thread-name-in-cc
> There are two ways to set a thread name. The first is via the
> SetThreadDescription function. The second is by throwing a
> particular exception while the Visual Studio debugger is attached to
> the process. Each approach has benefits and caveats. The use of
> SetThreadDescription is supported starting in Windows 10 version
> 1607 or Windows Server 2016.
>
> It's worth noting that both approaches can be used together, if
> desired, since the mechanisms by which they work are independent of
> each other.
Signed-off-by: Antonin Décimo <antonin@tarides.com>
Signed-off-by: LIU Hao <lh_mouse@126.com>
This commit moves `__mingw_has_sse()` to a separate file, and makes its
result cacheable.
SSE is required for x86-64, and can be enabled for x86-32 by passing `-msse`
to GCC. On ARM and ARM64 it's always absent. A macro is defined if it would
be known to return a constant.
Co-authored-by: Morilli <molli.bender@gmail.com>
Signed-off-by: LIU Hao <lh_mouse@126.com>
Fix ULongToChar to return -1 on overflow, like it does in the SDK.
Fix LongLongToUIntPtr and LongLongToULongPtr so they work on 32-bit.
Remove about 150 macros added this year that just redefine an existing function.
Signed-off-by: Jacek Caban <jacek@codeweavers.com>