Skip to content

Commit

Permalink
Fix #77937: preg_match failed
Browse files Browse the repository at this point in the history
On some recent Windows systems, ext\pcre\tests\locales.phpt fails,
because 'pt_PT' is accepted by `setlocale()`, but not properly
supported by the ctype functions, which are used internally by PCRE2 to
build the localized character tables.

Since there appears to be no way to properly check whether a given
locale is fully supported, but we want to minimize BC impact, we filter
out typical Unix locale names, except for a few cases which have
already been properly supported on Windows.  This way code like

  setlocale(LC_ALL, 'de_DE.UTF-8', 'de_DE', 'German_Germany.1252');

should work like on older Windows systems.

It should be noted that the locale names causing trouble are not (yet)
documented as valid names anyway, see
<https://docs.microsoft.com/en-us/cpp/c-runtime-library/locale-names-languages-and-country-region-strings?view=vs-2019>.
  • Loading branch information
cmb69 committed May 7, 2019
1 parent 9977de0 commit fa35882
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 0 deletions.
21 changes: 21 additions & 0 deletions ext/standard/string.c
Expand Up @@ -4513,7 +4513,28 @@ PHP_FUNCTION(setlocale)
}
}

# ifndef PHP_WIN32
retval = php_my_setlocale(cat, loc ? ZSTR_VAL(loc) : NULL);
# else
if (loc) {
/* BC: don't try /^[a-z]{2}_[A-Z]{2}($|\..*)/ except for /^u[ks]_U[KS]$/ */
char *locp = ZSTR_VAL(loc);
if (ZSTR_LEN(loc) >= 5 && locp[2] == '_'
&& locp[0] >= 'a' && locp[0] <= 'z' && locp[1] >= 'a' && locp[1] <= 'z'
&& locp[3] >= 'A' && locp[3] <= 'Z' && locp[4] >= 'A' && locp[4] <= 'Z'
&& (locp[5] == '\0' || locp[5] == '.')
&& !(locp[0] == 'u' && (locp[1] == 'k' || locp[1] == 's')
&& locp[3] == 'U' && (locp[4] == 'K' || locp[4] == 'S')
&& locp[5] == '\0')
) {
retval = NULL;
} else {
retval = php_my_setlocale(cat, ZSTR_VAL(loc));
}
} else {
retval = php_my_setlocale(cat, NULL);
}
# endif
zend_update_current_locale();
if (retval) {
if (loc) {
Expand Down
25 changes: 25 additions & 0 deletions ext/standard/tests/strings/setlocale-win32.phpt
@@ -0,0 +1,25 @@
--TEST--
Unix locale names are rejected on Windows, except for some special cases
--SKIPIF--
<?php
if (substr(PHP_OS, 0, 3) != 'WIN') die('skip this test is for Windows platforms only');
?>
--FILE--
<?php
var_dump(setlocale(LC_ALL, 'de_DE'));
var_dump(setlocale(LC_ALL, 'de_DE.UTF-8'));
// the following are supposed to be accepted
var_dump(setlocale(LC_ALL, 'uk_UK'));
var_dump(setlocale(LC_ALL, 'uk_US'));
var_dump(setlocale(LC_ALL, 'us_UK'));
var_dump(setlocale(LC_ALL, 'us_US'));
?>
===DONE===
--EXPECT--
bool(false)
bool(false)
string(27) "English_United Kingdom.1252"
string(26) "English_United States.1252"
string(27) "English_United Kingdom.1252"
string(26) "English_United States.1252"
===DONE===

0 comments on commit fa35882

Please sign in to comment.