php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #53033 Mathematical operations convert objects to integers
Submitted: 2010-10-10 00:45 UTC Modified: 2017-12-26 11:41 UTC
Votes:1
Avg. Score:3.0 ± 0.0
Reproduced:0 of 0 (0.0%)
From: rowan dot collins at gmail dot com Assigned: nikic (profile)
Status: Closed Package: Class/Object related
PHP Version: 5.3.3 OS: Any
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: rowan dot collins at gmail dot com
New email:
PHP Version: OS:

 

 [2010-10-10 00:45 UTC] rowan dot collins at gmail dot com
Description:
------------
When an object defined by an extension, such as SimpleXML, is used in a mathematical context, it is always converted to an int, never a float. This is inconsistent with the behaviour of other data types, which are automatically treated as a float if appropriate [e.g. the string "2.5" used in mathematical context is not truncated to int(2)].

This is impossible with user-defined classes, since no magic methods are available for governing cast to float or int, but binary object definitions can control this behaviour. This results in highly undesirable behaviour with SimpleXML objects, as reported in #42780

I have searched previous bug reports and the documentation, but cannot see any justification or documentation regarding this behaviour. In particular, there is no mention at http://php.net/manual/en/language.types.type-juggling.php or http://www.php.net/manual/en/language.types.object.php#language.types.object.casting and the tables at http://www.php.net/manual/en/types.comparisons.php do not cover implicit casts of this type.

Test script:
---------------
<?php

$x = simplexml_load_string('<x>2.5</x>');
var_dump($x*1); // int(2)
// type of other operand is irrelevant
var_dump($x*1.0); // float(2)

// strings behave differently
$y = '2.5';
var_dump($y*1); // float(2.5)
var_dump((string)$x*1); // float(2.5)

?>

Expected result:
----------------
All 4 examples should result in float(2.5)

Actual result:
--------------
As commented above. Unless the object is cast to string first, it is processed as an int, not a float, and the .5 is discarded.

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2010-10-11 06:37 UTC] cataphract@php.net
-Status: Open +Status: Verified
 [2010-10-11 06:37 UTC] cataphract@php.net
This is tricky because there's no way to tell an object to cast itself to a numeric type without asking explicitly for an int or a double and PHP prefers a double.

It would be possible to try first a double and, if failing, try an integer, but it's not straightforward because the current functions/macros throw notices if the conversion fails...
 [2010-10-11 06:39 UTC] cataphract@php.net
read: (...) and PHP prefers a int (not a double).

By the way, the work-around is to ask for a double conversion explicitly: 

<?php
$x = simplexml_load_string('<x>2.5</x>');
var_dump((double)$x*1); // float(2.5)
 [2017-02-26 05:00 UTC] qheaden at phaseshiftsoftware dot com
It looks like this issue affects all PHP versions according to the following output: https://3v4l.org/OqOJq

I am willing to check this bug out.
 [2017-02-26 11:25 UTC] nikic@php.net
If you want to work on this, here's some pointers on what needs to be done. The general issue is that cast_object handlers are currently limited to casting to integer or float, but not "cast to integer/float, whichever is more appropriate". To fix this, a new casting mode needs to be introduced. The procedure would be something like this:

* Add an _IS_NUMBER pseudo-type to zend_types.h
* In zend_operators.c, in convert_scalar_to_number() change the IS_OBJECT case to perform a cast to _IS_NUMBER (the general code for this is similar as in convert_to_long_base). Similar adjustments are necessary in zendi_convert_scalar_to_number().
* In sxe.c change the cast_object() function to handle the _IS_NUMBER cast (by calling convert_scalar_to_number()).
* Check the codebase for other cast_object handlers and see if they need to be adjusted to support casting to _IS_NUMBER.
 [2017-02-26 22:08 UTC] qheaden at phaseshiftsoftware dot com
Thanks for the info! It will be a big help.
 [2017-12-26 11:41 UTC] nikic@php.net
-Status: Verified +Status: Closed -Assigned To: +Assigned To: nikic
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Dec 03 17:01:29 2024 UTC