dmitry Tue Dec 19 11:55:17 2006 UTC
Modified files:
/php-src/main snprintf.c snprintf.h spprintf.c
/php-src/ext/standard formatted_print.c
/php-src/ext/soap php_encoding.c
/php-src/ext/soap/tests/bugs bug39815.phpt
/php-src/ext/soap/tests/interop/Round3/GroupD
r3_groupD_compound2_001w.phpt
Log:
Fixed bug #39815 (SOAP double encoding is not locale-independent)
http://cvs.php.net/viewvc.cgi/php-src/main/snprintf.c?r1=1.44&r2=1.45&diff_format=u
Index: php-src/main/snprintf.c
diff -u php-src/main/snprintf.c:1.44 php-src/main/snprintf.c:1.45
--- php-src/main/snprintf.c:1.44 Mon Dec 18 09:25:32 2006
+++ php-src/main/snprintf.c Tue Dec 19 11:55:16 2006
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: snprintf.c,v 1.44 2006/12/18 09:25:32 bjori Exp $ */
+/* $Id: snprintf.c,v 1.45 2006/12/19 11:55:16 dmitry Exp $ */
#include "php.h"
@@ -115,23 +115,20 @@
return(s);
}
-char *bsd_ecvt(double value, int ndigit, int *decpt, int *sign)
+static inline char *php_ecvt(double value, int ndigit, int *decpt, int *sign)
{
return(__cvt(value, ndigit, decpt, sign, 0, 1));
}
-char *bsd_fcvt(double value, int ndigit, int *decpt, int *sign)
+static inline char *php_fcvt(double value, int ndigit, int *decpt, int *sign)
{
return(__cvt(value, ndigit, decpt, sign, 1, 1));
}
-char *bsd_gcvt(double value, int ndigit, char *buf)
+PHPAPI char *php_gcvt(double value, int ndigit, char dec_point, char exponent,
char *buf)
{
char *digits, *dst, *src;
int i, decpt, sign;
- struct lconv *lconv;
-
- lconv = localeconv();
digits = zend_dtoa(value, 2, ndigit, &decpt, &sign, NULL);
if (decpt == 9999) {
@@ -161,7 +158,7 @@
sign = 0;
src = digits;
*dst++ = *src++;
- *dst++ = *lconv->decimal_point;
+ *dst++ = dec_point;
if (*src == '\0') {
*dst++ = '0';
} else {
@@ -169,7 +166,7 @@
*dst++ = *src++;
} while (*src != '\0');
}
- *dst++ = 'e';
+ *dst++ = exponent;
if (sign)
*dst++ = '-';
else
@@ -190,7 +187,7 @@
} else if (decpt < 0) {
/* standard format 0. */
*dst++ = '0'; /* zero before decimal point */
- *dst++ = *lconv->decimal_point;
+ *dst++ = dec_point;
do {
*dst++ = '0';
} while (++decpt < 0);
@@ -210,7 +207,7 @@
if (*src != '\0') {
if (src == digits)
*dst++ = '0'; /* zero before decimal point */
- *dst++ = *lconv->decimal_point;
+ *dst++ = dec_point;
for (i = decpt; digits[i] != '\0'; i++) {
*dst++ = digits[i];
}
@@ -357,29 +354,21 @@
* The sign is returned in the is_negative argument (and is not placed
* in buf).
*/
-char * ap_php_conv_fp(register char format, register double num,
- boolean_e add_dp, int precision, bool_int * is_negative, char
*buf, int *len)
+PHPAPI char * php_conv_fp(register char format, register double num,
+ boolean_e add_dp, int precision, char dec_point, bool_int *
is_negative, char *buf, int *len)
{
register char *s = buf;
register char *p, *p_orig;
int decimal_point;
- char dec_point = '.';
-
- if (format == 'f') {
- struct lconv *lconv;
- lconv = localeconv();
- dec_point = *lconv->decimal_point;
- format = 'F';
- }
if (precision >= NDIG - 1) {
precision = NDIG - 2;
}
if (format == 'F')
- p_orig = p = bsd_fcvt(num, precision, &decimal_point,
is_negative);
+ p_orig = p = php_fcvt(num, precision, &decimal_point,
is_negative);
else /* either e or E format
*/
- p_orig = p = bsd_ecvt(num, precision + 1, &decimal_point,
is_negative);
+ p_orig = p = php_ecvt(num, precision + 1, &decimal_point,
is_negative);
/*
* Check for Infinity and NaN
@@ -595,6 +584,8 @@
char num_buf[NUM_BUF_SIZE];
char char_buf[2]; /* for printing %% and
%<unknown> */
+ struct lconv *lconv = NULL;
+
/*
* Flag variables
*/
@@ -929,6 +920,7 @@
case 'f':
+ case 'F':
case 'e':
case 'E':
switch(modifier) {
@@ -949,8 +941,12 @@
s = "inf";
s_len = 3;
} else {
- s = ap_php_conv_fp(*fmt,
fp_num, alternate_form,
+ if (!lconv) {
+ lconv = localeconv();
+ }
+ s = php_conv_fp((*fmt ==
'f')?'F':*fmt, fp_num, alternate_form,
(adjust_precision == NO) ?
FLOAT_DIGITS : precision,
+ (*fmt ==
'f')?(*lconv->decimal_point):'.',
&is_negative, &num_buf[1], &s_len);
if (is_negative)
prefix_char = '-';
@@ -997,7 +993,10 @@
/*
* * We use &num_buf[ 1 ], so that we
have room for the sign
*/
- s = bsd_gcvt(fp_num, precision,
&num_buf[1]);
+ if (!lconv) {
+ lconv = localeconv();
+ }
+ s = php_gcvt(fp_num, precision,
*lconv->decimal_point, (*fmt == 'G')?'E':'e', &num_buf[1]);
if (*s == '-')
prefix_char = *s++;
else if (print_sign)
@@ -1009,8 +1008,6 @@
if (alternate_form && (q = strchr(s,
'.')) == NULL)
s[s_len++] = '.';
- if (*fmt == 'G' && (q = strchr(s, 'e'))
!= NULL)
- *q = 'E';
break;
http://cvs.php.net/viewvc.cgi/php-src/main/snprintf.h?r1=1.36&r2=1.37&diff_format=u
Index: php-src/main/snprintf.h
diff -u php-src/main/snprintf.h:1.36 php-src/main/snprintf.h:1.37
--- php-src/main/snprintf.h:1.36 Wed Dec 6 09:50:28 2006
+++ php-src/main/snprintf.h Tue Dec 19 11:55:16 2006
@@ -17,7 +17,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: snprintf.h,v 1.36 2006/12/06 09:50:28 tony2001 Exp $ */
+/* $Id: snprintf.h,v 1.37 2006/12/19 11:55:16 dmitry Exp $ */
/*
@@ -65,10 +65,19 @@
#ifndef SNPRINTF_H
#define SNPRINTF_H
+typedef int bool_int;
+
+typedef enum {
+ NO = 0, YES = 1
+} boolean_e;
+
BEGIN_EXTERN_C()
PHPAPI int ap_php_snprintf(char *, size_t, const char *, ...)
PHP_ATTRIBUTE_FORMAT(printf, 3, 4);
PHPAPI int ap_php_vsnprintf(char *, size_t, const char *, va_list ap)
PHP_ATTRIBUTE_FORMAT(printf, 3, 0);
PHPAPI int php_sprintf (char* s, const char* format, ...)
PHP_ATTRIBUTE_FORMAT(printf, 2, 3);
+PHPAPI char * php_gcvt(double value, int ndigit, char dec_point, char
exponent, char *buf);
+PHPAPI char * php_conv_fp(register char format, register double num,
+ boolean_e add_dp, int precision, char dec_point, bool_int *
is_negative, char *buf, int *len);
END_EXTERN_C()
#ifdef snprintf
@@ -87,10 +96,6 @@
#define sprintf php_sprintf
typedef enum {
- NO = 0, YES = 1
-} boolean_e;
-
-typedef enum {
LM_STD = 0,
#if SIZEOF_INTMAX_T
LM_INTMAX_T,
@@ -118,21 +123,12 @@
typedef WIDE_INT wide_int;
typedef unsigned WIDE_INT u_wide_int;
-typedef int bool_int;
-
extern char * ap_php_conv_10(register wide_int num, register bool_int
is_unsigned,
register bool_int * is_negative, char *buf_end, register int *len);
-extern char * ap_php_conv_fp(register char format, register double num,
- boolean_e add_dp, int precision, bool_int * is_negative, char
*buf, int *len);
-
extern char * ap_php_conv_p2(register u_wide_int num, register int nbits,
char format, char *buf_end, register int *len);
-extern char * bsd_ecvt(double value, int ndigit, int *decpt, int *sign);
-extern char * bsd_fcvt(double value, int ndigit, int *decpt, int *sign);
-extern char * bsd_gcvt(double value, int ndigit, char *buf);
-
#endif /* SNPRINTF_H */
/*
http://cvs.php.net/viewvc.cgi/php-src/main/spprintf.c?r1=1.38&r2=1.39&diff_format=u
Index: php-src/main/spprintf.c
diff -u php-src/main/spprintf.c:1.38 php-src/main/spprintf.c:1.39
--- php-src/main/spprintf.c:1.38 Wed Dec 6 09:50:28 2006
+++ php-src/main/spprintf.c Tue Dec 19 11:55:16 2006
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: spprintf.c,v 1.38 2006/12/06 09:50:28 tony2001 Exp $ */
+/* $Id: spprintf.c,v 1.39 2006/12/19 11:55:16 dmitry Exp $ */
/* This is the spprintf implementation.
* It has emerged from apache snprintf. See original header:
@@ -91,6 +91,10 @@
#include <inttypes.h>
#endif
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
+
#include "snprintf.h"
#define FALSE 0
@@ -226,6 +230,8 @@
char char_buf[2]; /* for printing %% and
%<unknown> */
zend_bool free_s; /* free string if allocated here */
+ struct lconv *lconv = NULL;
+
/*
* Flag variables
*/
@@ -617,6 +623,7 @@
break;
case 'f':
+ case 'F':
case 'e':
case 'E':
switch(modifier) {
@@ -637,8 +644,12 @@
s = "inf";
s_len = 3;
} else {
- s = ap_php_conv_fp(*fmt,
fp_num, alternate_form,
-
(adjust_precision == NO) ? FLOAT_DIGITS : precision,
+ if (!lconv) {
+ lconv = localeconv();
+ }
+ s = php_conv_fp((*fmt ==
'f')?'F':*fmt, fp_num, alternate_form,
+ (adjust_precision == NO) ?
FLOAT_DIGITS : precision,
+ (*fmt ==
'f')?(*lconv->decimal_point):'.',
&is_negative, &num_buf[1], &s_len);
if (is_negative)
prefix_char = '-';
@@ -685,7 +696,10 @@
/*
* * We use &num_buf[ 1 ], so that we
have room for the sign
*/
- s = bsd_gcvt(fp_num, precision,
&num_buf[1]);
+ if (!lconv) {
+ lconv = localeconv();
+ }
+ s = php_gcvt(fp_num, precision,
*lconv->decimal_point, (*fmt == 'G')?'E':'e', &num_buf[1]);
if (*s == '-')
prefix_char = *s++;
else if (print_sign)
@@ -697,8 +711,6 @@
if (alternate_form && (q = strchr(s,
'.')) == NULL)
s[s_len++] = '.';
- if (*fmt == 'G' && (q = strchr(s, 'e'))
!= NULL)
- *q = 'E';
break;
http://cvs.php.net/viewvc.cgi/php-src/ext/standard/formatted_print.c?r1=1.89&r2=1.90&diff_format=u
Index: php-src/ext/standard/formatted_print.c
diff -u php-src/ext/standard/formatted_print.c:1.89
php-src/ext/standard/formatted_print.c:1.90
--- php-src/ext/standard/formatted_print.c:1.89 Mon Dec 18 09:25:32 2006
+++ php-src/ext/standard/formatted_print.c Tue Dec 19 11:55:16 2006
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: formatted_print.c,v 1.89 2006/12/18 09:25:32 bjori Exp $ */
+/* $Id: formatted_print.c,v 1.90 2006/12/19 11:55:16 dmitry Exp $ */
#include <math.h> /* modf() */
#include "php.h"
@@ -196,8 +196,9 @@
TSRMLS_DC)
{
char num_buf[NUM_BUF_SIZE];
- char *s = NULL, *q;
+ char *s = NULL;
int s_len = 0, is_negative = 0;
+ struct lconv *lconv;
PRINTF_DEBUG(("sprintf: appenddouble(%x, %x, %x, %f, %d, '%c', %d,
%c)\n",
*buffer, pos, size, number, width, padding,
alignment, fmt));
@@ -229,7 +230,9 @@
case 'E':
case 'f':
case 'F':
- s = ap_php_conv_fp(fmt, number, 0, precision,
+ lconv = localeconv();
+ s = php_conv_fp((fmt == 'f')?'F':fmt, number, 0,
precision,
+ (fmt ==
'f')?(*lconv->decimal_point):'.',
&is_negative, &num_buf[1],
&s_len);
if (is_negative) {
num_buf[0] = '-';
@@ -249,7 +252,8 @@
/*
* * We use &num_buf[ 1 ], so that we have room for the
sign
*/
- s = bsd_gcvt(number, precision, &num_buf[1]);
+ lconv = localeconv();
+ s = php_gcvt(number, precision, *lconv->decimal_point,
(fmt == 'G')?'E':'e', &num_buf[1]);
is_negative = 0;
if (*s == '-') {
is_negative = 1;
@@ -260,10 +264,6 @@
}
s_len = strlen(s);
-
- if (fmt == 'G' && (q = strchr(s, 'e')) != NULL) {
- *q = 'E';
- }
break;
}
http://cvs.php.net/viewvc.cgi/php-src/ext/soap/php_encoding.c?r1=1.148&r2=1.149&diff_format=u
Index: php-src/ext/soap/php_encoding.c
diff -u php-src/ext/soap/php_encoding.c:1.148
php-src/ext/soap/php_encoding.c:1.149
--- php-src/ext/soap/php_encoding.c:1.148 Mon Dec 18 14:39:39 2006
+++ php-src/ext/soap/php_encoding.c Tue Dec 19 11:55:16 2006
@@ -17,7 +17,7 @@
| Dmitry Stogov <[EMAIL PROTECTED]> |
+----------------------------------------------------------------------+
*/
-/* $Id: php_encoding.c,v 1.148 2006/12/18 14:39:39 dmitry Exp $ */
+/* $Id: php_encoding.c,v 1.149 2006/12/19 11:55:16 dmitry Exp $ */
#include <time.h>
@@ -928,19 +928,23 @@
{
xmlNodePtr ret;
zval tmp;
+ char *str;
+ TSRMLS_FETCH();
ret = xmlNewNode(NULL, BAD_CAST("BOGUS"));
xmlAddChild(parent, ret);
FIND_ZVAL_NULL(data, ret, style);
tmp = *data;
- zval_copy_ctor(&tmp);
if (Z_TYPE(tmp) != IS_DOUBLE) {
+ zval_copy_ctor(&tmp);
convert_to_double(&tmp);
}
- convert_to_string(&tmp);
- xmlNodeSetContentLen(ret, BAD_CAST(Z_STRVAL(tmp)), Z_STRLEN(tmp));
- zval_dtor(&tmp);
+
+ str = (char *) emalloc(MAX_LENGTH_OF_DOUBLE + EG(precision) + 1);
+ php_gcvt(Z_DVAL(tmp), EG(precision), '.', 'E', str);
+ xmlNodeSetContentLen(ret, BAD_CAST(str), strlen(str));
+ efree(str);
if (style == SOAP_ENCODED) {
set_ns_and_type(ret, type);
http://cvs.php.net/viewvc.cgi/php-src/ext/soap/tests/bugs/bug39815.phpt?r1=1.1&r2=1.2&diff_format=u
Index: php-src/ext/soap/tests/bugs/bug39815.phpt
diff -u /dev/null php-src/ext/soap/tests/bugs/bug39815.phpt:1.2
--- /dev/null Tue Dec 19 11:55:17 2006
+++ php-src/ext/soap/tests/bugs/bug39815.phpt Tue Dec 19 11:55:16 2006
@@ -0,0 +1,42 @@
+--TEST--
+Bug #39815 (to_zval_double() in ext/soap/php_encoding.c is not
locale-independent)
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+function test(){
+ return 123.456;
+}
+class LocalSoapClient extends SoapClient {
+
+ function __construct($wsdl, $options) {
+ parent::__construct($wsdl, $options);
+ $this->server = new SoapServer($wsdl, $options);
+ $this->server->addFunction('test');
+ }
+
+ function __doRequest($request, $location, $action, $version) {
+ ob_start();
+ $this->server->handle($request);
+ $response = ob_get_contents();
+ ob_end_clean();
+ return $response;
+ }
+
+}
+$x = new LocalSoapClient(NULL,array('location'=>'test://',
+ 'uri'=>'http://testuri.org',
+ "trace"=>1));
[EMAIL PROTECTED](LC_ALL,"sv_SE");
+var_dump($x->test());
+echo $x->__getLastResponse();
[EMAIL PROTECTED](LC_ALL,"en_US");
+var_dump($x->test());
+echo $x->__getLastResponse();
+--EXPECT--
+float(123,456)
+<?xml version="1.0" encoding="UTF-8"?>
+<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="http://testuri.org" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:testResponse><return
xsi:type="xsd:float">123.456</return></ns1:testResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>
+float(123.456)
+<?xml version="1.0" encoding="UTF-8"?>
+<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="http://testuri.org" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:testResponse><return
xsi:type="xsd:float">123.456</return></ns1:testResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>
http://cvs.php.net/viewvc.cgi/php-src/ext/soap/tests/interop/Round3/GroupD/r3_groupD_compound2_001w.phpt?r1=1.2&r2=1.3&diff_format=u
Index:
php-src/ext/soap/tests/interop/Round3/GroupD/r3_groupD_compound2_001w.phpt
diff -u
php-src/ext/soap/tests/interop/Round3/GroupD/r3_groupD_compound2_001w.phpt:1.2
php-src/ext/soap/tests/interop/Round3/GroupD/r3_groupD_compound2_001w.phpt:1.3
---
php-src/ext/soap/tests/interop/Round3/GroupD/r3_groupD_compound2_001w.phpt:1.2
Wed Aug 24 11:46:26 2005
+++ php-src/ext/soap/tests/interop/Round3/GroupD/r3_groupD_compound2_001w.phpt
Tue Dec 19 11:55:16 2006
@@ -31,7 +31,7 @@
?>
--EXPECT--
<?xml version="1.0" encoding="UTF-8"?>
-<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="http://soapinterop.org/person"
xmlns:ns2="http://soapinterop.org/employee"><SOAP-ENV:Body><ns2:x_Employee><ns2:person><ns1:Name>Shane</ns1:Name><ns1:Male>true</ns1:Male></ns2:person><ns2:salary>1000000</ns2:salary><ns2:ID>12345</ns2:ID></ns2:x_Employee></SOAP-ENV:Body></SOAP-ENV:Envelope>
+<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="http://soapinterop.org/person"
xmlns:ns2="http://soapinterop.org/employee"><SOAP-ENV:Body><ns2:x_Employee><ns2:person><ns1:Name>Shane</ns1:Name><ns1:Male>true</ns1:Male></ns2:person><ns2:salary>1.0E+6</ns2:salary><ns2:ID>12345</ns2:ID></ns2:x_Employee></SOAP-ENV:Body></SOAP-ENV:Envelope>
<?xml version="1.0" encoding="UTF-8"?>
-<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="http://soapinterop.org/person"
xmlns:ns2="http://soapinterop.org/employee"><SOAP-ENV:Body><ns2:result_Employee><ns2:person><ns1:Name>Shane</ns1:Name><ns1:Male>true</ns1:Male></ns2:person><ns2:salary>1000000</ns2:salary><ns2:ID>12345</ns2:ID></ns2:result_Employee></SOAP-ENV:Body></SOAP-ENV:Envelope>
+<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="http://soapinterop.org/person"
xmlns:ns2="http://soapinterop.org/employee"><SOAP-ENV:Body><ns2:result_Employee><ns2:person><ns1:Name>Shane</ns1:Name><ns1:Male>true</ns1:Male></ns2:person><ns2:salary>1.0E+6</ns2:salary><ns2:ID>12345</ns2:ID></ns2:result_Employee></SOAP-ENV:Body></SOAP-ENV:Envelope>
ok
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php