Re: getlocalename_l() crash on C locale
Takashi Yano <[email protected]>
| Newsgroups | gmane.comp.lib.newlib,gmane.os.cygwin |
|---|---|
| Message-ID | <[email protected]> |
On Mon, 24 Aug 2026 09:32:02 +1000
Tony Cook wrote:
> It looks like getlocalename_l() doesn't handle a locale object for the
> C locale correctly.
>
> It looks like it is trying to strcpy() to a NULL pointer.
>
> Originally came up at https://github.com/Perl/perl5/pull/24666
>
> Tony
>
> tony@GANYMEDE ~/play
> $ uname -a
> CYGWIN_NT-10.0-19045 GANYMEDE 3.6.10-1.x86_64 2026-07-13 20:20 UTC x86_64 Cygwin
>
> tony@GANYMEDE ~/play
> $ cat getlcn_l.c
> #include <locale.h>
> #include <stdio.h>
>
> int main(int argc, char **argv) {
> if (argc < 2) {
> fprintf(stderr, "Usage: %s locale-name\n");
> return 1;
> }
>
> locale_t lc = newlocale(LC_ALL_MASK, argv[1], 0);
> puts("newlocale");
> if (!lc) {
> perror("newlocale");
> return 1;
> }
> const char *name = getlocalename_l(LC_ALL, lc);
> printf("name '%s'\n", name);
> }
>
> tony@GANYMEDE ~/play
> $ cc -ogetlcn_l.exe -g getlcn_l.c
>
> tony@GANYMEDE ~/play
> $ ./getlcn_l C
> newlocale
>
> tony@GANYMEDE ~/play
> $ ./getlcn_l en_AU.UTF-8
> newlocale
> name 'en_AU.UTF-8'
>
> tony@GANYMEDE ~/play
> $ gdb --args ./getlcn_l C
> GNU gdb (GDB) (Cygwin 15.2-1) 15.2
> Copyright (C) 2024 Free Software Foundation, Inc.
> ...
> Reading symbols from ./getlcn_l...
> (gdb) r
> Starting program: /home/tony/play/getlcn_l C
> [New Thread 7356.0x2d20]
> [New Thread 7356.0x4f88]
> [New Thread 7356.0x6684]
> newlocale
>
> Thread 1 "getlcn_l" received signal SIGTRAP, Trace/breakpoint trap.
> 0x00007ff88aba9823 in KERNELBASE!DebugBreak ()
> from /cygdrive/c/WINDOWS/System32/KERNELBASE.dll
> (gdb) bt
> #0 0x00007ff88aba9823 in KERNELBASE!DebugBreak ()
> from /cygdrive/c/WINDOWS/System32/KERNELBASE.dll
> #1 0x00007ff8561264a7 in break_here ()
> at /usr/src/debug/cygwin-3.6.10-1/winsup/cygwin/dcrt0.cc:473
> #2 0x00007ff8561403e2 in try_to_debug ()
> at /usr/src/debug/cygwin-3.6.10-1/winsup/cygwin/exceptions.cc:599
> #3 exception::handle (e=0x7ffffc970, frame=<optimized out>, in=0x7ffffc480,
> dispatch=<optimized out>)
> at /usr/src/debug/cygwin-3.6.10-1/winsup/cygwin/exceptions.cc:812
> #4 0x00007ff88d2729df in ntdll!.chkstk ()
> from /cygdrive/c/WINDOWS/SYSTEM32/ntdll.dll
> #5 0x00007ff88d222554 in ntdll!RtlRaiseException ()
> from /cygdrive/c/WINDOWS/SYSTEM32/ntdll.dll
> #6 0x00007ff88d2714ee in ntdll!KiUserExceptionDispatcher ()
> from /cygdrive/c/WINDOWS/SYSTEM32/ntdll.dll
> #7 0x00007ff8562c70b4 in strcpy (dst0=0x0, src0=<optimized out>)
> at /usr/src/debug/cygwin-3.6.10-1/newlib/libc/string/strcpy.c:70
> #8 0x00007ff8562d043f in __currentlocale (locobj=0x7ff8563e10c0 <__C_locale>,
> locale_string=0x7ff8563e11a0 <__C_locale+224> "C")
> at /usr/src/debug/cygwin-3.6.10-1/newlib/libc/locale/locale.c:460
> #9 0x00007ff856276cf4 in _sigfe () at sigfe.s:35
> #10 0x0000000100401118 in main (argc=2, argv=0xa00002900) at getlcn_l.c:16
Thanks for the report. However, as your stack-trace shows,
This is not a cygwin's bug, but a newlib's bug.
With the commit:
commit a0fe984953ddaa808a00612b5c6959d1c3987a2d
Author: Corinna Vinschen <[email protected]>
Date: Mon Mar 24 21:28:02 2025 +0100
getlocalename_l: allow LC_ALL category
Following the changes from Austin Group bug
https://www.austingroupbugs.net/view.php?id=1741, getlocalename_l()
now allows to specify LC_ALL and returns a setlocale-conmpatible
LC_ALL locale string.
Consequentially we have to raise the size of _reent::_getlocalename_l_buf
so there's enough space for the LC_ALL locale string.
Guard all different definitions and usages of _getlocalename_l_buf
in reent.h with _MB_CAPABLE.
Link: https://www.austingroupbugs.net/view.php?id=1741
Fixes: 71511d4ac868 ("getlocalename_l: implement per SUS Base Specifications Issue 8 draft")
Signed-off-by: Corinna Vinschen <[email protected]>
the code attempt to copy locale string to `locobj->locale_string`,
in __currentlocale() in _getlocalename_l_r(). However, `locobj` is
the "C" locale, it points to the const area. This is the cause of
the crash.
I confirmed that the following patch:
diff --git a/newlib/libc/locale/getlocalename_l.c b/newlib/libc/locale/getlocalename_l.c
index 1f18f828a..7ad4331b4 100644
--- a/newlib/libc/locale/getlocalename_l.c
+++ b/newlib/libc/locale/getlocalename_l.c
@@ -63,6 +63,8 @@ _getlocalename_l_r (struct _reent *ptr, int category, struct __locale_t *locobj)
if (locobj == LC_GLOBAL_LOCALE)
return __currentlocale (__get_global_locale (),
_REENT_GETLOCALENAME_L_BUF (ptr));
+ else if (locobj == __get_C_locale ())
+ return "C";
return __currentlocale (locobj, locobj->locale_string);
}
if (locobj == LC_GLOBAL_LOCALE)
fixes the issue. I'll submit the patch to newlib list.
--
Takashi Yano <[email protected]>