summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnatol Belski <ab@php.net>2014-12-06 11:59:43 +0100
committerAnatol Belski <ab@php.net>2014-12-06 11:59:43 +0100
commit1b4d5ad46a60401bb3db754b4ef6888a7285e637 (patch)
tree0f32497547dd60278673d8bfb8ce00c3a7cc8305
parent625b929c6eb222773d175bd22a7b893165b960fd (diff)
downloadphp-git-1b4d5ad46a60401bb3db754b4ef6888a7285e637.tar.gz
Fixed bug #65230 setting locale randomly broken
-rw-r--r--NEWS1
-rw-r--r--ext/standard/formatted_print.c16
-rw-r--r--ext/standard/tests/strings/bug65230.phpt60
-rw-r--r--main/snprintf.c16
-rw-r--r--main/spprintf.c16
-rw-r--r--tests/lang/034.phpt4
-rw-r--r--tests/lang/bug30638.phpt4
7 files changed, 109 insertions, 8 deletions
diff --git a/NEWS b/NEWS
index d62f125028..a78ab396ab 100644
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,7 @@ PHP NEWS
(Anatol)
. Fixed bug #68297 (Application Popup provides too few information). (Anatol)
. Fixed bug #65769 (localeconv() broken in TS builds). (Anatol)
+ . Fixed bug #65230 (setting locale randomly broken). (Anatol)
- cURL:
. Fixed bug #67643 (curl_multi_getcontent returns '' when
diff --git a/ext/standard/formatted_print.c b/ext/standard/formatted_print.c
index 2592b1655d..a21bfebe42 100644
--- a/ext/standard/formatted_print.c
+++ b/ext/standard/formatted_print.c
@@ -27,7 +27,11 @@
#ifdef HAVE_LOCALE_H
#include <locale.h>
+#ifdef ZTS
+#define LCONV_DECIMAL_POINT (*lconv.decimal_point)
+#else
#define LCONV_DECIMAL_POINT (*lconv->decimal_point)
+#endif
#else
#define LCONV_DECIMAL_POINT '.'
#endif
@@ -214,8 +218,12 @@ php_sprintf_appenddouble(char **buffer, int *pos,
char *s = NULL;
int s_len = 0, is_negative = 0;
#ifdef HAVE_LOCALE_H
+#ifdef ZTS
+ struct lconv lconv;
+#else
struct lconv *lconv;
#endif
+#endif
PRINTF_DEBUG(("sprintf: appenddouble(%x, %x, %x, %f, %d, '%c', %d, %c)\n",
*buffer, pos, size, number, width, padding, alignment, fmt));
@@ -246,8 +254,12 @@ php_sprintf_appenddouble(char **buffer, int *pos,
case 'f':
case 'F':
#ifdef HAVE_LOCALE_H
+#ifdef ZTS
+ localeconv_r(&lconv);
+#else
lconv = localeconv();
#endif
+#endif
s = php_conv_fp((fmt == 'f')?'F':fmt, number, 0, precision,
(fmt == 'f')?LCONV_DECIMAL_POINT:'.',
&is_negative, &num_buf[1], &s_len);
@@ -270,8 +282,12 @@ php_sprintf_appenddouble(char **buffer, int *pos,
* * We use &num_buf[ 1 ], so that we have room for the sign
*/
#ifdef HAVE_LOCALE_H
+#ifdef ZTS
+ localeconv_r(&lconv);
+#else
lconv = localeconv();
#endif
+#endif
s = php_gcvt(number, precision, LCONV_DECIMAL_POINT, (fmt == 'G')?'E':'e', &num_buf[1]);
is_negative = 0;
if (*s == '-') {
diff --git a/ext/standard/tests/strings/bug65230.phpt b/ext/standard/tests/strings/bug65230.phpt
new file mode 100644
index 0000000000..ca2c3ca922
--- /dev/null
+++ b/ext/standard/tests/strings/bug65230.phpt
@@ -0,0 +1,60 @@
+--TEST--
+Bug #65230 setting locale randomly broken
+--SKIPIF--
+<?php
+if (substr(PHP_OS, 0, 3) != 'WIN') {
+ die('skip');
+}
+?>
+--INI--
+date.timezone=Europe/Berlin
+--FILE--
+<?php
+
+function test($locale, $value)
+{
+ $newlocale = setlocale(LC_ALL, $locale);
+ $conv = localeconv();
+ $sep = $conv['decimal_point'];
+
+ printf("%s\n--------------------------\n", $newlocale);
+ printf(" sep: %s\n", $sep);
+ printf(" %%f: %f\n", $value);
+ printf(" %%F: %F\n", $value);
+ printf("date: %s\n", strftime('%x'));
+ printf("\n");
+}
+
+test('german', 3.41);
+test('english', 3.41);
+test('french', 3.41);
+test('german', 3.41);
+--EXPECT--
+German_Germany.1252
+--------------------------
+ sep: ,
+ %f: 3,410000
+ %F: 3.410000
+date: 05.12.2014
+
+English_United States.1252
+--------------------------
+ sep: .
+ %f: 3.410000
+ %F: 3.410000
+date: 12/5/2014
+
+French_France.1252
+--------------------------
+ sep: ,
+ %f: 3,410000
+ %F: 3.410000
+date: 05/12/2014
+
+German_Germany.1252
+--------------------------
+ sep: ,
+ %f: 3,410000
+ %F: 3.410000
+date: 05.12.2014
+
diff --git a/main/snprintf.c b/main/snprintf.c
index 1c73dcdcb7..64b6633655 100644
--- a/main/snprintf.c
+++ b/main/snprintf.c
@@ -38,7 +38,11 @@
#ifdef HAVE_LOCALE_H
#include <locale.h>
+#ifdef ZTS
+#define LCONV_DECIMAL_POINT (*lconv.decimal_point)
+#else
#define LCONV_DECIMAL_POINT (*lconv->decimal_point)
+#endif
#else
#define LCONV_DECIMAL_POINT '.'
#endif
@@ -606,8 +610,12 @@ static int format_converter(register buffy * odp, const char *fmt, va_list ap) /
char char_buf[2]; /* for printing %% and %<unknown> */
#ifdef HAVE_LOCALE_H
+#ifdef ZTS
+ struct lconv lconv;
+#else
struct lconv *lconv = NULL;
#endif
+#endif
/*
* Flag variables
@@ -998,10 +1006,14 @@ static int format_converter(register buffy * odp, const char *fmt, va_list ap) /
s_len = 3;
} else {
#ifdef HAVE_LOCALE_H
+#ifdef ZTS
+ localeconv_r(&lconv);
+#else
if (!lconv) {
lconv = localeconv();
}
#endif
+#endif
s = php_conv_fp((*fmt == 'f')?'F':*fmt, fp_num, alternate_form,
(adjust_precision == NO) ? FLOAT_DIGITS : precision,
(*fmt == 'f')?LCONV_DECIMAL_POINT:'.',
@@ -1055,10 +1067,14 @@ static int format_converter(register buffy * odp, const char *fmt, va_list ap) /
* * We use &num_buf[ 1 ], so that we have room for the sign
*/
#ifdef HAVE_LOCALE_H
+#ifdef ZTS
+ localeconv_r(&lconv);
+#else
if (!lconv) {
lconv = localeconv();
}
#endif
+#endif
s = php_gcvt(fp_num, precision, (*fmt=='H' || *fmt == 'k') ? '.' : LCONV_DECIMAL_POINT, (*fmt == 'G' || *fmt == 'H')?'E':'e', &num_buf[1]);
if (*s == '-') {
prefix_char = *s++;
diff --git a/main/spprintf.c b/main/spprintf.c
index 5b16d51441..212914fe9d 100644
--- a/main/spprintf.c
+++ b/main/spprintf.c
@@ -93,7 +93,11 @@
#ifdef HAVE_LOCALE_H
#include <locale.h>
+#ifdef ZTS
+#define LCONV_DECIMAL_POINT (*lconv.decimal_point)
+#else
#define LCONV_DECIMAL_POINT (*lconv->decimal_point)
+#endif
#else
#define LCONV_DECIMAL_POINT '.'
#endif
@@ -217,8 +221,12 @@ static void xbuf_format_converter(smart_str *xbuf, const char *fmt, va_list ap)
char char_buf[2]; /* for printing %% and %<unknown> */
#ifdef HAVE_LOCALE_H
+#ifdef ZTS
+ struct lconv lconv;
+#else
struct lconv *lconv = NULL;
#endif
+#endif
/*
* Flag variables
@@ -608,10 +616,14 @@ static void xbuf_format_converter(smart_str *xbuf, const char *fmt, va_list ap)
s_len = 3;
} else {
#ifdef HAVE_LOCALE_H
+#ifdef ZTS
+ localeconv_r(&lconv);
+#else
if (!lconv) {
lconv = localeconv();
}
#endif
+#endif
s = php_conv_fp((*fmt == 'f')?'F':*fmt, fp_num, alternate_form,
(adjust_precision == NO) ? FLOAT_DIGITS : precision,
(*fmt == 'f')?LCONV_DECIMAL_POINT:'.',
@@ -664,10 +676,14 @@ static void xbuf_format_converter(smart_str *xbuf, const char *fmt, va_list ap)
* * We use &num_buf[ 1 ], so that we have room for the sign
*/
#ifdef HAVE_LOCALE_H
+#ifdef ZTS
+ localeconv_r(&lconv);
+#else
if (!lconv) {
lconv = localeconv();
}
#endif
+#endif
s = php_gcvt(fp_num, precision, (*fmt=='H' || *fmt == 'k') ? '.' : LCONV_DECIMAL_POINT, (*fmt == 'G' || *fmt == 'H')?'E':'e', &num_buf[1]);
if (*s == '-')
prefix_char = *s++;
diff --git a/tests/lang/034.phpt b/tests/lang/034.phpt
index cea0797d69..5d2c610926 100644
--- a/tests/lang/034.phpt
+++ b/tests/lang/034.phpt
@@ -4,10 +4,6 @@ Bug #12647 (Locale settings affecting float parsing)
precision=14
--SKIPIF--
<?php # try to activate a german locale
-if (substr(PHP_OS, 0, 3) == 'WIN') {
- /* skip on windows until #63688 was fixed */
- die('skip');
-}
if (setlocale(LC_NUMERIC, "de_DE.UTF-8", "de_DE", "de", "german", "ge", "de_DE.ISO-8859-1") === FALSE) {
print "skip Can't find german locale";
}
diff --git a/tests/lang/bug30638.phpt b/tests/lang/bug30638.phpt
index 945a228eda..30b70f30fb 100644
--- a/tests/lang/bug30638.phpt
+++ b/tests/lang/bug30638.phpt
@@ -2,10 +2,6 @@
Bug #30638 (localeconv returns wrong LC_NUMERIC settings) (ok to fail on MacOS X)
--SKIPIF--
<?php # try to activate a german locale
-if (substr(PHP_OS, 0, 3) == 'WIN') {
- /* skip on windows until #63688 was fixed */
- die('skip');
-}
if (setlocale(LC_NUMERIC, "de_DE.UTF-8", "de_DE", "de", "german", "ge", "de_DE.ISO-8859-1") === FALSE) {
print "skip setlocale() failed";
} elseif (strtolower(php_uname('s')) == 'darwin') {