Bug #66085 [Com]: in function serialize() there is irregular behaviour
| From: | aaron dot hamid at gmail dot com | Date: | Mon, 23 Dec 2013 07:43:38 +0000 |
| Subject: | Bug #66085 [Com]: in function serialize() there is irregular behaviour | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-183441@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
Comment by: aaron dot hamid at gmail dot com
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:
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.
Previous Comments:
------------------------------------------------------------------------
[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
------------------------------------------------------------------------
[2013-11-14 11:27:40] bwoebi@php.net
That actually is more complicated than I thought. If I fix that, the recursion prevention
doesn't work anymore in other edge cases.
Another developer might feel free to fix this.
------------------------------------------------------------------------
[2013-11-13 21:01:33] bwoebi@php.net
I see; thank you for the report, I'll investigate further tomorrow.
Seems the recursion prevention is buggy. Maybe it needs an extra stack for every serialize() call.
------------------------------------------------------------------------
[2013-11-13 20:43:19] machine dot check dot exception at gmail dot com
The bug is there. Check this: http://3v4l.org/DJg0j
It looks like it is a problem with memory allocation. Windows and linux allocate in different ways,
that's why probably windows "crashes" earlier than linux (in maybe any overflow?).
------------------------------------------------------------------------
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