Bug #70275 [Opn->Asn]: On recursion error, json_encode can eat up all system memory
| From: | bukka@php.net | Date: | Mon, 09 Nov 2015 19:28:30 +0000 |
| Subject: | Bug #70275 [Opn->Asn]: On recursion error, json_encode can eat up all system memory | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-197137@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=70275&edit=1
ID: 70275
Updated by: bukka@php.net
Reported by: royanee at gmail dot com
Summary: On recursion error, json_encode can eat up all
system memory
-Status: Open
+Status: Assigned
Type: Bug
Package: JSON related
PHP Version: 5.6.12
-Assigned To:
+Assigned To: bukka
Block user comment: N
Private report: N
Previous Comments:
------------------------------------------------------------------------
[2015-08-14 23:14:23] royanee at gmail dot com
Description:
------------
When json_encode encounters recursion or other errors it will return false (as long as you are not
using the largely undocumented constant JSON_PARTIAL_OUTPUT_ON_ERROR).
Unfortunately, it waits until after it has processed all of the data to return the error. This was a
problem for me when I was attempting to export an application state in JSON. As I was using the CLI,
it ate up all of the system memory and at best it would have returned false if I could have waited
an eternity for it to finish.
I've included a test script with a nice handful of circular object references.
Test script:
---------------
$max_num_objects = 20;
for ($num_objects = 5; $num_objects <= $max_num_objects; $num_objects++) {
echo PHP_EOL . 'Number of Objects: ' . $num_objects . PHP_EOL;
// Create the objects and link them to each other.
$objects = new stdClass;
for ($i = 0; $i < $num_objects; $i++) {
$objects->$i = new stdClass;
}
for ($i = 0; $i < $num_objects; $i++) {
for ($j = 0; $j < $num_objects; $j++) {
if ($i != $j) {
$objects->$i->$j = $objects->$j;
}
}
}
$starttime = microtime(true);
serialize($objects);
echo '$objects serialize: ' . number_format(microtime(true) - $starttime, 3) .
' seconds' . PHP_EOL;
$starttime = microtime(true);
if (json_encode($objects) === FALSE) {
echo 'JSON Error #' . json_last_error() . ': ' .
json_last_error_msg() . PHP_EOL;
}
echo '$objects json_encode: ' . number_format(microtime(true) - $starttime, 3) .
' seconds' . PHP_EOL;
}
Expected result:
----------------
Finishes in less than a second, ideally in a negligible amount of time. Example:
...
Number of Objects: 10
$objects serialize: 0.000 seconds
JSON Error #6: Recursion detected
$objects json_encode: 0.000 seconds
Actual result:
--------------
...
Number of Objects: 10
$objects serialize: 0.000 seconds
JSON Error #6: Recursion detected
$objects json_encode: 7.227 seconds
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=70275&edit=1