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]>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.