From: Nikita Popov Date: Wed, 29 Apr 2020 09:51:50 +0000 (+0200) Subject: Do not inherit LC_CTYPE locale from environment X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c4ad8beaa890b931031a5cf8a1d2d38550fca3af;p=php Do not inherit LC_CTYPE locale from environment Treatment of locales in PHP is currently inconsistent: The LC_ALL locale is set to "C", as is standard behavior on program startup. The LC_CTYPE locale is set to "", which will inherit it from the environment. However, the inherited LC_CTYPE locale will only be used in some cases, while in other cases it is necessary to perform an explicit setlocale() call in PHP first. This is the case for the locale-sensitive handling in the PCRE extension. Make things consistent by *never* inheriting any locales from the environment. LC_ALL, including LC_CTYPE will be "C" on startup. A locale can be set or inherited through an explicit setlocale() call, at which point the behavior will be fully consistent and predictable. Closes GH-5488. --- diff --git a/UPGRADING b/UPGRADING index 96b9745d4c..982ebe635c 100644 --- a/UPGRADING +++ b/UPGRADING @@ -397,6 +397,12 @@ PHP 8.0 UPGRADE NOTES . If the array returned by __sleep() contains non-existing properties, these are now silently ignored. Previously, such properties would have been serialized as if they had the value NULL. + . The default locale on startup is now always "C". No locales are inherited + from the environment by default. Previously, LC_ALL was set to "C", while + LC_CTYPE was inherited from the environment. However, some functions did not + respect the inherited locale without an explicit setlocale() call. An + explicit setlocale() call is now always required if you wish to change any + locale component from the default. - tidy: . The $use_include_path parameter, which was not used internally, has been diff --git a/Zend/tests/lc_ctype_inheritance.phpt b/Zend/tests/lc_ctype_inheritance.phpt new file mode 100644 index 0000000000..8971ff1969 --- /dev/null +++ b/Zend/tests/lc_ctype_inheritance.phpt @@ -0,0 +1,25 @@ +--TEST-- +Do not inherit LC_CTYPE from environment +--SKIPIF-- + +--ENV-- +LC_CTYPE=de_DE +--FILE-- + +--EXPECT-- +string(1) "C" +string(2) "e4" +int(0) +bool(true) +string(2) "c4" +int(1) diff --git a/ext/snmp/snmp.c b/ext/snmp/snmp.c index 8464e74aad..d5cf7cce04 100644 --- a/ext/snmp/snmp.c +++ b/ext/snmp/snmp.c @@ -49,6 +49,7 @@ #ifdef HAVE_UNISTD_H #include #endif +#include #ifndef __P #ifdef __GNUC__ @@ -1971,6 +1972,8 @@ PHP_MINIT_FUNCTION(snmp) le_snmp_session = zend_register_list_destructors_ex(php_snmp_session_destructor, NULL, PHP_SNMP_SESSION_RES_NAME, module_number); init_snmp("snmpapp"); + /* net-snmp corrupts the CTYPE locale during initialization. */ + setlocale(LC_CTYPE, "C"); #ifdef NETSNMP_DS_LIB_DONT_PERSIST_STATE /* Prevent update of the snmpapp.conf file */ diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 32a82aae26..5fa7be86db 100755 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -516,7 +516,6 @@ PHP_RSHUTDOWN_FUNCTION(basic) /* {{{ */ * to the value in startup environment */ if (BG(locale_changed)) { setlocale(LC_ALL, "C"); - setlocale(LC_CTYPE, ""); zend_update_current_locale(); if (BG(locale_string)) { zend_string_release_ex(BG(locale_string), 0); diff --git a/ext/standard/tests/strings/strtolower-win32.phpt b/ext/standard/tests/strings/strtolower-win32.phpt index ff631754df..2fc693641d 100644 Binary files a/ext/standard/tests/strings/strtolower-win32.phpt and b/ext/standard/tests/strings/strtolower-win32.phpt differ diff --git a/ext/standard/tests/strings/strtoupper1-win32.phpt b/ext/standard/tests/strings/strtoupper1-win32.phpt index 7240e5c021..619ab51d86 100644 Binary files a/ext/standard/tests/strings/strtoupper1-win32.phpt and b/ext/standard/tests/strings/strtoupper1-win32.phpt differ diff --git a/main/main.c b/main/main.c index 3a1e92ee08..dc9182e481 100644 --- a/main/main.c +++ b/main/main.c @@ -2133,7 +2133,6 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod zuf.getenv_function = sapi_getenv; zuf.resolve_path_function = php_resolve_path_for_zend; zend_startup(&zuf); - setlocale(LC_CTYPE, ""); zend_update_current_locale(); #if HAVE_TZSET