Bug->Doc #76098 [Opn]: Conversion from hex string to 64-bit int returns wrong value

From: Date: Thu, 15 Mar 2018 11:25:05 +0000
Subject: Bug->Doc #76098 [Opn]: Conversion from hex string to 64-bit int returns wrong value
References: 1  Groups: php.doc.bugs 
Request: Send a blank email to doc-bugs+get-15528@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=76098&edit=1 ID: 76098 Updated by: cmb@php.net Reported by: mikael dot knutsson at gmail dot com Summary: Conversion from hex string to 64-bit int returns wrong value Status: Open -Type: Bug +Type: Documentation Problem -Package: Variables related +Package: Math related Operating System: Linux 64-bit PHP Version: 7.2.3 Block user comment: N Private report: N New Comment: > […] which implies big-endianness in the packed value. That is to be expected. pack("H*", $strhex) returns "\xeb\x3d\xd7\x96\xef\xda\x24\x09", which is big-endian (the highest byte is to the left). > However, this happens on a 64-bit compiled PHP where this > integer should fit into the platform's integer size. No, it does not, since "PHP does not support unsigned integers"[1]. > when assigned to a variable as a hex string and converted using > intval() it loses precision. Hexadecimal number literals are regarded as non-negative numbers, but this number exceeds PHP_INT_MAX, so it is stored as float. Since the float value exceeds PHP_INT_MAX the result of the conversion to integer is actually undefined[2]. So yes, if you want to convert unsigned 64bit values represented as hexadecimal strings, you have to work-around the signed integer limitations. Your (un)pack() solution appears to be appropriate. Changing to doc-bug, since this info could be added to the hexdec() man page. [1] <http://www.php.net/manual/en/language.types.integer.php#language.types.integer.syntax> [2] <http://www.php.net/manual/en/language.types.integer.php#language.types.integer.casting.from-float> Previous Comments: ------------------------------------------------------------------------ [2018-03-15 08:47:15] mikael dot knutsson at gmail dot com Description: ------------ We have a hex string like this: "eb3dd796efda2409" received from an upstream system. This is a big-nibble hex string containing this integer value: -1495802457948019703 This is a 64-bit signed integer. When converting this using hexdec this is converted to a float and returns the wrong value, when assigned to a variable as a hex string and converted using intval() it loses precision. When looking at the documentation: http://php.net/manual/en/function.hexdec.php it mentions this: > The function can convert numbers that are too large to fit into the platforms integer type, > larger values are returned as float in that case. However, this happens on a 64-bit compiled PHP where this integer should fit into the platform's integer size. php --version PHP 7.2.3-1 (cli) (built: Mar 6 2018 11:15:04) ( NTS ) Copyright (c) 1997-2018 The PHP Group Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies with Zend OPcache v7.2.3-1, Copyright (c) 1999-2018, by Zend Technologies php -a Interactive mode enabled php > echo PHP_INT_MAX; 9223372036854775807 php > echo PHP_INT_SIZE; 8 As a side note: We ended up using pack/unpack to avoid the interim float conversion, and we also had to use "J" as the unpack conversion type to get the right value which implies big-endianness in the packed value. I am not sure this is correct either as doing this conversion in other languages works just fine without specifying endianness. (tried in Python and Go) (I can file a separate bug if this is also not intended) Test script: --------------- $strhex = "eb3dd796efda2409"; $hex = 0xeb3dd796efda2409; echo hexdec($strhex); echo $hex; echo intval($hex); var_dump(unpack('J', pack("H*", $strhex))); Expected result: ---------------- -1495802457948019703 -1495802457948019703 -1495802457948019703 array(1) { [1]=> int(-1495802457948019703) } Actual result: -------------- 1.6950941615762E+19 1.6950941615762E+19 -1495802457948020736 array(1) { [1]=> int(-1495802457948019703) } ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=76098&edit=1

« previous php.doc.bugs (#15528) next »