php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #54973 SimpleXML casts intergers wrong.
Submitted: 2011-06-01 22:18 UTC Modified: 2017-12-26 11:41 UTC
Votes:6
Avg. Score:3.5 ± 0.8
Reproduced:4 of 4 (100.0%)
Same Version:1 (25.0%)
Same OS:2 (50.0%)
From: bphelpsen at gmail dot com Assigned: nikic (profile)
Status: Closed Package: SimpleXML related
PHP Version: 5.3.6 OS: Linux
Private report: No CVE-ID: None
 [2011-06-01 22:18 UTC] bphelpsen at gmail dot com
Description:
------------
When an XML node value is an integer SimpleXML always casts it to an int, even if its a float or double.

Test script:
---------------
<?php
$xml = simplexml_load_string("<xml><number>214748364800</number></xml>");

echo $xml->number . "\n"; // the proper number

$int = $xml->number / 1024 / 1024 / 1024; // initial cast to an int causes problems
echo $int . "\n"; 

$double = (double) $xml->number / 1024 / 1024 / 1024; // hard cast to a double fixes it
echo $double . "\n";
?>

Expected result:
----------------
214748364800
200
200

Actual result:
--------------
214748364800
1.9999999990687
200

Patches

Add a Patch

Pull Requests

Pull requests:

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2011-06-02 20:00 UTC] iliaa@php.net
-Status: Open +Status: Bogus
 [2011-06-02 20:00 UTC] iliaa@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php

This has nothing to do with SimpleXML, but rather the fact that a numeric string 
in PHP by default would converted to an integer.
 [2011-06-02 20:05 UTC] bphelpsen at gmail dot com
Then why do I get different results when I run this code:

<?php echo "214748364800" / 1024 / 1024 / 1024; ?>

than when I run the example code.  Shouldn't they return the same value?

Here is an example, with the same results as my local test: 

http://codepad.org/KICl3xHw
 [2011-06-02 22:14 UTC] dtajchreber@php.net
This looks like a bug... SimpleXML's cast_object handler doesn't check for 
overflow when trying to convert a node value to a 
long. $xml->value goes through Zend's add_function and gets passed to 
zendi_convert_scalar_to_number which calls SimpleXML's 
cast_object handler because $xml->number is an object. It then gets chopped into 
LONG_MAX by strtol. An overflow check could 
fix this... but it might break some BC.... 

[1] http://lxr.php.net/xref/PHP_5_3/Zend/zend_operators.c#758
[2] http://lxr.php.net/xref/PHP_5_3/ext/simplexml/simplexml.c#1722
[3] http://lxr.php.net/xref/PHP_5_3/Zend/zend_operators.c#355
[4] http://lxr.php.net/xref/PHP_5_3/Zend/zend_operators.c#768
[5] http://www.gnu.org/s/hello/manual/libc/Parsing-of-Integers.html
 [2011-06-03 03:44 UTC] felipe@php.net
-Status: Bogus +Status: Analyzed
 [2011-06-03 11:55 UTC] cataphract@php.net
I remember seeing this before. The problem is that the Zend engine, when doing the add operation, converts any objects it finds to ints. The simplexml extension is merely doing what it's asked, i.e., convert the value of the object to int.

The solution must be either
a) making the Zend Engine default the conversion to a double
b) making the Zend Engine try both a double and an int and compare the two results
c) making the Zend Engine convert the object to a string instead and then convert the string using the usual means (that is, is_numeric_string)
d) change the API so that cast_object can be told to convert the object to either an int or a double, sort of like is_numeric_string
 [2013-07-22 08:33 UTC] kaplan@php.net
The referenced pull request (#213) has two tests to verify the fix for this bug 
(when and if ready). Please don't forget to use them when commiting the fix.
 [2013-11-06 14:42 UTC] corry at jhstudios dot com
$stdobj= new stdClass;
$stdobj->Price='.53';
echo 1+$stdobj->Price;

output:
object(stdClass)#1 (1) { ["Price"]=> string(3) ".53" } 
1.53

This shows that the standard class is correctly juggled from a string to a float when added to an integer. This is in contrast to other comments that suggested that the reported behavior is to be expected.
 [2016-09-19 13:23 UTC] cmb@php.net
> This shows that the standard class is correctly juggled from a
> string to a float when added to an integer.

Not really. Actually, the object isn't juggled at all, but rather
one of its properties.
 [2017-12-26 11:41 UTC] nikic@php.net
-Status: Analyzed +Status: Closed -Assigned To: +Assigned To: nikic
 
PHP Copyright © 2001-2018 The PHP Group
All rights reserved.
Last updated: Thu Dec 13 22:01:26 2018 UTC