On Cygwin 3.6.0, I see the test-getlocalename_l test fail: it crashes.

Reported at <https://cygwin.com/pipermail/cygwin/2025-March/257715.html>.

This patch provides a workaround:


2025-03-24  Bruno Haible  <br...@clisp.org>

        getlocalename_l-unsafe: Work around Cygwin 3.6.0 bug.
        * m4/locale_h.m4 (gl_LOCALE_H_DEFAULTS): Initialize
        REPLACE_GETLOCALENAME_L.
        * m4/getlocalename_l.m4 (gl_FUNC_GETLOCALENAME_L_UNSAFE): Test whether
        getlocalename_l works. Set REPLACE_GETLOCALENAME_L.
        * modules/locale-h (Makefile.am): Substitute REPLACE_GETLOCALENAME_L.
        * lib/locale.in.h (getlocalename_l): Consider REPLACE_GETLOCALENAME_L.
        * modules/getlocalename_l-simple (Depends-on, configure.ac): Likewise.
        * doc/posix-functions/getlocalename_l.texi: Mention two Cygwin bugs.

diff --git a/doc/posix-functions/getlocalename_l.texi 
b/doc/posix-functions/getlocalename_l.texi
index dc7b3ed94c..e258cd1df7 100644
--- a/doc/posix-functions/getlocalename_l.texi
+++ b/doc/posix-functions/getlocalename_l.texi
@@ -14,8 +14,20 @@
 glibc 2.41, macOS 14, FreeBSD 14.0, NetBSD 10.0, OpenBSD 7.5, Minix 3.3.0, AIX 
7.3.1, HP-UX 11.31, Solaris 11.4, Cygwin 3.5.x, mingw, MSVC 14, Android 9.0.
 But the gnulib replacement supports only a single locale category:
 the argument @code{LC_ALL} is unsupported.
+@item
+This function returns an invalid pointer
+when the second argument is @code{LC_GLOBAL_LOCALE},
+on some platforms:
+@c https://cygwin.com/pipermail/cygwin/2025-March/257715.html
+Cygwin 3.6.0.
 @end itemize
 
 Portability problems not fixed by Gnulib:
 @itemize
+@item
+This function supports only a single locale category,
+i.e. the argument @code{LC_ALL} is unsupported,
+on some platforms:
+@c https://cygwin.com/pipermail/cygwin/2025-March/257715.html
+Cygwin 3.6.0.
 @end itemize
diff --git a/lib/locale.in.h b/lib/locale.in.h
index 5eead0a360..34f8c5b631 100644
--- a/lib/locale.in.h
+++ b/lib/locale.in.h
@@ -385,13 +385,25 @@ _GL_WARN_ON_USE (freelocale, "freelocale is not 
portable");
 #endif
 
 #if @GNULIB_GETLOCALENAME_L@
-# if !@HAVE_GETLOCALENAME_L@
+# if @REPLACE_GETLOCALENAME_L@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef getlocalename_l
+#   define getlocalename_l rpl_getlocalename_l
+#  endif
+_GL_FUNCDECL_RPL (getlocalename_l, const char *,
+                  (int category, locale_t locale),
+                  _GL_ARG_NONNULL ((2)));
+_GL_CXXALIAS_RPL (getlocalename_l, const char *,
+                  (int category, locale_t locale));
+# else
+#  if !@HAVE_GETLOCALENAME_L@
 _GL_FUNCDECL_SYS (getlocalename_l, const char *,
                   (int category, locale_t locale),
                   _GL_ARG_NONNULL ((2)));
-# endif
+#  endif
 _GL_CXXALIAS_SYS (getlocalename_l, const char *,
                   (int category, locale_t locale));
+# endif
 # if __GLIBC__ >= 2
 _GL_CXXALIASWARN (getlocalename_l);
 # endif
diff --git a/m4/getlocalename_l.m4 b/m4/getlocalename_l.m4
index e434dff5f3..6c9d766ffa 100644
--- a/m4/getlocalename_l.m4
+++ b/m4/getlocalename_l.m4
@@ -1,5 +1,5 @@
 # getlocalename_l.m4
-# serial 2
+# serial 3
 dnl Copyright (C) 2025 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -27,10 +27,41 @@ AC_DEFUN_ONCE([gl_FUNC_GETLOCALENAME_L_UNSAFE]
   AC_REQUIRE([gl_FUNC_SETLOCALE_NULL])
   AC_CHECK_FUNCS_ONCE([getlocalename_l])
   if test $ac_cv_func_getlocalename_l = yes; then
-    GETLOCALENAME_L_LIB=
+    dnl Check against the Cygwin 3.6.0 bug: It returns an invalid pointer when
+    dnl the second argument is LC_GLOBAL_LOCALE.
+    AC_REQUIRE([AC_CANONICAL_HOST])
+    AC_CACHE_CHECK([whether getlocalename_l works],
+      [gl_cv_func_getlocalename_l_works],
+      [AC_RUN_IFELSE(
+         [AC_LANG_SOURCE([[
+#include <locale.h>
+#include <string.h>
+int main ()
+{
+  const char *ret = getlocalename_l (LC_COLLATE, LC_GLOBAL_LOCALE);
+  return strlen (ret) == 0;
+}]])],
+         [gl_cv_func_getlocalename_l_works=yes],
+         [gl_cv_func_getlocalename_l_works=no],
+         [case "$host_os" in
+            cygwin*) # Guess no on Cygwin.
+              gl_cv_func_getlocalename_l_works="guessing no" ;;
+            *)       # Guess yes otherwise.
+              gl_cv_func_getlocalename_l_works="guessing yes" ;;
+          esac
+         ])
+      ])
+    case "$gl_cv_func_getlocalename_l_works" in
+      *yes) ;;
+      *) REPLACE_GETLOCALENAME_L=1 ;;
+    esac
   else
     HAVE_GETLOCALENAME_L=0
+  fi
+  if test $HAVE_GETLOCALENAME_L = 0 || test $REPLACE_GETLOCALENAME_L = 1; then
     GETLOCALENAME_L_LIB="$SETLOCALE_NULL_LIB"
+  else
+    GETLOCALENAME_L_LIB=
   fi
   dnl GETLOCALENAME_L_LIB is expected to be '-pthread' or '-lpthread' on AIX
   dnl with gcc or xlc, and empty otherwise.
diff --git a/m4/locale_h.m4 b/m4/locale_h.m4
index 058dc7924b..e1afbc16da 100644
--- a/m4/locale_h.m4
+++ b/m4/locale_h.m4
@@ -1,5 +1,5 @@
 # locale_h.m4
-# serial 36
+# serial 37
 dnl Copyright (C) 2007, 2009-2025 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -190,15 +190,16 @@ AC_DEFUN([gl_LOCALE_H_REQUIRE_DEFAULTS]
 AC_DEFUN([gl_LOCALE_H_DEFAULTS],
 [
   dnl Assume proper GNU behavior unless another module says otherwise.
-  HAVE_NEWLOCALE=1;       AC_SUBST([HAVE_NEWLOCALE])
-  HAVE_DUPLOCALE=1;       AC_SUBST([HAVE_DUPLOCALE])
-  HAVE_FREELOCALE=1;      AC_SUBST([HAVE_FREELOCALE])
-  HAVE_GETLOCALENAME_L=1; AC_SUBST([HAVE_GETLOCALENAME_L])
-  REPLACE_LOCALECONV=0;   AC_SUBST([REPLACE_LOCALECONV])
-  REPLACE_SETLOCALE=0;    AC_SUBST([REPLACE_SETLOCALE])
-  REPLACE_NEWLOCALE=0;    AC_SUBST([REPLACE_NEWLOCALE])
-  REPLACE_DUPLOCALE=0;    AC_SUBST([REPLACE_DUPLOCALE])
-  REPLACE_FREELOCALE=0;   AC_SUBST([REPLACE_FREELOCALE])
-  REPLACE_STRUCT_LCONV=0; AC_SUBST([REPLACE_STRUCT_LCONV])
+  HAVE_NEWLOCALE=1;          AC_SUBST([HAVE_NEWLOCALE])
+  HAVE_DUPLOCALE=1;          AC_SUBST([HAVE_DUPLOCALE])
+  HAVE_FREELOCALE=1;         AC_SUBST([HAVE_FREELOCALE])
+  HAVE_GETLOCALENAME_L=1;    AC_SUBST([HAVE_GETLOCALENAME_L])
+  REPLACE_LOCALECONV=0;      AC_SUBST([REPLACE_LOCALECONV])
+  REPLACE_SETLOCALE=0;       AC_SUBST([REPLACE_SETLOCALE])
+  REPLACE_NEWLOCALE=0;       AC_SUBST([REPLACE_NEWLOCALE])
+  REPLACE_DUPLOCALE=0;       AC_SUBST([REPLACE_DUPLOCALE])
+  REPLACE_FREELOCALE=0;      AC_SUBST([REPLACE_FREELOCALE])
+  REPLACE_GETLOCALENAME_L=0; AC_SUBST([REPLACE_GETLOCALENAME_L])
+  REPLACE_STRUCT_LCONV=0;    AC_SUBST([REPLACE_STRUCT_LCONV])
   LOCALENAME_ENHANCE_LOCALE_FUNCS=0; 
AC_SUBST([LOCALENAME_ENHANCE_LOCALE_FUNCS])
 ])
diff --git a/modules/getlocalename_l-simple b/modules/getlocalename_l-simple
index f750146d97..6b9cc9e9ba 100644
--- a/modules/getlocalename_l-simple
+++ b/modules/getlocalename_l-simple
@@ -9,15 +9,16 @@ m4/getlocalename_l.m4
 Depends-on:
 locale-h
 extensions
-getlocalename_l-unsafe [test $HAVE_GETLOCALENAME_L = 0]
-flexmember             [test $HAVE_GETLOCALENAME_L = 0]
-lock                   [test $HAVE_GETLOCALENAME_L = 0]
-bool                   [test $HAVE_GETLOCALENAME_L = 0]
-thread-optim           [test $HAVE_GETLOCALENAME_L = 0]
+getlocalename_l-unsafe [test $HAVE_GETLOCALENAME_L = 0 || test 
$REPLACE_GETLOCALENAME_L = 1]
+flexmember             [test $HAVE_GETLOCALENAME_L = 0 || test 
$REPLACE_GETLOCALENAME_L = 1]
+lock                   [test $HAVE_GETLOCALENAME_L = 0 || test 
$REPLACE_GETLOCALENAME_L = 1]
+bool                   [test $HAVE_GETLOCALENAME_L = 0 || test 
$REPLACE_GETLOCALENAME_L = 1]
+thread-optim           [test $HAVE_GETLOCALENAME_L = 0 || test 
$REPLACE_GETLOCALENAME_L = 1]
 
 configure.ac:
 gl_FUNC_GETLOCALENAME_L_SIMPLE
-gl_CONDITIONAL([GL_COND_OBJ_GETLOCALENAME_L], [test $HAVE_GETLOCALENAME_L = 0])
+gl_CONDITIONAL([GL_COND_OBJ_GETLOCALENAME_L],
+               [test $HAVE_GETLOCALENAME_L = 0 || test 
$REPLACE_GETLOCALENAME_L = 1])
 AM_COND_IF([GL_COND_OBJ_GETLOCALENAME_L], [
   gl_PREREQ_GETLOCALENAME_L_SIMPLE
 ])
diff --git a/modules/locale-h b/modules/locale-h
index 00910fde2a..97645b2355 100644
--- a/modules/locale-h
+++ b/modules/locale-h
@@ -54,6 +54,7 @@ locale.h: locale.in.h $(top_builddir)/config.status 
$(CXXDEFS_H) $(ARG_NONNULL_H
              -e 's|@''REPLACE_NEWLOCALE''@|$(REPLACE_NEWLOCALE)|g' \
              -e 's|@''REPLACE_DUPLOCALE''@|$(REPLACE_DUPLOCALE)|g' \
              -e 's|@''REPLACE_FREELOCALE''@|$(REPLACE_FREELOCALE)|g' \
+             -e 's|@''REPLACE_GETLOCALENAME_L''@|$(REPLACE_GETLOCALENAME_L)|g' 
\
              -e 's|@''REPLACE_STRUCT_LCONV''@|$(REPLACE_STRUCT_LCONV)|g' \
              -e 
's|@''LOCALENAME_ENHANCE_LOCALE_FUNCS''@|$(LOCALENAME_ENHANCE_LOCALE_FUNCS)|g' \
              -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \




Reply via email to