Bug #66085 [Ver]: in function serialize() there is irregular behaviour
| From: | nikic@php.net | Date: | Sun, 01 Jan 2017 11:51:30 +0000 |
| Subject: | Bug #66085 [Ver]: in function serialize() there is irregular behaviour | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-206271@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=66085&edit=1
ID: 66085
Updated by: nikic@php.net
Reported by: machine dot check dot exception at gmail dot com
Summary: in function serialize() there is irregular behaviour
Status: Verified
Type: Bug
Package: Arrays related
Operating System: Windows 7
PHP Version: 5.5.5
Block user comment: N
Private report: N
New Comment:
This bug has been fixed in PHP 7 by retaining all relevant zvals during serialization: https://github.com/php/php-src/blob/master/ext/standard/var.c#L629
Previous Comments:
------------------------------------------------------------------------
[2017-01-01 11:47:23] nikic@php.net
Related To: Bug #63163
------------------------------------------------------------------------
[2013-12-23 07:48:47] aaron dot hamid at gmail dot com
sorry i mis-pasted in my last comment, of course there should be 'global $keep_ref;' at
beginning of serialize().
------------------------------------------------------------------------
[2013-12-23 07:43:38] aaron dot hamid at gmail dot com
Yup, zval ids/addresses are getting reused. It looks like $tmp is getting collected after the test
serialize() method. If I *prevent* the collection by keeping a reference to the inner $tmp in a
global array, then I get the expected output:
$keep_ref = array();
class test implements Serializable {
public $a;
public function __construct( $_val ){
$this->a = $_val;
}
public function serialize() {
$tmp = (object) array();
$tmp->a = $this->a;
array_push($keep_ref, $tmp); // keep hold of a reference
echo serialize( $tmp ) . "\n";
return serialize( $tmp );
}
}
I tested with the 9 value array example here: http://3v4l.org/DJg0j
Can anybody confirm?
If zval id/address is used as the visited object key, and these are getting reused/replaced by
garbage collection while walking the object graph, then I'm not sure how we can implement
references across the entire object graph. Is there a way to temporarily disable collecting
reference-counted objects? I see there is gc_disable/gc_enable that appears to only affect
"circular" reference collector.
------------------------------------------------------------------------
[2013-12-23 07:00:39] aaron dot hamid at gmail dot com
I debugged this some and discovered that this line is producing object(stdClass)'s with the
same zval pointer and zend_objects_get_address address values (actually they alternate two previous
values) after the second entry:
$tmp = (object) array();
This causes the object to be detected as already encountered and the reference encoded. I
don't understand how or why this should be the case, are value structures getting reused, is
garbage collection occurring?
If I comment out the encountered lookup in php_var_serialize_intern then the desired output is
produced, although I assume that defeats the recursion prevention you are talking about bwoebi - is
there any other insight you can shed on this? Is my understanding correct?
------------------------------------------------------------------------
[2013-12-16 17:32:05] will at johnstonclan dot net
Another test case available here:
https://bugs.php.net/bug.php?id=66292
------------------------------------------------------------------------
The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
https://bugs.php.net/bug.php?id=66085
--
Edit this bug report at https://bugs.php.net/bug.php?id=66085&edit=1