php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #68194 Closure captures late bound class too eagerly
Submitted: 2014-10-09 06:54 UTC Modified: 2015-05-20 16:33 UTC
Votes:6
Avg. Score:4.5 ± 0.8
Reproduced:6 of 6 (100.0%)
Same Version:5 (83.3%)
Same OS:4 (66.7%)
From: denis at slik dot eu Assigned: levim (profile)
Status: Closed Package: Scripting Engine problem
PHP Version: 5.6.1 OS: Irrelevant
Private report: No CVE-ID: None
 [2014-10-09 06:54 UTC] denis at slik dot eu
Description:
------------
In #66622, Closures have been changed to capture the late bound class very eagerly to make the `static` keyword work.
This had a side effect of backwards-incompatible visibility breaking.

For a full example, see http://3v4l.org/O5dLF.
This worked in <=5.4.29, <=5.5.13, but breaks in >=5.4.30, >=5.5.14, >=5.6.1.

It would seem sensible that refactoring the code inside a closure would not change the visibility restrictions.


Test script:
---------------
class Base {
  public static function hi() {
    echo Left::$prot;
    $cl = function(){
      echo Left::$prot;
    };
    $cl();
  }
}

class Left extends Base {
  protected static $prot = "works\n";
}

class Right extends Base {
}

Right::hi();


Expected result:
----------------
works
works

Actual result:
--------------
works
Fatal error: Cannot access protected property Left::$prot


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-10-17 13:18 UTC] tyrael@php.net
-Assigned To: +Assigned To: levim
 [2014-10-17 13:18 UTC] tyrael@php.net
Levi, could you look into this please?
 [2014-10-17 13:58 UTC] levim@php.net
To be completely honest, I am not sure why Right and Base can access a protected property in Left. The behavior of the closure actually seems correct to me.

I'll have to poke around in documentation and talk to more people. Thank you for this report.
 [2014-10-17 14:45 UTC] levim@php.net
This behavior is documented on the visibility page: http://php.net/manual/en/language.oop5.visibility.php

> Members declared protected can be accessed only within the class itself and by inherited and parent classes.

With that being said, everyone I have talked to thus far believes it is a bug and should be considered for removal in the next major version of PHP. This needs to be discussed with more people.

While that discussion is going on I'll dig into the technical details of why the closure doesn't work.
 [2015-05-05 17:59 UTC] levim@php.net
I have looked at this again and I believe that this is not a bug. Class Right has no permission to access anything that is protected or private in Left.
 [2015-05-05 17:59 UTC] levim@php.net
-Status: Assigned +Status: Feedback
 [2015-05-07 06:40 UTC] denis at slik dot eu
Is that a bug in the documentation, then? (The bit that you have quoted)

In addition, is the difference of behavior between regular code and code in the same location in the closure intended?

Finally, do you consider a backwards compatibility breakage?
 [2015-05-17 04:22 UTC] php-bugs at lists dot php dot net
No feedback was provided. The bug is being suspended because
we assume that you are no longer experiencing the problem.
If this is not the case and you are able to provide the
information that was requested earlier, please do so and
change the status of the bug back to "Re-Opened". Thank you.
 [2015-05-17 06:20 UTC] requinix@php.net
-Status: No Feedback +Status: Open
 [2015-05-20 16:33 UTC] nikic@php.net
-Status: Assigned +Status: Closed
 [2015-05-20 16:33 UTC] nikic@php.net
Your code will work in PHP 7. So the consistency bug between closure / non-closure was fixed.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Apr 23 21:01:31 2024 UTC