For the "[PATCH 3/3] crt: improve _wassert() emulation" I would propose
small improvement (changes attached). It implements decision based on
_set_error_mode() (as it was already written in the comment), use alloca
instead of _alloca (alloca is GNU name and mingw-w64 crt already uses
the non-underscore variant) and reduce calculation of alloca buffers.
Currently it first tries to estimate buffer size based on wcsnlen and
MB_LEN_MAX. Then it calculates the real buffer size correctly via
WideCharToMultiByte() and third time it is using WideCharToMultiByte()
for the final conversion. So the first step via wcsnlen and MB_LEN_MAX
is not needed, the real size can be calculated directly. Also memset is
not needed.
>From 12b499fcbab58c327389ac1869c4a7370a438984 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <[email protected]>
Date: Tue, 3 Sep 2024 21:00:27 +0200
Subject: [PATCH 1/2] crt: Provide _set_error_mode() function for pre-msvcrt40
builds
pre-msvcrt40 libraries always print assert error message to stderr
independently of what was set via __set_app_type() call.
---
mingw-w64-crt/Makefile.am | 1 +
mingw-w64-crt/misc/_set_error_mode.c | 26 ++++++++++++++++++++++++++
2 files changed, 27 insertions(+)
create mode 100644 mingw-w64-crt/misc/_set_error_mode.c
diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am
index b651dce59d51..9c0d7d1f2d63 100644
--- a/mingw-w64-crt/Makefile.am
+++ b/mingw-w64-crt/Makefile.am
@@ -919,6 +919,7 @@ src_pre_msvcrt40=\
misc/__dstbias.c \
misc/__set_app_type.c \
misc/_dstbias.c \
+ misc/_set_error_mode.c \
misc/dummy__setusermatherr.c \
stdio/_filelengthi64.c \
stdio/_findfirst32i64.c \
diff --git a/mingw-w64-crt/misc/_set_error_mode.c
b/mingw-w64-crt/misc/_set_error_mode.c
new file mode 100644
index 000000000000..64586cb66ef9
--- /dev/null
+++ b/mingw-w64-crt/misc/_set_error_mode.c
@@ -0,0 +1,26 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the mingw-w64 runtime package.
+ * No warranty is given; refer to the file DISCLAIMER.PD within this package.
+ */
+
+#include <stdlib.h>
+
+int __cdecl _set_error_mode(int mode_val)
+{
+ /* Dummy implementation for pre-msvcrt40 builds where assert() always sends
+ * error message to stderr independently of what was set via
__set_app_type().
+ * No change in this behavior is possible, so just validate input argument
and
+ * always return _OUT_TO_STDERR or -1.
+ */
+ switch (mode_val) {
+ case _OUT_TO_DEFAULT:
+ case _OUT_TO_STDERR:
+ case _OUT_TO_MSGBOX:
+ case _REPORT_ERRMODE:
+ return _OUT_TO_STDERR;
+ default:
+ return -1;
+ }
+}
+int (__cdecl *__MINGW_IMP_SYMBOL(_set_error_mode))(int) = _set_error_mode;
--
2.20.1
>From 9066ff3585caa18f3eb5e3b7bef08c889f163f85 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <[email protected]>
Date: Sat, 20 Jun 2026 22:26:51 +0200
Subject: [PATCH 2/2] fixup! crt: improve _wassert() emulation
---
mingw-w64-crt/misc/wassert.c | 78 ++++++++++++++++--------------------
1 file changed, 35 insertions(+), 43 deletions(-)
diff --git a/mingw-w64-crt/misc/wassert.c b/mingw-w64-crt/misc/wassert.c
index 9faaa4ba4958..2ad741191925 100644
--- a/mingw-w64-crt/misc/wassert.c
+++ b/mingw-w64-crt/misc/wassert.c
@@ -5,15 +5,15 @@
*/
#include <assert.h>
-#include <limits.h>
+#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
-#include <wchar.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
+extern int __mingw_app_type; /* filled by crtexe.c and crtdll.c */
+
/**
* Convert wide character string `wcs` to code page `cp`.
*
@@ -30,17 +30,23 @@ static void conv (char *buffer, int buffer_size, const
wchar_t *wcs, unsigned cp
*
* This allows us to preserve and display as much information as possible.
*/
- int length = WideCharToMultiByte (cp, 0, wcs, -1, NULL, 0, NULL, NULL);
-
- if (length == 0) {
- return;
- }
-
- if (length > buffer_size) {
- buffer_size -= 1;
- }
+ int length = WideCharToMultiByte (cp, 0, wcs, -1, buffer, buffer_size,
NULL, NULL);
+ if (length <= 0)
+ buffer[0] = '\0';
+ else if (length >= buffer_size)
+ buffer[buffer_size-1] = '\0';
+ else
+ buffer[length-1] = '\0';
+}
- WideCharToMultiByte (cp, 0, wcs, -1, buffer, buffer_size, NULL, NULL);
+static int convsize (int max_buffer_size, const wchar_t *wcs, unsigned cp) {
+ int length = WideCharToMultiByte (cp, 0, wcs, -1, NULL, 0, NULL, NULL);
+ if (length <= 0)
+ return 1; /* 1 for nul term */
+ else if (length >= max_buffer_size)
+ return max_buffer_size;
+ else
+ return length + 1; /* +1 for nul term */
}
/* _wassert is not available on XP, so forward it to _assert if needed */
@@ -60,27 +66,7 @@ static void __cdecl emu__wassert(const wchar_t *_Message,
const wchar_t *_File,
*
* As the result, we should avoid using static buffer to avoid race
* condition when multiple threads call _wassert() at the same time.
- */
- char *message = NULL;
- char *file = NULL;
-
- /**
- * Estimate maximum buffer size assuming that each wide character converts
- * to at least 1 byte and at most `MB_LEN_MAX` bytes.
- */
- int message_length = wcsnlen (_Message, BUFSIZ) * MB_LEN_MAX;
- int file_length = wcsnlen (_File, FILENAME_MAX) * MB_LEN_MAX;
-
- message_length = __min (message_length, BUFSIZ);
- file_length = __min (file_length, FILENAME_MAX);
-
- message = _alloca (message_length);
- file = _alloca (file_length);
-
- memset (message, 0, message_length);
- memset (file, 0, file_length);
-
- /**
+ *
* _assert() prints `_Message` to stderr or displays a message box,
* depending on _set_error_mode setting.
*
@@ -90,17 +76,23 @@ static void __cdecl emu__wassert(const wchar_t *_Message,
const wchar_t *_File,
* When displaying a message box, we want to convert `_Message` to active
* ANSI code page; most ANSI APIs interpret strings using that code page.
*
- * Perfectly, we would call _set_error_mode (_REPORT_ERRMODE) to query
- * current setting and decide which code page to use; we cannot do this
- * because _set_error_mode is not available in crtdll.dll, msvcrt10.dll and
- * msvcrt20.dll.
- *
- * Use active ANSI code page as the conservative option.
*/
- unsigned cp = GetACP ();
- conv (message, message_length, _Message, cp);
- conv (file, file_length, _File, cp);
+ unsigned cp;
+ int errmode = _set_error_mode (_REPORT_ERRMODE);
+ if (errmode == _OUT_TO_STDERR || (errmode == _OUT_TO_DEFAULT &&
__mingw_app_type == 0 /*console*/))
+ cp = ___lc_codepage_func (); /* stderr codepage */
+ else
+ cp = GetACP (); /* gui MessageBoxA codepage */
+
+ int message_size = convsize (BUFSIZ, _Message, cp);
+ int file_size = convsize (FILENAME_MAX, _File, cp);
+
+ char *message = alloca (message_size);
+ char *file = alloca (file_size);
+
+ conv (message, message_size, _Message, cp);
+ conv (file, file_size, _File, cp);
_assert(message, file, _Line);
}
--
2.20.1
_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public