From: fredrik at wangel dot net Operating system: Irrelevant PHP version: 6CVS-2006-12-13 (snap) PHP Bug Type: SOAP related Bug description: to_zval_double() in ext/soap/php_encoding.c is not locale-independent
Description: ------------ [Note: This is an inherent problem within a PHP extension's C code, not with a PHP script] Problem: The SOAPClient/SOAPServer converts xsd:float values in a locale-dependent fashion, causing serious issues when the caller's locale is not English. According to "XML Schema Part 2: Datatypes", a decimal (either xsd:float or xsd:double) is always written using a period (.) as a decimal indicator [See http://www.w3.org/TR/xmlschema-2/#decimal] However, SOAPServer writes decimals using the current locale's (LC_NUMERIC) formatting rules, which is a violation of the standard. Likewise, on the client side, the function to_zval_double() in ext/soap/php_encoding.c uses atof() which parses a string according to the current locale. Since the server and client can have totally different settings for locale, the conversion fails. Hence, if the SOAP server's locale is set to "sv_SE" (Swedish) or some other language that does not use period as decimal indicator, and the SOAP client is in English, the resulting float is truncated into an integer value. Suggested fix is to either either temporarily change LC_NUMERIC [via setlocale()] into "POSIX" (or "C"), or use zend_strtod() for conversion from XML. When converting to XML [using convert_to_string()] the simplest solution should be to change LC_NUMERIC temporarily, since zend_sprintf() also uses current locale settings. PLEASE NOTE: If you do not have the locales from the example (sv_SE and en_US) on your test server, this will likely fallback into C locale, and thus the result always looks good. Verify that your test server formats 123.456 into "123,456". Try "se" or "Swedish" if "sv_SE" fails. Reproduce code: --------------- -- SERVER -- class Server {function getValue(){return (float)123.456;}} setlocale(LC_ALL,"sv_SE"); $server = new SoapServer(null,array('uri'=>'http://localhost/', 'soap_version'=>SOAP_1_2, 'encoding'=>'ISO-8859-1')); $server->setClass("Server"); $server->handle(); --- CLIENT -- $client = new SoapClient(null,array('location'=>'http://localhost/soap/Server.php', 'uri'=>'http://localhost/', 'soap_version'=>SOAP_1_2, 'encoding'=>'ISO-8859-1')); header("Content-Type: text/plain; charset=ISO-8859-1"); setlocale(LC_ALL,"sv_SE"); print((float)123.456 . "\n"); setlocale(LC_ALL,"en_US"); $value = $client->getValue(); var_dump($value); Expected result: ---------------- 123,456 float(123.456) Actual result: -------------- 123,456 float(123) -- Edit bug report at http://bugs.php.net/?id=39815&edit=1 -- Try a CVS snapshot (PHP 4.4): http://bugs.php.net/fix.php?id=39815&r=trysnapshot44 Try a CVS snapshot (PHP 5.2): http://bugs.php.net/fix.php?id=39815&r=trysnapshot52 Try a CVS snapshot (PHP 6.0): http://bugs.php.net/fix.php?id=39815&r=trysnapshot60 Fixed in CVS: http://bugs.php.net/fix.php?id=39815&r=fixedcvs Fixed in release: http://bugs.php.net/fix.php?id=39815&r=alreadyfixed Need backtrace: http://bugs.php.net/fix.php?id=39815&r=needtrace Need Reproduce Script: http://bugs.php.net/fix.php?id=39815&r=needscript Try newer version: http://bugs.php.net/fix.php?id=39815&r=oldversion Not developer issue: http://bugs.php.net/fix.php?id=39815&r=support Expected behavior: http://bugs.php.net/fix.php?id=39815&r=notwrong Not enough info: http://bugs.php.net/fix.php?id=39815&r=notenoughinfo Submitted twice: http://bugs.php.net/fix.php?id=39815&r=submittedtwice register_globals: http://bugs.php.net/fix.php?id=39815&r=globals PHP 3 support discontinued: http://bugs.php.net/fix.php?id=39815&r=php3 Daylight Savings: http://bugs.php.net/fix.php?id=39815&r=dst IIS Stability: http://bugs.php.net/fix.php?id=39815&r=isapi Install GNU Sed: http://bugs.php.net/fix.php?id=39815&r=gnused Floating point limitations: http://bugs.php.net/fix.php?id=39815&r=float No Zend Extensions: http://bugs.php.net/fix.php?id=39815&r=nozend MySQL Configuration Error: http://bugs.php.net/fix.php?id=39815&r=mysqlcfg