php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #72177 Scope issue in __destruct after ReflectionProperty::setValue()
Submitted: 2016-05-09 13:28 UTC Modified: 2016-05-12 21:23 UTC
From: lbarnaud@php.net Assigned: dmitry (profile)
Status: Closed Package: Reflection related
PHP Version: 7.0Git-2016-05-09 (Git) OS:
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: lbarnaud@php.net
New email:
PHP Version: OS:

 

 [2016-05-09 13:28 UTC] lbarnaud@php.net
Description:
------------
When __destruct() is called, following a ReflectionProperty::setValue() call, scopes seem to be wrong.

In the following reproducing script, the method `Child::__destruct()` fails to set `$this->bar to null`, with the error `Cannot access protected property Child::$bar`.

I can reproduce this in git master, but not in any version from 3v4l.org.

Test script:
---------------
<?php

class Child
{
    protected $bar;

    public function __destruct()
    {
        $this->bar = null;
    }
}

class Parnt
{
    protected $child;

    public function doSomething()
    {
        $this->child = new Child();

        $prop = new \ReflectionProperty($this, 'child');
        $prop->setAccessible(true);
        $prop->setValue($this, null);
    }
}

$p = new Parnt();
$p->doSomething();

echo "OK\n";

Expected result:
----------------
OK

Actual result:
--------------
Fatal error: Uncaught Error: Cannot access protected property Child::$bar in /tmp/x.php:9
Stack trace:
#0 [internal function]: Child->__destruct()
#1 /tmp/x.php(23): ReflectionProperty->setValue(Object(Parnt), NULL)
#2 /tmp/x.php(28): Parnt->doSomething()
#3 {main}
  thrown in /tmp/x.php on line 9

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-05-12 15:48 UTC] nikic@php.net
-Status: Open +Status: Assigned -Assigned To: +Assigned To: dmitry
 [2016-05-12 15:48 UTC] nikic@php.net
Fallout from the EG(scope) removal. Now EG(fake_scope) will continue shadowing the scope, even though we might reenter a differently scoped method.

This looks a bit tricky... maybe we should just avoid the fake scoping altogether and add an extra scope argument to the property handlers?
 [2016-05-12 21:43 UTC] ocramius at gmail dot com
Related: I got similar failures when accessing object state via `__get`, when `__get` is triggered by reflection, as the scope with which `__get` is called is wrong.
Specifically, something like following:

=====foo.php======
<?php

class Foo
{
    private $bar = 'bar';

    public function __construct()
    {
        unset($this->bar);
    }
}

class Bar extends Foo
{
    private $baz = 'baz';
    private static $tab = 'tab';

    public function __get(string $name)
    {
        var_dump($this->baz);
        var_dump(self::$tab);
        return $name;
    }
}

$r = new ReflectionProperty(Foo::class, 'bar');

$r->setAccessible(true);

var_dump($r->getValue(new Bar));
=====/foo.php======

This will work in 7.0.0~7.0.7 (see https://3v4l.org/dQlsf), but will crash on master (7.1.0-DEV), with something like following:

=====OUTPUT======
NULL

Fatal error: Uncaught Error: Cannot access private property Bar::$tab in foo.php:21
Stack trace:
#0 foo.php(20): Bar->__get('baz')
#1 [internal function]: Bar->__get('bar')
#2 foo.php(30): ReflectionProperty->getValue(Object(Bar))
#3 {main}
  thrown in /Users/ocramius/Documents/Projects/ProxyManager/foo.php on line 21
=====/OUTPUT======
 [2016-05-13 08:55 UTC] dmitry@php.net
Automatic comment on behalf of dmitry@zend.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=e9c3f9fcde1013cc1c9bdead7e16478a108d7907
Log: Fixed bug #72177 (Scope issue in __destruct after ReflectionProperty::setValue())
 [2016-05-13 08:55 UTC] dmitry@php.net
-Status: Assigned +Status: Closed
 [2016-07-20 11:31 UTC] davey@php.net
Automatic comment on behalf of dmitry@zend.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=e9c3f9fcde1013cc1c9bdead7e16478a108d7907
Log: Fixed bug #72177 (Scope issue in __destruct after ReflectionProperty::setValue())
 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Fri Jul 04 15:01:36 2025 UTC