php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #65903 Reference type property unexpectedly converted to value type property
Submitted: 2013-10-15 19:09 UTC Modified: 2018-03-16 23:04 UTC
Votes:3
Avg. Score:4.3 ± 0.9
Reproduced:3 of 3 (100.0%)
Same Version:1 (33.3%)
Same OS:2 (66.7%)
From: veg at tut dot by Assigned:
Status: Open Package: Scripting Engine problem
PHP Version: 5.5.4 OS: Windows 7 Pro SP1 x86
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: veg at tut dot by
New email:
PHP Version: OS:

 

 [2013-10-15 19:09 UTC] veg at tut dot by
Description:
------------
I've used a little code snippet to convert property from value type to reference type. It's described here: http://www.php.net/manual/en/language.oop5.cloning.php
It's very useful practice when you want to share some properties between all clones. But it works with some bugs. When you try to read a reference type property of object without clones, this property unexpectedly converted to value type property.

Test script:
---------------
<?php
header('content-type: text/plain; charset=utf-8');

class demo
{
    public $n = 0;
    function __construct() { $this->n =& $this->n; }
    function magic()       { if ($this->n) return; }
    function set($n)       { $this->n = $n; }
}

// Outputs 1 = 1 as expected
$a1 = new demo();
$b1 = clone $a1;
$a1->magic();
$b1->set(1);
echo "{$a1->n} = {$b1->n}\n";

// Outputs 0 = 1 (magic() method is called a little earlier)
$a2 = new demo();
$a2->magic();
$b2 = clone $a2;
$b2->set(1);
echo "{$a2->n} = {$b2->n}\n";

Expected result:
----------------
1 = 1
1 = 1

Actual result:
--------------
1 = 1
0 = 1

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2013-10-15 22:07 UTC] bwoebi@php.net
Some simpler reproduce case (also reproducible with arrays etc.):

root# php -r '$z = (object)["p" => 1]; $z->p = &$z->p; var_dump($z);'
object(stdClass)#1 {
  ["p"]=>
  &long(1) // << here is an &
}
root# php -r '$z = (object)["p" => 1]; $z->p = &$z->p; $z->p; var_dump($z);'
object(stdClass)#1 {
  ["p"]=>
  long(1) // << note that there's no &
}

So it seems that a reference to itself on object properties is removed upon direct read access.

(The problem is that when referencing a variable to itself the refcount isn't incremented and when a temporary variable is being destroyed the refcount is decremented and now equal to 1; so the reference is thought to be unset and then removed. Note that this only is the case for IS_TMP_VAR (IS_CV and IS_VAR are immune against that).)
 [2018-03-16 23:04 UTC] cmb@php.net
JFTR: the behavior has been changed as of PHP 7.0.0, see
<https://3v4l.org/VTJMI> and <https://3v4l.org/oi75J>.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Oct 31 22:01:27 2024 UTC