Skip to content

Commit 7b4808a

Browse files
committed
Fixed bug #68636 (setlocale no longer returns current value per category).
1 parent ed8ebd6 commit 7b4808a

File tree

4 files changed

+49
-20
lines changed

4 files changed

+49
-20
lines changed

ext/standard/basic_functions.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3708,6 +3708,7 @@ PHP_RINIT_FUNCTION(basic) /* {{{ */
37083708
ZVAL_UNDEF(&BG(strtok_zval));
37093709
BG(strtok_last) = NULL;
37103710
BG(locale_string) = NULL;
3711+
BG(locale_changed) = 0;
37113712
BG(array_walk_fci) = empty_fcall_info;
37123713
BG(array_walk_fci_cache) = empty_fcall_info_cache;
37133714
BG(user_compare_fci) = empty_fcall_info;
@@ -3756,12 +3757,14 @@ PHP_RSHUTDOWN_FUNCTION(basic) /* {{{ */
37563757

37573758
/* Check if locale was changed and change it back
37583759
* to the value in startup environment */
3759-
if (BG(locale_string) != NULL) {
3760+
if (BG(locale_changed)) {
37603761
setlocale(LC_ALL, "C");
37613762
setlocale(LC_CTYPE, "");
37623763
zend_update_current_locale();
3763-
zend_string_release(BG(locale_string));
3764-
BG(locale_string) = NULL;
3764+
if (BG(locale_string)) {
3765+
zend_string_release(BG(locale_string));
3766+
BG(locale_string) = NULL;
3767+
}
37653768
}
37663769

37673770
/* FG(stream_wrappers) and FG(stream_filters) are destroyed

ext/standard/basic_functions.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,8 @@ typedef struct _php_basic_globals {
168168
HashTable putenv_ht;
169169
zval strtok_zval;
170170
char *strtok_string;
171-
zend_string *locale_string;
171+
zend_string *locale_string; /* current LC_CTYPE locale (or NULL for 'C') */
172+
zend_bool locale_changed; /* locale was changed and has to be restored */
172173
char *strtok_last;
173174
char strtok_table[256];
174175
zend_ulong strtok_len;

ext/standard/string.c

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4343,27 +4343,31 @@ PHP_FUNCTION(setlocale)
43434343
if (retval) {
43444344
if (loc) {
43454345
/* Remember if locale was changed */
4346-
size_t len;
4346+
size_t len = strlen(retval);
43474347

4348-
if (BG(locale_string)) {
4349-
zend_string_release(BG(locale_string));
4350-
}
4351-
len = strlen(retval);
4352-
if (len == loc->len && !memcmp(loc->val, retval, len)) {
4353-
BG(locale_string) = zend_string_copy(loc);
4354-
} else {
4355-
BG(locale_string) = zend_string_init(retval, len, 0);
4348+
BG(locale_changed) = 1;
4349+
if (cat == LC_CTYPE || cat == LC_ALL) {
4350+
if (BG(locale_string)) {
4351+
zend_string_release(BG(locale_string));
4352+
}
4353+
if (len == loc->len && !memcmp(loc->val, retval, len)) {
4354+
BG(locale_string) = zend_string_copy(loc);
4355+
RETURN_STR(BG(locale_string));
4356+
} else {
4357+
BG(locale_string) = zend_string_init(retval, len, 0);
4358+
zend_string_release(loc);
4359+
RETURN_STR(BG(locale_string));
4360+
}
4361+
} else if (len == loc->len && !memcmp(loc->val, retval, len)) {
4362+
RETURN_STR(loc);
43564363
}
4357-
43584364
zend_string_release(loc);
43594365
}
4360-
if (BG(locale_string)) {
4361-
RETURN_STR(zend_string_copy(BG(locale_string)));
4362-
} else {
4363-
RETURN_EMPTY_STRING();
4364-
}
4366+
RETURN_STRING(retval);
4367+
}
4368+
if (loc) {
4369+
zend_string_release(loc);
43654370
}
4366-
zend_string_release(loc);
43674371

43684372
if (Z_TYPE(args[0]) == IS_ARRAY) {
43694373
if (zend_hash_move_forward_ex(Z_ARRVAL(args[0]), &pos) == FAILURE) break;
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
Bug #68636 (setlocale no longer returns current value per category).
3+
--SKIPIF--
4+
<?php
5+
if (substr(PHP_OS, 0, 3) == 'WIN') {
6+
die('skip Not valid for windows');
7+
}
8+
if (setlocale(LC_ALL, "en_US.UTF8") !== "en_US.UTF8") {
9+
die('skip available locales not usable');
10+
}
11+
?>
12+
--FILE--
13+
<?php
14+
var_dump(setlocale(LC_TIME, 'en_US.UTF8'));
15+
var_dump(setlocale(LC_NUMERIC, 'C'));
16+
var_dump(setlocale(LC_TIME, 0));
17+
?>
18+
--EXPECT--
19+
string(10) "en_US.UTF8"
20+
string(1) "C"
21+
string(10) "en_US.UTF8"

0 commit comments

Comments
 (0)