Req #41409 [Opn]: PHP does not process hexadecimal strings in a consistent manner.

From: Date: Thu, 01 May 2014 02:22:54 +0000
Subject: Req #41409 [Opn]: PHP does not process hexadecimal strings in a consistent manner.
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-185540@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=41409&edit=1

 ID:                 41409
 Updated by:         levim@php.net
 Reported by:        wharmby at uk dot ibm dot com
 Summary:            PHP does not process hexadecimal strings in a
                     consistent manner.
 Status:             Open
 Type:               Feature/Change Request
-Package:            Feature/Change Request
+Package:            *General Issues
-Operating System:   Windows XP
+Operating System:   Irrelevant
-PHP Version:        5CVS-2007-05-16 (CVS)
+PHP Version:        4.3.0
 Block user comment: N
 Private report:     N

 New Comment:

Using it as an int is different than casting it as an an int yields different results? Seems like a
bug to me unless there is some behavior rule I'm not thinking of.

I ran your reproduce code through http://3v4l.org/gZ1Z7 and it
gives consistent results from 4.3.0 to 5.6.0beta1.


Previous Comments:
------------------------------------------------------------------------
[2007-05-16 12:18:25] wharmby at uk dot ibm dot com

Description:
------------
PHP does not process hexadecimal strings in a consistent manner or
document when a hexadecimal string is evaluated as a numeric value and 
when it's not.

Whilst developing new PHPT testcase colleagues of mine have noticed
that PHP does not process hexadecimal strings in a consistent manner 
which makes it more difficult to determine what its expected and what 
is unexpected behaviour.

We have reviewed the documentation in the PHP manual on the subject at
http://www.php.net/manual/en/language.types.string.php
and there is no
explicit mention here of support for hexadecimal strings but it does
contain the reference

   "For more information on this conversion, see the Unix manual page for strtod(3). "

The MSDN description of strtod makes no reference to treatment of hexadecimal strings but the Linux
manual does. 

The following simple testcase demonstrates the inconsistency we are 
seeing and is based on a  testcase in a comment by "wilkinson98 at
hotmail dot com" on the manual back in 2005.

If we add to hexadecimal strings together the  strings are first 
converted to numbers by calling zendi_convert_scalar_to_number() which
calls  zend_bool is_numeric_string() to convert the strings which in 
turn calls the CRT function strtol() to do the conversion. In this 
case strtol() is called with a base of 10 or 16 dependent on whether 
or not the string starts with "0x" 

i.e the code in zend_bool is_numeric_string() reads:

    /* handle hex numbers */
    if (length>=2 && str[0]=='0' && (str[1]=='x' ||
str[1]=='X')) {
            conv_base=16;
    }
    errno=0;
    local_lval = strtol(str, &end_ptr_long, conv_base);

So hexadecimal strings are evaluated as numerical values and the 
addition produces the expected result. Or at least it does provided 
the string does not start with any white space, e.g "   0x123". Any white space causes a
string to evaluate to 0 which again is not what 
is suggested should happen from reading the description of strtod as suggested by the PHP manual; 
strtod description says white is ignored. So that needs clarifying too.

If we first cast the strings to "int" before adding them however, the
cast opcode handler calls convert_to_long()which calls convert_to_long_base() with a base of 10
which in turn calls strtol()
with base 10. As a result the hexadecimal strings both evaluate to 0 
and the result is 0.  The convert_to_long() function could easily be 
changed to employ similar logic to above to set the base dependent on 
the first 2 characters of the string but as convert_to_long() is called by a number of extension
functions to convert 
passed arguments, e.g range() this means that these functions will 
also have their behaviour changed too. Whilst this would be good form the point of view of
consistency it may break existing applications. 

PHP either needs to be changed to either consistently evaluate hexadecimal strings as numerical
values when appropriate (and I 
believe casting a string to an int is a case where an hexadecimal
string should be evaluated as numerical value) or document clearly 
when a hexadecimal string will be evaluated as a numeric value and 
when it's not. 

I am raising this defect to flag the issue and get feed back on whether the code or manual should be
fixed here. I would prefer to see
the code fixed but accept that doing so may break existing applications and so all that can be done
is to document the behaviour.
Either way I am happy to work with my colleagues developing the new PHPT testcases to determine
which code or manual pages need fixing.


Reproduce code:
---------------
<?php

$a = "0x32";
$b = "0x64";

echo $a + $b, "\n";
echo (int)$a + (int)$b, "\n";

?>

Expected result:
----------------
150
150

Actual result:
--------------
150
0


------------------------------------------------------------------------



-- 
Edit this bug report at https://bugs.php.net/bug.php?id=41409&edit=1


Thread (6 messages)

« previous php.bugs (#185540) next »