perl5 icon indicating copy to clipboard operation
perl5 copied to clipboard

win32/locale: Fallback to 'system default locale' is broken

Open bram-perl opened this issue 3 years ago • 0 comments

Description: In commit 65ebb05984db179833ff252f547043f32184d893 (included in perl v5.20.0) a fallback to the 'system default locale' was added for Windows. In commit d2b24094d5f9c39457520a4a1ecbabb9e3999245 (included in perl v5.28.0) this however got (accidentally) broken.

Example (using Strawberry Perl):

    set LC_ALL=foo
    set LANG=bar

    .\5.18.4\perl\bin\perl.exe -e1

    .\5.20.3\perl\bin\perl.exe -e1
    perl: warning: Setting locale failed.
    perl: warning: Please check that your locale settings:
            LC_ALL = "foo",
            LANG = "bar"
        are supported and installed on your system.
    perl: warning: Falling back to the system default locale ("English_Belgium.1252").

    .\5.26.3\perl\bin\perl.exe -e1
    perl: warning: Setting locale failed.
    perl: warning: Please check that your locale settings:
            LC_ALL = "foo",
            LANG = "bar"
        are supported and installed on your system.
    perl: warning: Falling back to the system default locale ("English_Belgium.1252").

    .\5.28.2\perl\bin\perl.exe -e1
    perl: warning: Setting locale failed.
    perl: warning: Please check that your locale settings:
            LC_ALL = "foo",
            LANG = "bar"
        are supported and installed on your system.
    perl: warning: Falling back to the standard locale ("C").

TLDR:

  • no warning/fallback on 5.18.4
  • fallback to 'system default locale' for v5.20.0 - v5.26.3
  • fallback to 'standard locale' for v5.28.0+

Steps to reproduce:

On windows set to env variable LC_ALL and LANG to an invalid value and then run perl -e1 i.e.

  1. set LC_ALL=foo
  2. set LANG=bar
  3. perl -e1

Expected result:

Warning message shows Falling back to the system default locale (...)

The bug:

On Windows calling setlocale(LC_ALL, "") returns the default environment. This is what the code attempts to do. In the original commit:

                system_default_locale = setlocale(LC_ALL, "");

Today that same code:

                system_default_locale = setlocale_c(LC_ALL, "");

On WIN32 setlocale_c resolves to S_win32_setlocale which contains (stripped down version):

    if (locale && strEQ(locale, "")) {
        locale = PerlEnv_getenv("LC_ALL");
    }

#ifdef USE_WSETLOCALE
    result = S_wrap_wsetlocale(aTHX_ category, locale);
#else
    result = setlocale(category, locale);
#endif

In other words: to set system_default_locale the code needs to call setlocale with an empty string but S_win32_setlocale checks for the empty string and then changes it. Which causes setlocale to not be called with the empty string causing system_default_locale to end up as NULL.

Possible fix:

A possible quick and dirty fix is to bypass S_win32_setlocale and instead call setlocale directly:

diff --git a/locale.c b/locale.c
index 88583a0ef2..b2717d1ebc 100644
--- a/locale.c
+++ b/locale.c
@@ -3500,7 +3500,7 @@ Perl_init_i18nl10n(pTHX_ int printwarn)

                 /* Note that this may change the locale, but we are going to do
                  * that anyway just below */
-                system_default_locale = setlocale_c(LC_ALL, "");
+                system_default_locale = setlocale(LC_ALL, "");
                 DEBUG_LOCALE_INIT(LC_ALL_INDEX_, "", system_default_locale);

                 /* Skip if invalid or if it's already on the list of locales to

Before the patch:

.\perl.exe -e1
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
        LC_ALL = "foo",
        (possibly more locale environment variables)
        LANG = "bar"
    are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").

After the patch:

.\perl.exe -e1
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
        LC_ALL = "foo",
        (possibly more locale environment variables)
        LANG = "bar"
    are supported and installed on your system.
perl: warning: Falling back to the system default locale ("English_Belgium.1252").

bram-perl avatar Aug 06 '22 19:08 bram-perl