Bug #72100 [Opn->Asn]: implode() inserts garbage into resulting string when joins very big integer
| From: | pajoye@php.net | Date: | Tue, 26 Apr 2016 07:30:48 +0000 |
| Subject: | Bug #72100 [Opn->Asn]: implode() inserts garbage into resulting string when joins very big integer | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-200781@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=72100&edit=1
ID: 72100
Updated by: pajoye@php.net
Reported by: mikhail dot galanin at yahoo dot com
Summary: implode() inserts garbage into resulting string when
joins very big integer
-Status: Open
+Status: Assigned
Type: Bug
Package: Scripting Engine problem
Operating System: SLES x86_64
PHP Version: 7.0.5
-Assigned To:
+Assigned To: ab
Block user comment: N
Private report: N
New Comment:
err It is big number related. I was checking two times the same script.
Assigning to Anatol, he knows that area well :)
Previous Comments:
------------------------------------------------------------------------
[2016-04-26 07:26:51] pajoye@php.net
It seems to be unrelated to big numbers.
shorter script:
$a1 = ['INSERT IGNORE INTO', 'Table', 999999999999999999, PHP_INT_MIN,
PHP_INT_MAX];
$a2 = ['INSERT IGNORE INTO', 'Table', 1, 2, 3];
$str1 = implode(' ', $a1);
$str2 = implode(' ', $a1);
var_dump($str1, $str2);
It keeps the ending \0 for the 1st string,
"INSERT IGNORE INTO<bh:00> Ta" (little literal hexdump).
------------------------------------------------------------------------
[2016-04-25 09:13:25] mikhail dot galanin at yahoo dot com
Here is .phpt for the issue:
--TEST--
Test implode() function, problems with big numbers
--SKIPIF--
<?php
if (PHP_INT_SIZE != 8) die("skip this test is for 64bit platform only");
?>
--FILE--
<?php
/* Prototype : string vsprintf(string $format , array $args)
* Description: Return a formatted string
* Source code: ext/standard/formatted_print.c
*/
/* very long number */
var_dump( implode(" ", ["hello long", 999999999999999999, PHP_INT_MAX] ) );
var_dump( implode(" ", ["hello negative long", -999999999999999999, PHP_INT_MIN]
) );
var_dump( implode(" ", ["hello small long", -101, -100, -99, -90, -11, -10, -9,
-1, 0, 1, 2, 9, 10, 11, 90, 99, 100, 101] ) );
echo "Done\n";
?>
--EXPECTF--
string(49) "hello long 999999999999999999 9223372036854775807"
string(60) "hello negative long -999999999999999999 -9223372036854775808"
string(76) "hello small long -101 -100 -99 -90 -11 -10 -9 -1 0 1 2 9 10 11 90 99 100 101"
Done
------------------------------------------------------------------------
[2016-04-25 09:09:06] mikhail dot galanin at yahoo dot com
Description:
------------
In the implode() implementation, there's an optimisation that operates when input array
contains long's. This optimisation relays on the fact that log10(num) returns digit number of
string representation of "num". Even though mathematically it is correct there an issue
when num consist of more than 14 nines (i.e. 99999999999999999). In this case the log10 is rounded
up and actual result gets wrong.
Test script:
---------------
$a = [
'INSERT IGNORE INTO ',
'Table',
(999999999999999999),
PHP_INT_MIN,
PHP_INT_MAX
];
$str = implode(' ', $a);
echo json_encode(["str" => $str]);
Expected result:
----------------
{"str":"INSERT IGNORE INTO Table 999999999999999999 -9223372036854775808
9223372036854775807"}
Actual result:
--------------
{"str":"INSERT IGNORE INTO \u0000 Table 999999999999999999 -9223372036854775808
9223372036854775807"}
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=72100&edit=1