# serialize bug with array that references to itself?

- Thread: https://externals.io/message/13705
- Original archive: https://news-web.php.net/php.internals/13705
- Started by Francisco M. Marzoa Alonso on 2004-11-03T13:36:08+00:00
- Messages: 13
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #13706 — Andrey Hristov — 2004-11-03T13:31:53+00:00

URL: https://externals.io/message/13705#13706 · In reply to: #13705

Francisco M. Marzoa Alonso wrote:
> Try this code:
> 
> <pre>
> <?php
> 
> $Arr = array();
> $Arr['self'] = &$Arr;
> var_dump ( $Arr );
> 
> $serdata = serialize ($Arr);
> $Arr2 = unserialize ( $serdata );
> echo "\n\n";
> var_dump ( $Arr2 );
> 
> ?>
> </pre>
> 
> The second array is expected to be exactly as $Arr, but it doesn't. This 
> is the output for that code:
> 
> array(1) {
>  ["self"]=>
>  array(1) {
>    ["self"]=>
>    *RECURSION*
>  }
> }
> 
> array(1) {
>  ["self"]=>
>  array(1) {
>    ["self"]=>
>    `NULL` 
>  }
> }
> 
> As you can see the second array has a `NULL` value where the first one had 
> a recursive reference.
> 
> Can this be considered as a bug of PHP serialization system?
> 

Looks as such.
While looking at this one, I cooked a little example which cores ZE2 (5.1.0-dev)

<?php
class a{}
class b{}

$a=new a;
$b=new b;
$a->a=$b;
$c=array($a,$b);
var_dump($c,$d=serialize($c));
var_dump($e=unserialize($d));
$d[0]->a->prop=1;
var_dump($d);
?>

If one looks at it she will see that I have an error in the example and instead
of $d[0]->a I have to use $e[0] , still a Segmentation Fault is not tolerable.

This works ok :
<?php
class a{}
class b{}

$a=new a;
$b=new b;
$a->a=$b;
$c=array($a,$b);
var_dump($c, $d=serialize($c));
var_dump($e=unserialize($d));
$d[0]->a->prop=1;
var_dump($d);
?>

$e is :
array(2) {
   [0]=>
   object(a)#3 (1) {
     ["a"]=>
     object(b)#4 (1) {
       ["prop"]=>
       int(1)
     }
   }
   [1]=>
   object(b)#4 (1) {
     ["prop"]=>
     int(1)
   }
}

Andrey

---

## #13705 — Francisco M. Marzoa Alonso — 2004-11-03T13:36:08+00:00

URL: https://externals.io/message/13705#13705

Try this code:

<pre>
<?php

$Arr = array();
$Arr['self'] = &$Arr;
var_dump ( $Arr );

$serdata = serialize ($Arr);
$Arr2 = unserialize ( $serdata );
echo "\n\n";
var_dump ( $Arr2 );

?>
</pre>

The second array is expected to be exactly as $Arr, but it doesn't. This 
is the output for that code:

array(1) {
  ["self"]=>
  array(1) {
    ["self"]=>
    *RECURSION*
  }
}

array(1) {
  ["self"]=>
  array(1) {
    ["self"]=>
    `NULL` 
  }
}

As you can see the second array has a `NULL` value where the first one had 
a recursive reference.

Can this be considered as a bug of PHP serialization system?

---

## #13709 — Andrey Hristov — 2004-11-03T15:10:04+00:00

URL: https://externals.io/message/13705#13709 · In reply to: #13708

Feel free to file a bug report at http://bugs.php.net .Mention
in the subject there there is core dump.

Thanks,
Andrey

Francisco M. Marzoa Alonso wrote:
> Should I fill a bug notification report or so? (where are them? ;-))
> 
> Andrey Hristov wrote:
> 
> > […]

---

## #13708 — Francisco M. Marzoa Alonso — 2004-11-03T16:03:11+00:00

URL: https://externals.io/message/13705#13708 · In reply to: #13706

Should I fill a bug notification report or so? (where are them? ;-))

Andrey Hristov wrote:

> Francisco M. Marzoa Alonso wrote:
>
> > […]
>
> Looks as such.
> While looking at this one, I cooked a little example which cores ZE2 
> (5.1.0-dev)
>
> <?php
> class a{}
> class b{}
>
> $a=new a;
> $b=new b;
> $a->a=$b;
> $c=array($a,$b);
> var_dump($c,$d=serialize($c));
> var_dump($e=unserialize($d));
> $d[0]->a->prop=1;
> var_dump($d);
> ?>
>
> If one looks at it she will see that I have an error in the example 
> and instead
> of $d[0]->a I have to use $e[0] , still a Segmentation Fault is not 
> tolerable.
>
> This works ok :
> <?php
> class a{}
> class b{}
>
> $a=new a;
> $b=new b;
> $a->a=$b;
> $c=array($a,$b);
> var_dump($c, $d=serialize($c));
> var_dump($e=unserialize($d));
> $d[0]->a->prop=1;
> var_dump($d);
> ?>
>
> $e is :
> array(2) {
>   [0]=>
>   object(a)#3 (1) {
>     ["a"]=>
>     object(b)#4 (1) {
>       ["prop"]=>
>       int(1)
>     }
>   }
>   [1]=>
>   object(b)#4 (1) {
>     ["prop"]=>
>     int(1)
>   }
> }
>
> Andrey

---

## #13711 — Andrey Hristov — 2004-11-03T16:03:53+00:00

URL: https://externals.io/message/13705#13711 · In reply to: #13710

Well, when there is traversion inside the engine, it checks whether it has
processed a "node" already several times. As far as I remember the threshold
is 3. So once it goes over $Arr, the counter increases to 1, the second time
to 2 and third time it is 3 and ZE reports recursion.

HTH,
Andrey

Francisco M. Marzoa Alonso wrote:
> BTW., I'm not sure that there's nothing more wrong here. Takin the first 
> part of the code of first example:
> 
> <?php
> 
> $Arr = array();
> $Arr['self'] = &$Arr;
> var_dump ( $Arr );
> 
> ?>
> 
> It returns:
> 
> array(1) {
> ["self"]=>
> array(1) {
>   ["self"]=>
>   *RECURSION*
> }
> }
> 
> Is that as its expected to be? I meant that perhaps it should be:
> 
> array(1) {
>   ["self"]=>
>   *RECURSION*
> }
> 
> Since the element in $Arr['self'] is yet (or at least should be) a 
> reference to itself...

---

## #13712 — Jochem Maas — 2004-11-03T16:37:35+00:00

URL: https://externals.io/message/13705#13712 · In reply to: #13711

Andrey Hristov wrote:
>  Well, when there is traversion inside the engine, it checks whether it has
> processed a "node" already several times. As far as I remember the 
> threshold
> is 3. So once it goes over $Arr, the counter increases to 1, the second 
> time
> to 2 and third time it is 3 and ZE reports recursion.

is there good reason to set the threshold at 3 iso 2?

when dumping out objects that make heavy use of 'parent' references this 
leads to tons of extra output which would be greatly cutdown if the 
threshold was 2 iso 3.

just to make the point, print_r seems to use a threshold of 2 (which is 
why I always try print_r before taking my chances with var_dump):

<?php

class a { public $self; }

$A = new a;
$A->self = $A;
var_dump( $A );
print_r( $A );

?>

> 
> HTH,
> Andrey
> 
> Francisco M. Marzoa Alonso wrote:
> 
> > […]

---

## #13710 — Francisco M. Marzoa Alonso — 2004-11-03T16:45:53+00:00

URL: https://externals.io/message/13705#13710 · In reply to: #13709

BTW., I'm not sure that there's nothing more wrong here. Takin the first 
part of the code of first example:

<?php

$Arr = array();
$Arr['self'] = &$Arr;
var_dump ( $Arr );

?>

It returns:

array(1) {
 ["self"]=>
 array(1) {
   ["self"]=>
   *RECURSION*
 }
}

Is that as its expected to be? I meant that perhaps it should be:

array(1) {
   ["self"]=>
   *RECURSION*
}

Since the element in $Arr['self'] is yet (or at least should be) a 
reference to itself...

---

## #13714 — Moriyoshi Koizumi — 2004-11-03T17:22:23+00:00

URL: https://externals.io/message/13705#13714 · In reply to: #13706

> $c=array($a,$b);
> var_dump($c,$d=serialize($c));
> var_dump($e=unserialize($d));
> $d[0]->a->prop=1;
> var_dump($d);
> ?>

Did you mean "$e[0]->a->prop" by "$d[0]->a->prop"?

That looks like another issue:

<?php
// This causes bus error.
$a = 'abc';
$a{0}->a->prop = 1;
?>

Moriyoshi

---

## #13715 — Andrey Hristov — 2004-11-03T17:25:45+00:00

URL: https://externals.io/message/13705#13715 · In reply to: #13712

Hi,
 `print_r()` and `var_dump()` are quite different in their nature.
 `print_r()` is a thin wrapper around an internal Zend function
(as far as I remember) while `var_dump()` is in ext/standard/var.c
The do more or less the same job still some differences in the
output (print_r() shows nothing on `NULL` variables which I find
clumsy since lack of output where I expect ouput makes me
suspicious).

Andrey

Jochem Maas wrote:
> Andrey Hristov wrote:
> 
> > […]
> 
> 
> is there good reason to set the threshold at 3 iso 2?
> 
> when dumping out objects that make heavy use of 'parent' references this 
> leads to tons of extra output which would be greatly cutdown if the 
> threshold was 2 iso 3.
> 
> just to make the point, print_r seems to use a threshold of 2 (which is 
> why I always try print_r before taking my chances with var_dump):
> 
> <?php
> 
> class a { public $self; }
> 
> $A = new a;
> $A->self = $A;
> var_dump( $A );
> print_r( $A );
> 
> ?>
> 
> > […]

---

## #13716 — Andrey Hristov — 2004-11-03T17:26:59+00:00

URL: https://externals.io/message/13705#13716 · In reply to: #13714

Moriyoshi Koizumi wrote:
> 
> 
> 
> > […]
> 
> 
> Did you mean "$e[0]->a->prop" by "$d[0]->a->prop"?

Well, when I was writing the test I made a mistake which
I saw later but my mistake lead to a PHP core dump.

> 
> That looks like another issue:
> 
> <?php
> // This causes bus error.
> $a = 'abc';
> $a{0}->a->prop = 1;
> ?>
> 
> Moriyoshi
> 

Andrey

---

## #13713 — Francisco M. Marzoa Alonso — 2004-11-03T17:43:11+00:00

URL: https://externals.io/message/13705#13713 · In reply to: #13711

I think I understand the reason because I obtain that output, but I 
cannot figure out the motivations for doing it in that way. I should 
probably take a look at ZE sources.

Thx. a lot by your help.

Andrey Hristov wrote:

>  Well, when there is traversion inside the engine, it checks whether 
> it has
> processed a "node" already several times. As far as I remember the 
> threshold
> is 3. So once it goes over $Arr, the counter increases to 1, the 
> second time
> to 2 and third time it is 3 and ZE reports recursion.
>
> HTH,
> Andrey

---

## #13718 — Moriyoshi Koizumi — 2004-11-03T18:29:35+00:00

URL: https://externals.io/message/13705#13718 · In reply to: #13716

> > […]
> 
> Well, when I was writing the test I made a mistake which
> I saw later but my mistake lead to a PHP core dump.

Looks more like I should've read the mail more carefully :)

Moriyoshi

---

## #13719 — Jochem Maas — 2004-11-03T18:35:14+00:00

URL: https://externals.io/message/13705#13719 · In reply to: #13715

Hi Andrey,

I have to confess my understanding of the engine internals is next to 
zero, but I do understand that var_dump and print_r were created 
with/for different pretexts.

I agree with you that printing nothing for `NULL` is doesn't feel right 
(btw boolean false has the same effect) - this can be problematic when 
you don't know that this is the case (indeed much time have I lost on 
this issue when I first started out), this is a minor gripe and easily 
sidestepped with a var_dump :-)

my question was more out of curiosity (although I would like to see the 
threshold for var_dump dropped to 2 if that is technically 
feasible/acceptable) - there may be a good reason for the difference in 
thresholds, it may be a an oversight/inconsistency. either way my motive 
is to better understand the reasoning behind the way things work in PHP 
- better understanding how/why a developer made it work a certain has in 
the past really helped me improve my code.

thanking everyone who has made (and continues to make) PHP what it is - 
it rocks alot more than it doesn't ;-).

Andrey Hristov wrote:
>  Hi,
> `print_r()` and `var_dump()` are quite different in their nature.
> `print_r()` is a thin wrapper around an internal Zend function
> (as far as I remember) while `var_dump()` is in ext/standard/var.c
> The do more or less the same job still some differences in the
> output (print_r() shows nothing on `NULL` variables which I find
> clumsy since lack of output where I expect ouput makes me
> suspicious).
> 
> Andrey
> 
> Jochem Maas wrote:
> 
> > […]
