This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
locale.c: strxfrm() requires LC_CTYPE eq LC_COLLATE
authorKarl Williamson <khw@cpan.org>
Sun, 7 Mar 2021 15:04:06 +0000 (08:04 -0700)
committerKarl Williamson <khw@cpan.org>
Thu, 1 Sep 2022 16:28:26 +0000 (10:28 -0600)
The libc functions strxfrm() on some platforms requires the LC_CTYPE
locale to be the same as the LC_COLLATE locale (or rather, probably that
they have the same code set, but checking for locale is cheaper).
Otherwise mojibake would result, or more likely the function will fail,
setting errno.

This commit brings the locales into alignment if necessary

locale.c

index 894822e..95f65f6 100644 (file)
--- a/locale.c
+++ b/locale.c
@@ -5564,6 +5564,16 @@ Perl__mem_collxfrm(pTHX_ const char *input_string,
     /* Store the collation id */
     *(U32*)xbuf = PL_collation_ix;
 
+#    ifdef USE_LOCALE_CTYPE
+
+    orig_CTYPE_locale = toggle_locale_c(LC_CTYPE, PL_collation_name);
+
+#      define CLEANUP_STRXFRM                                           \
+                restore_toggled_locale_c(LC_CTYPE, orig_CTYPE_locale)
+#    else
+#      define CLEANUP_STRXFRM  NOOP
+#    endif
+
     /* Then the transformation of the input.  We loop until successful, or we
      * give up */
     for (;;) {
@@ -5697,6 +5707,8 @@ Perl__mem_collxfrm(pTHX_ const char *input_string,
         first_time = FALSE;
     }
 
+    CLEANUP_STRXFRM;
+
     DEBUG_Lv((print_collxfrm_input_and_return(s, s + len, xlen, utf8),
               PerlIO_printf(Perl_debug_log, "Its xfrm is:"),
         PerlIO_printf(Perl_debug_log, "%s\n",
@@ -5714,6 +5726,7 @@ Perl__mem_collxfrm(pTHX_ const char *input_string,
 
   bad:
 
+    CLEANUP_STRXFRM;
     DEBUG_Lv(print_collxfrm_input_and_return(s, s + len, NULL, utf8));
 
     Safefree(xbuf);