#36424 [Com]: Serializable interface breaks object references

From: Date: Tue, 06 Jun 2006 21:04:33 +0000
Subject: #36424 [Com]: Serializable interface breaks object references
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-98100@lists.php.net to get a copy of this message
 ID:               36424
 Comment by:       hos dot endre at cafecsoport dot hu
 Reported By:      mastabog at hotmail dot com
 Status:           Assigned
 Bug Type:         SPL related
 Operating System: *
 PHP Version:      5.1.3RC2-dev
 Assigned To:      helly
 New Comment:

Yes its expected, but IMHO the problem need a featureful fix, not a
limitation.

Im not sure my problem is SPL related.

Here is my workaround:

The native serialize must start counting variables from 1. Outer
references may indexed negative, in case of nested call. Nested native
calls can only called in a native calls context in case of handling a
__serialize() or Serializable::serialize() call. The nested call can
reference as -1 to the topmost calls serialized root object. In case of
a negative reference is unresolvable on unserialization (multiplying by
-1 and querying the topmost pointer remapping), the value is not ready,
and a null value replaces temporarily.

What about a nested call already serialized a variable
that the topmost is willing to serialize? we have that pointer in the
map, but the reference no. might be greater
than the number of locally serialized variables.

If every call starts numbering variables from 1, then the topmost
serialize call also could reference on those hidden
variables by a negative index from the nesting wide accessible map -
not the calls local map. Backwards
if the unserialization process makes it possible, the negative
reference is also resolvable at the time the function processes it.

In case of wrong unserialization order, the negative reference's zval
is created with null, and the time the unserialization reaches that
index, da value's pointer is ready to be casted properly.

I think above mentioned way doesnt violates the syntax or the result of
serialization, this could work for a lot of cases, just like mine.

This way, the following code could produce this:

C:1:"A":93:{a:2:{s:4:"that";C:1:"A":43:{a:2:{s:4:"that";R:-1;s:9:"thatsThat";R:-2;}}s:9:"thatsThat";R:-1;}

class A implements Serializable
{
	public $dontSerialize;
	public $that;
	public $thatsThat;

	function __construct($that = null)
	{
		$this->that = ($that === null) ? new A($this) : $that;
		$this->thatsThat = &$this->that->that;
	}

	function serialize()
	{
		return serialize(array($this->that, $this->thatsThat));
	}

	function unserialize($serialized)
	{
		list($this->that, $this->thatsThat) = unserialize($serialized);
	}
}
echo serialize(new A());

Some more without any class relation, the following script serialises 3
arrays instead of 2 since we are passing a copy of $arr1, but the
_deprecated_ syntax serialize(&$arr1) still works fine.

Documentation says: "recent versions of PHP you will get a warning
saying that "Call-time pass-by-reference" is deprecated when you use a
& in foo(&$a);"

References' syntax are not consequent.

$arr2 = array();
$arr1['that'] = &$arr2;
$arr2['that'] = &$arr1;
$arr1['thatsThat'] = &$arr2['that'];
$arr2['thatsThat'] = &$arr1['that'];
echo serialize($arr1);

Produces:

a:2:{s:4:"that";a:2:{s:4:"that";a:2:{s:4:"that";R:2;s:9:"thatsThat";R:3;}s:9:"thatsThat";R:2;}s:9:"thatsThat";R:3;}

instead of

a:2:{s:4:"that";a:2:{s:4:"that";R:1;s:9:"thatsThat";R:2;}s:9:"thatsThat";R:1;}


Previous Comments:
------------------------------------------------------------------------

[2006-06-06 19:02:38] tony2001@php.net

Yeah, calling a function in an endless loop usually ends up with stack
overflow. It's expected and has nothing to do with this report.

------------------------------------------------------------------------

[2006-06-06 18:51:37] hos dot endre at cafecsoport dot hu

Crashing also reproducable.

Win2000Prof / PHP514

My related problem is that serializing a Serializable object, thats
some object property holds a reference to the serialized root object,
PHP crashes.

The magic function __serialize have too much sideFx for me - making the
object unworkable,
but I cant figure out how nested serialize function calls could work
properly.

Probably when the native serialize function is handles a nested call
then could hook up the root calls pointer map?

And then could this work for nested unserialization?

At this time I have no vision about the sideFx of this mention.

Right now I dont have a prepared C development environment to work out,
and dont remember how the related part of the code workx. As I remember
nested call test was implemented in the __autoload() function.

Since it can cause crashes please take more care on this bug.

Just uncomment 'implements Serializable' to let it crash.

class A // implements Serializable
{
	public $dontSerialize;
	public $that;

	function __construct($that = null)
	{
		$this->that = ($that === null) ? new A($this) : $that;
	}

	function serialize()
	{
		return serialize($this->that);
	}

	function unserialize($serialized)
	{
		$this->that = serialize($serialized);
	}
}

------------------------------------------------------------------------

[2006-04-11 11:43:11] sniper@php.net

Assigned to the SPL maintainer.

------------------------------------------------------------------------

[2006-03-18 10:30:38] nohn@php.net

To make this fail, it needs to be

    $this->assertEquals(true, $new_oC->A === $new_oC->B->A);


------------------------------------------------------------------------

[2006-03-18 10:29:16] nohn@php.net

When playing around with this bug, I discovered this:

While

    var_dump($new_oC->A === $new_oC->B->A);

Results into bool(false)

    $this->assertEquals($new_oC->A, $new_oC->B->A);

Does not fail!

------------------------------------------------------------------------

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
    http://bugs.php.net/36424

-- 
Edit this bug report at http://bugs.php.net/?id=36424&edit=1


Thread (25 messages)

« previous php.bugs (#98100) next »