summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2015-01-09 01:41:13 +0300
committerDmitry Stogov <dmitry@zend.com>2015-01-09 01:41:13 +0300
commit7b4808a6471655b44e65cfb4585c01f2efea444a (patch)
tree079cd73b2731c42112c96d8cab2b0a0c8b527348
parented8ebd6ce40650d54a283e3296151d86e12d7ece (diff)
downloadphp-git-7b4808a6471655b44e65cfb4585c01f2efea444a.tar.gz
Fixed bug #68636 (setlocale no longer returns current value per category).
-rw-r--r--ext/standard/basic_functions.c9
-rw-r--r--ext/standard/basic_functions.h3
-rw-r--r--ext/standard/string.c36
-rw-r--r--ext/standard/tests/strings/bug68636.phpt21
4 files changed, 49 insertions, 20 deletions
diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c
index ed5206aa69..02001f5433 100644
--- a/ext/standard/basic_functions.c
+++ b/ext/standard/basic_functions.c
@@ -3708,6 +3708,7 @@ PHP_RINIT_FUNCTION(basic) /* {{{ */
ZVAL_UNDEF(&BG(strtok_zval));
BG(strtok_last) = NULL;
BG(locale_string) = NULL;
+ BG(locale_changed) = 0;
BG(array_walk_fci) = empty_fcall_info;
BG(array_walk_fci_cache) = empty_fcall_info_cache;
BG(user_compare_fci) = empty_fcall_info;
@@ -3756,12 +3757,14 @@ PHP_RSHUTDOWN_FUNCTION(basic) /* {{{ */
/* Check if locale was changed and change it back
* to the value in startup environment */
- if (BG(locale_string) != NULL) {
+ if (BG(locale_changed)) {
setlocale(LC_ALL, "C");
setlocale(LC_CTYPE, "");
zend_update_current_locale();
- zend_string_release(BG(locale_string));
- BG(locale_string) = NULL;
+ if (BG(locale_string)) {
+ zend_string_release(BG(locale_string));
+ BG(locale_string) = NULL;
+ }
}
/* FG(stream_wrappers) and FG(stream_filters) are destroyed
diff --git a/ext/standard/basic_functions.h b/ext/standard/basic_functions.h
index fe09dc5e25..8820148a63 100644
--- a/ext/standard/basic_functions.h
+++ b/ext/standard/basic_functions.h
@@ -168,7 +168,8 @@ typedef struct _php_basic_globals {
HashTable putenv_ht;
zval strtok_zval;
char *strtok_string;
- zend_string *locale_string;
+ zend_string *locale_string; /* current LC_CTYPE locale (or NULL for 'C') */
+ zend_bool locale_changed; /* locale was changed and has to be restored */
char *strtok_last;
char strtok_table[256];
zend_ulong strtok_len;
diff --git a/ext/standard/string.c b/ext/standard/string.c
index c57885fff1..483e8b4f1d 100644
--- a/ext/standard/string.c
+++ b/ext/standard/string.c
@@ -4343,27 +4343,31 @@ PHP_FUNCTION(setlocale)
if (retval) {
if (loc) {
/* Remember if locale was changed */
- size_t len;
+ size_t len = strlen(retval);
- if (BG(locale_string)) {
- zend_string_release(BG(locale_string));
- }
- len = strlen(retval);
- if (len == loc->len && !memcmp(loc->val, retval, len)) {
- BG(locale_string) = zend_string_copy(loc);
- } else {
- BG(locale_string) = zend_string_init(retval, len, 0);
+ BG(locale_changed) = 1;
+ if (cat == LC_CTYPE || cat == LC_ALL) {
+ if (BG(locale_string)) {
+ zend_string_release(BG(locale_string));
+ }
+ if (len == loc->len && !memcmp(loc->val, retval, len)) {
+ BG(locale_string) = zend_string_copy(loc);
+ RETURN_STR(BG(locale_string));
+ } else {
+ BG(locale_string) = zend_string_init(retval, len, 0);
+ zend_string_release(loc);
+ RETURN_STR(BG(locale_string));
+ }
+ } else if (len == loc->len && !memcmp(loc->val, retval, len)) {
+ RETURN_STR(loc);
}
-
zend_string_release(loc);
}
- if (BG(locale_string)) {
- RETURN_STR(zend_string_copy(BG(locale_string)));
- } else {
- RETURN_EMPTY_STRING();
- }
+ RETURN_STRING(retval);
+ }
+ if (loc) {
+ zend_string_release(loc);
}
- zend_string_release(loc);
if (Z_TYPE(args[0]) == IS_ARRAY) {
if (zend_hash_move_forward_ex(Z_ARRVAL(args[0]), &pos) == FAILURE) break;
diff --git a/ext/standard/tests/strings/bug68636.phpt b/ext/standard/tests/strings/bug68636.phpt
new file mode 100644
index 0000000000..246722c7aa
--- /dev/null
+++ b/ext/standard/tests/strings/bug68636.phpt
@@ -0,0 +1,21 @@
+--TEST--
+Bug #68636 (setlocale no longer returns current value per category).
+--SKIPIF--
+<?php
+if (substr(PHP_OS, 0, 3) == 'WIN') {
+ die('skip Not valid for windows');
+}
+if (setlocale(LC_ALL, "en_US.UTF8") !== "en_US.UTF8") {
+ die('skip available locales not usable');
+}
+?>
+--FILE--
+<?php
+var_dump(setlocale(LC_TIME, 'en_US.UTF8'));
+var_dump(setlocale(LC_NUMERIC, 'C'));
+var_dump(setlocale(LC_TIME, 0));
+?>
+--EXPECT--
+string(10) "en_US.UTF8"
+string(1) "C"
+string(10) "en_US.UTF8"