php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #46140 Unserializing with __wakeup that removes child causes subsequent refs to shift
Submitted: 2008-09-21 02:22 UTC Modified: 2015-05-24 18:06 UTC
Votes:5
Avg. Score:3.0 ± 1.1
Reproduced:5 of 5 (100.0%)
Same Version:5 (100.0%)
Same OS:1 (20.0%)
From: ehassler at synapsestudios dot com Assigned: cmb (profile)
Status: Closed Package: Class/Object related
PHP Version: 5.2.8 OS: *
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: ehassler at synapsestudios dot com
New email:
PHP Version: OS:

 

 [2008-09-21 02:22 UTC] ehassler at synapsestudios dot com
Description:
------------
During unserialization of a 3 deep non-recursive but not-a-tree data structure (more like a diamond) where, on nodes in level 2 a __wakeup causes all references to a child node of a certain class to be removed, when that child node would occur in subsequent level 2 nodes' child spots, the reference instead now points to the next level 2 node instead of any level 3 node.  More specifically, it points to the first level 2 node after the one that removed said child.

The sample code makes it more clear.

Reproduce code:
---------------
	class B {
		public $value;
		function __construct($value){ $this->value = $value; }
		
		function __wakeup()
		{
			if($this->value instanceof C)
					$this->value = C::$instance;
		}
	}
	
	class C { static public $instance; }
	
	C::$instance = new C;
	
	$A = array(  new B(C::$instance), new B(C::$instance), new B(C::$instance) );	

	var_dump($A);
	$A = unserialize(serialize($A));
	var_dump($A);

Expected result:
----------------
array
  0 => 
    object(B)[2]
      public 'value' => 
        object(C)[1]
  1 => 
    object(B)[3]
      public 'value' => 
        object(C)[1]
  2 => 
    object(B)[4]
      public 'value' => 
        object(C)[1]

array
  0 => 
    object(B)[5]
      public 'value' => 
        object(C)[1]
  1 => 
    object(B)[7]
      public 'value' => 
        object(C)[1]
  2 => 
    object(B)[8]
      public 'value' => 
        object(C)[1]


Actual result:
--------------
array
  0 => 
    object(B)[2]
      public 'value' => 
        object(C)[1]
  1 => 
    object(B)[3]
      public 'value' => 
        object(C)[1]
  2 => 
    object(B)[4]
      public 'value' => 
        object(C)[1]

array
  0 => 
    object(B)[5]
      public 'value' => 
        object(C)[1]
  1 => 
    object(B)[6]
      public 'value' => 
        &object(B)[6]
  2 => 
    object(B)[7]
      public 'value' => 
        object(B)[6]
          public 'value' => 
            &object(B)[6]


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2008-09-21 02:33 UTC] ehassler at synapsestudios dot com
After adding static $instance2 to class C, and changing the __wakeup to this:

function __wakeup()
{
	if($this->value instanceof C)
	{
		C::$instance2 = $this->value;
		$this->value = C::$instance;
	}
}

I get the expected behavior.  So, I guess, you know, hope that helps.
 [2008-10-29 00:18 UTC] ehassler at synapsestudios dot com
Very similar problem in PHP_VERSION === '5.2.7RC3-dev' under Windows. 
I ran my test script and got out:

array(3) {
  [0]=>
  object(B)#5 (1) {
    ["value"]=>
    object(C)#1 (0) {
    }
  }
  [1]=>
  object(B)#6 (1) {
    ["value"]=>
    object(B)#6 (1) {
      ["value"]=>
      *RECURSION*
    }
  }
  [2]=>
  object(B)#7 (1) {
    ["value"]=>
    object(B)#6 (1) {
      ["value"]=>
      object(B)#6 (1) {
        ["value"]=>
        *RECURSION*
      }
    }
  }
}
 [2014-06-02 20:49 UTC] cmbecker69 at gmx dot de
It seems this issue will be solved in PHP 5.7, see
<http://3v4l.org/jpqW8>.
 [2015-05-24 18:06 UTC] cmb@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: cmb
 [2015-05-24 18:06 UTC] cmb@php.net
Fixed as of PHP 5.4.39, 5.5.23 and 5.6.7.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Apr 26 23:01:29 2024 UTC