php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #65160 $this can be changed using reference
Submitted: 2013-06-28 14:45 UTC Modified: 2013-06-29 14:13 UTC
Votes:1
Avg. Score:3.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:0 (0.0%)
Same OS:0 (0.0%)
From: m dot adeelnawaz at ymail dot com Assigned:
Status: Not a bug Package: Class/Object related
PHP Version: 5.5.0 OS: Windows 7 / Linux
Private report: No CVE-ID: None
 [2013-06-28 14:45 UTC] m dot adeelnawaz at ymail dot com
Description:
------------
In an object method, $this must always be a reference to the caller object.
Now $this can not be re-assigned but re-assigning is not the only way to modify $this. The code below demonstrates another way to set $this to something other than the caller object.

This is what happens. $this is a reference (or copy of the identifier) to the caller object. After doing this
	$a = &$this;
$a and $this are both pointing to the same reference to the object identifier. So changing one of them (assigning them to something not by reference) will change the reference for both of them.
After executing this line
	$a = new a();
Both $a and $this start pointing to the reference of the identifier to the newly created object. You can change $this's reference by setting $a (not by reference) to any non-null variable or value.

Test script:
---------------
class a{}
class b{
	function test(){
		$a = &$this;
		
		echo get_class($this).'<br/>';
		echo get_class($a).'<br/>';
		
		$a = new a();
		
		echo get_class($this).'<br/>';
		echo get_class($a).'<br/>';
	}
}

$b = new b();
$b->test();

Expected result:
----------------
One of the following should happen when I run the code above.

1. The code should produce a fatal error on line 3 ($a = &$this;) saying that referencing to $this is not allowed.

2. The code should allow me to create a reference to $this in $a but assigning any non-null value to $a (not by reference) should produce a fatal error saying that $a is a reference to $this so it should (first) be assigned by reference to some variable / object other than current object.

3. The code should allow me to create a reference to $this in $a but then the same rules should apply to $a as $this with one exception that $a can be unset().

Actual result:
--------------
b
b
b
a

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2013-06-28 14:59 UTC] m dot adeelnawaz at ymail dot com
Actual result:
--------------
b
b
a
a
 [2013-06-28 16:47 UTC] ab@php.net
looks like a real mess, namely here's a modified snippet

<?php

class a{}
class b{
        function test(){
                $a = &$this;

                echo get_class($this).PHP_EOL;
                echo get_class($a).PHP_EOL;

                $a = new a();

                echo get_class($this).PHP_EOL;
                echo get_class($a).PHP_EOL;
        }

        function test2()
        {
                echo get_class($this).PHP_EOL;
        }
        function test3()
        {
                $a = &$this;

                $a = new a;

                echo get_class($this).PHP_EOL;
                echo get_class($a).PHP_EOL;

                $this->test();
        }
}

$b = new b();
$b->test();
$b->test2();
$b->test3();

$a = new a;
$a->test();

especially b:test3() - it reports both $a and $this having class 'a', but $this-
>test() works after that. Whereby (new a)->test() will die on undefined method.
 [2013-06-29 11:45 UTC] ab@php.net
On the other hand, overriding of $this is only possible on the stack, therefore 
calling ->test2() will have it back.
 [2013-06-29 14:13 UTC] johannes@php.net
-Status: Open +Status: Not a bug
 [2013-06-29 14:13 UTC] johannes@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php

We don't prevent people from purposely shooting in their own feet. The checks we do are there during parsing stage in order to prevent obvious mistakes and to warn people coming from PHP 4 (where reassigning $this was the only way in a constructor to report errors)

We don't check further at runtime and won't do this as the only way would e to check _every_ variable operation, which are costs in no relation to the benefit.
 
PHP Copyright © 2001-2020 The PHP Group
All rights reserved.
Last updated: Thu Oct 01 05:01:24 2020 UTC