getlocalename_l() crash on C locale

Takashi Yano takashi.yano@nifty.ne.jp
Mon Aug 24 06:49:59 GMT 2026


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 <corinna@vinschen.de>
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 <corinna@vinschen.de>

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 <takashi.yano@nifty.ne.jp>


More information about the Newlib mailing list