Bug #74748 [Com]: HexDec outputs invalid conversions
| From: | danack@php.net | Date: | Mon, 12 Jun 2017 11:33:27 +0000 |
| Subject: | Bug #74748 [Com]: HexDec outputs invalid conversions | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-209502@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=74748&edit=1
ID: 74748
Comment by: danack@php.net
Reported by: sysop at pkx dot pw
Summary: HexDec outputs invalid conversions
Status: Not a bug
Type: Bug
Package: Math related
Operating System: LInux Mint 18
PHP Version: Irrelevant
Block user comment: N
Private report: N
New Comment:
> -9223372036854775808 is the same as the defined PHP_INT_MIN.
echo dechex(-9223372036854775808);
// 8000000000000000
which is the same as PHP_INT_MAX + 1. HexDec has no way of knowing which one you meant.
> I guess as a whole php only supports unsigned numbers.
No, in this very particular case PHP can't tell the difference.
> I have try'ed to use pack with the q syntax however it outputs a invalid hexadecimal
> number as a whole, so thats wrong too.
$packed = pack('J', -9223372036854775805);
echo bin2hex($packed) . "\n";
var_dump(unpack('Jfoo', $packed));
// Output is
8000000000000003
array(1) {
["foo"]=>
int(-9223372036854775805)
}
Please feel free to report a separate bug if you can make a reproduce case.
Previous Comments:
------------------------------------------------------------------------
[2017-06-12 10:10:32] sysop at pkx dot pw
This is clearly a bug, -9223372036854775808 is the same as the defined PHP_INT_MIN.
I need to keep the signedness of the variable, but I guess as a whole php only supports unsigned
numbers.
What I mean is your correct some weirdness goes on, as the defined value is output as a integer, but
the same value as a variable outputs a float, even through they're the same number.
I have try'ed to use pack with the q syntax however it outputs a invalid hexadecimal number as
a whole, so thats wrong too.
------------------------------------------------------------------------
[2017-06-12 09:35:31] danack@php.net
You are converting decimal to hex, which converts the number to the representation, but doesn't
save the signed information.
$hexed = dechex(-9223372036854775805);
var_dump($hexed);
var_dump(dechex(PHP_INT_MAX));
//Output is
string(16) "8000000000000003"
string(16) "7fffffffffffffff"
When PHP goes to convert back from this string, to a decimal, it interprets 0x80000000003 as an
unsigned number. As that number is bigger than PHP_INT_MAX, it overflows to a floating point number,
where weird things start happening, as not every int can be represented in a float above 2**53.
Perhaps you want to be using the pack and unpack functions:
http://php.net/manual/en/function.pack.php
http://php.net/manual/en/function.unpack.php
Which shouldn't make assumptions about the signedness of numbers.
------------------------------------------------------------------------
[2017-06-12 08:38:46] sysop at pkx dot pw
Description:
------------
---
From manual page: http://www.php.net/function.hexdec
---
Test script:
---------------
var_dump((int)hexdec(dechex(-9223372036854775805)));
var_dump((int)hexdec(dechex(-9223372036854775804)));
var_dump((int)hexdec(dechex(-9223372036854775803)));
Expected result:
----------------
int(-9223372036854775808)
int(-9223372036854775808)
int(-9223372036854775808)
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=74748&edit=1