From: wharmby at uk dot ibm dot com Operating system: Windows XP PHP version: 5CVS-2007-05-16 (CVS) PHP Bug Type: Scripting Engine problem Bug description: PHP does not process hexadecimal strings in a consistent manner.
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 bug report at http://bugs.php.net/?id=41409&edit=1 -- Try a CVS snapshot (PHP 4.4): http://bugs.php.net/fix.php?id=41409&r=trysnapshot44 Try a CVS snapshot (PHP 5.2): http://bugs.php.net/fix.php?id=41409&r=trysnapshot52 Try a CVS snapshot (PHP 6.0): http://bugs.php.net/fix.php?id=41409&r=trysnapshot60 Fixed in CVS: http://bugs.php.net/fix.php?id=41409&r=fixedcvs Fixed in release: http://bugs.php.net/fix.php?id=41409&r=alreadyfixed Need backtrace: http://bugs.php.net/fix.php?id=41409&r=needtrace Need Reproduce Script: http://bugs.php.net/fix.php?id=41409&r=needscript Try newer version: http://bugs.php.net/fix.php?id=41409&r=oldversion Not developer issue: http://bugs.php.net/fix.php?id=41409&r=support Expected behavior: http://bugs.php.net/fix.php?id=41409&r=notwrong Not enough info: http://bugs.php.net/fix.php?id=41409&r=notenoughinfo Submitted twice: http://bugs.php.net/fix.php?id=41409&r=submittedtwice register_globals: http://bugs.php.net/fix.php?id=41409&r=globals PHP 3 support discontinued: http://bugs.php.net/fix.php?id=41409&r=php3 Daylight Savings: http://bugs.php.net/fix.php?id=41409&r=dst IIS Stability: http://bugs.php.net/fix.php?id=41409&r=isapi Install GNU Sed: http://bugs.php.net/fix.php?id=41409&r=gnused Floating point limitations: http://bugs.php.net/fix.php?id=41409&r=float No Zend Extensions: http://bugs.php.net/fix.php?id=41409&r=nozend MySQL Configuration Error: http://bugs.php.net/fix.php?id=41409&r=mysqlcfg