On Monday 29 September 2025 14:00:30 Martin Storsjö wrote:
> On Mon, 15 Sep 2025, Pali Rohár wrote:
> 
> > Ou. I see. The second test case is crashing inside the UCRT's wcstok()
> > function. So there is no assert output and because of crash there is
> > also no other visible output. Normally dr watson would be visible.
> > 
> > After debugging, it looks like that UCRT's wcstok() function does not
> > accept NULL state when the string is NULL. And is trying to dereference
> > the *state (which cause NULL dereference and crash). I would propose to
> > disable the second test case. With that change, the test passed my tests
> > under UCRT env.
> > 
> > diff --git a/mingw-w64-crt/testcases/t_wcstok_s.c 
> > b/mingw-w64-crt/testcases/t_wcstok_s.c
> > index a9ce9f3dc9d8..ff02805bd1e6 100644
> > --- a/mingw-w64-crt/testcases/t_wcstok_s.c
> > +++ b/mingw-w64-crt/testcases/t_wcstok_s.c
> > @@ -36,7 +36,9 @@ int main() {
> >     assert(handler_called == 0);
> >     assert(handler_errno == -1);
> > 
> > -    /* wcstok for NULL string and state returns NULL and does not set 
> > errno and does not call handler */
> > +    /* msvcrt wcstok for NULL string and state returns NULL and does not 
> > set errno and does not call handler */
> > +    /* UCRT wcstok for NULL string expects that the state is non-NULL and 
> > dereference it, so do not call this test for UCRT */
> > +#ifndef _UCRT
> >     handler_called = 0;
> >     handler_errno = -1;
> >     errno = -1;
> > @@ -46,6 +48,7 @@ int main() {
> >     assert(errno == -1);
> >     assert(handler_called == 0);
> >     assert(handler_errno == -1);
> > +#endif
> > 
> 
> Thanks; this change does fix the failures on UCRT.

Perfect.

> 
> > > 
> > > On msvcrt, on aarch64 and arm64ec (armv7 untested), it fails like this:
> > > 
> > > FAIL: t_wcstok_s
> > > ================
> > > 
> > > Assertion failed: handler_called == 1, file ../../testcases/t_wcstok_s.c,
> > > line 75
> > > FAIL t_wcstok_s.exe (exit status: 3)
> > 
> > This looks like that msvcrt.dll's wcstok_s on all platforms is calling
> > msvcrt.dll's _invalid_parameter which is broken. So the registered
> > exception handler is not called at all.
> > 
> > Replacing wcstok_s by mingw-w64 emulation also on arm platforms (not
> > just i386 and x64) could help here. Could you check this change?
> 
> This change in itself doesn't seem to be enough to make the tests pass; they
> now hang instead.
> 
> I (or someone else with access to aarch64 systems) will need to concretely
> look into it where it is hanging, unless you telepathically can think of why
> this may be. :-) Unfortunately I haven't had time to do that yet, but I will
> try to get to it.
> 
> // Martin

Ah, my mistake. Now I see where is the issue. mingw-w64's wcstok_s is
wrapper around the wcstok. And mingw-w64's arm wcstok is in
msvcr80plus_wcstok.c which is wrapper around wcstok_s. So that is why it
hangs on arm. I would propose this change which could fix the wcstok_s
for arm. It is untested.




crt: Fix wcstok_s for arm msvcrt

wcstok_s in arm msvcrt does not call invalid parameter handler because
msvcrt.dll does not provide _set_invalid_parameter_handler function.

So add a wrapper around arm msvcrt wcstok_s function which will invoke the
mingw-w64 _invalid_parameter_noinfo().

diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am
index a4b7364e9c54..67a1e7d3eaf9 100644
--- a/mingw-w64-crt/Makefile.am
+++ b/mingw-w64-crt/Makefile.am
@@ -684,6 +684,7 @@ src_msvcrtarm32=\
   misc/_getpid.c \
   misc/__initenv.c \
   misc/__winitenv.c \
+  secapi/msvcrt_arm_wcstok_s.c \
   stdio/_fstat64i32.c \
   stdio/_setmaxstdio.c \
   stdio/_stat64i32.c \
@@ -807,6 +808,7 @@ src_msvcrtarm64=\
   misc/_getpid.c \
   misc/__initenv.c \
   misc/__winitenv.c \
+  secapi/msvcrt_arm_wcstok_s.c \
   stdio/_fstat32.c \
   stdio/_fstat32i64.c \
   stdio/_setmaxstdio.c \
diff --git a/mingw-w64-crt/lib-common/msvcrt.def.in 
b/mingw-w64-crt/lib-common/msvcrt.def.in
index 236eb591d767..abeebee691fe 100644
--- a/mingw-w64-crt/lib-common/msvcrt.def.in
+++ b/mingw-w64-crt/lib-common/msvcrt.def.in
@@ -1847,7 +1847,7 @@ wcsncpy_s
 F_ARM_ANY(wcsnlen) ; i386 and x64 wcsnlen replaced by emu
 ; wcsrtombs replaced by emu, CRT version does not report invalid conversion 
state
 wcsrtombs_s
-F_ARM_ANY(wcstok_s) ; i386 and x64 wcstok_s replaced by emu
+__msvcrt_wcstok_s == wcstok_s ; wcstok_s replaced by emu, it does not call 
exception handler for invalid arguments
 wcstombs_s
 ; wctob replaced by emu, CRT version may sign-extend its return value
 wctomb_s
diff --git a/mingw-w64-crt/secapi/msvcrt_arm_wcstok_s.c 
b/mingw-w64-crt/secapi/msvcrt_arm_wcstok_s.c
new file mode 100644
index 000000000000..6e00dd7ddda5
--- /dev/null
+++ b/mingw-w64-crt/secapi/msvcrt_arm_wcstok_s.c
@@ -0,0 +1,29 @@
+/**
+ * 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 <errno.h>
+#include <wchar.h>
+
+_CRTIMP wchar_t *__cdecl __msvcrt_wcstok_s(wchar_t *_Str, const wchar_t 
*_Delim, wchar_t **_Context);
+
+wchar_t *__cdecl wcstok_s(wchar_t *_Str, const wchar_t *_Delim, wchar_t 
**_Context)
+{
+  /* msvcrt.dll's wcstok_s() does not call mingw-w64's _invalid_parameter()
+   * replacement which fixes the broken msvcrt.dll's _invalid_parameter().
+   * So call mingw-w64's _invalid_parameter() manually on EINVAL.
+   */
+  wchar_t *ret;
+  int old_errno = errno;
+  errno = 0;
+  ret = __msvcrt_wcstok_s(_Str, _Delim, _Context);
+  if (errno == EINVAL) {
+    _invalid_parameter_noinfo();
+    return NULL;
+  }
+  errno = old_errno;
+  return ret;
+}
+wchar_t *(__cdecl *__MINGW_IMP_SYMBOL(wcstok_s))(wchar_t *, const wchar_t *, 
wchar_t **) = wcstok_s;


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

Reply via email to