Skip to content

Commit c4ad8be

Browse files
committed
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 phpGH-5488.
1 parent 707cb18 commit c4ad8be

File tree

7 files changed

+34
-2
lines changed

7 files changed

+34
-2
lines changed

UPGRADING

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,12 @@ PHP 8.0 UPGRADE NOTES
397397
. If the array returned by __sleep() contains non-existing properties, these
398398
are now silently ignored. Previously, such properties would have been
399399
serialized as if they had the value NULL.
400+
. The default locale on startup is now always "C". No locales are inherited
401+
from the environment by default. Previously, LC_ALL was set to "C", while
402+
LC_CTYPE was inherited from the environment. However, some functions did not
403+
respect the inherited locale without an explicit setlocale() call. An
404+
explicit setlocale() call is now always required if you wish to change any
405+
locale component from the default.
400406

401407
- tidy:
402408
. The $use_include_path parameter, which was not used internally, has been

Zend/tests/lc_ctype_inheritance.phpt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
--TEST--
2+
Do not inherit LC_CTYPE from environment
3+
--SKIPIF--
4+
<?php
5+
if (!setlocale(LC_CTYPE, "de_DE", "de-DE")) die("skip requires de_DE locale");
6+
?>
7+
--ENV--
8+
LC_CTYPE=de_DE
9+
--FILE--
10+
<?php
11+
12+
var_dump(setlocale(LC_CTYPE, "0"));
13+
var_dump(bin2hex(strtoupper("\xe4")));
14+
var_dump(preg_match('/\w/', "\xe4"));
15+
var_dump(setlocale(LC_CTYPE, "de_DE", "de-DE") !== false);
16+
var_dump(bin2hex(strtoupper("\xe4")));
17+
var_dump(preg_match('/\w/', "\xe4"));
18+
?>
19+
--EXPECT--
20+
string(1) "C"
21+
string(2) "e4"
22+
int(0)
23+
bool(true)
24+
string(2) "c4"
25+
int(1)

ext/snmp/snmp.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
#ifdef HAVE_UNISTD_H
5050
#include <unistd.h>
5151
#endif
52+
#include <locale.h>
5253

5354
#ifndef __P
5455
#ifdef __GNUC__
@@ -1971,6 +1972,8 @@ PHP_MINIT_FUNCTION(snmp)
19711972
le_snmp_session = zend_register_list_destructors_ex(php_snmp_session_destructor, NULL, PHP_SNMP_SESSION_RES_NAME, module_number);
19721973

19731974
init_snmp("snmpapp");
1975+
/* net-snmp corrupts the CTYPE locale during initialization. */
1976+
setlocale(LC_CTYPE, "C");
19741977

19751978
#ifdef NETSNMP_DS_LIB_DONT_PERSIST_STATE
19761979
/* Prevent update of the snmpapp.conf file */

ext/standard/basic_functions.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,6 @@ PHP_RSHUTDOWN_FUNCTION(basic) /* {{{ */
516516
* to the value in startup environment */
517517
if (BG(locale_changed)) {
518518
setlocale(LC_ALL, "C");
519-
setlocale(LC_CTYPE, "");
520519
zend_update_current_locale();
521520
if (BG(locale_string)) {
522521
zend_string_release_ex(BG(locale_string), 0);
49 Bytes
Binary file not shown.
49 Bytes
Binary file not shown.

main/main.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2133,7 +2133,6 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod
21332133
zuf.getenv_function = sapi_getenv;
21342134
zuf.resolve_path_function = php_resolve_path_for_zend;
21352135
zend_startup(&zuf);
2136-
setlocale(LC_CTYPE, "");
21372136
zend_update_current_locale();
21382137

21392138
#if HAVE_TZSET

0 commit comments

Comments
 (0)