serialize bug with array that references to itself?

php.internals

Francisco M. Marzoa Alonso

21 years ago
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?

Andrey Hristov

21 years ago
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

Francisco M. Marzoa Alonso

21 years ago
Should I fill a bug notification report or so? (where are them? ;-)) Andrey Hristov wrote:

Andrey Hristov

21 years ago
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:

Francisco M. Marzoa Alonso

21 years ago
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...

Andrey Hristov

21 years ago
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:

Jochem Maas

21 years ago
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 ); ?>

Andrey Hristov

21 years ago
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:

Jochem Maas

21 years ago
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:

Francisco M. Marzoa Alonso

21 years ago
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:

Moriyoshi Koizumi

21 years ago
On 2004/11/03, at 22:31, Andrey Hristov wrote:
> $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

Andrey Hristov

21 years ago
Moriyoshi Koizumi wrote:
> > On 2004/11/03, at 22:31, Andrey Hristov wrote: > >> $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"?
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

Moriyoshi Koizumi

21 years ago
> > 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.
Looks more like I should've read the mail more carefully :) Moriyoshi