| Doc Bug #74776 | undocumented change: PHP 7.1 preserves scope of call_user_func, breaks usage | ||||
|---|---|---|---|---|---|
| Submitted: | 2017-06-18 13:42 UTC | Modified: | 2018-07-08 22:36 UTC | ||
| From: | iamonyourroof at gmail dot com | Assigned: | |||
| Status: | Verified | Package: | Documentation problem | ||
| PHP Version: | 7.1.6 | OS: | Linux | ||
| Private report: | No | CVE-ID: | None | ||
[2017-06-18 13:42 UTC] iamonyourroof at gmail dot com
Description: ------------ Dear, the following code has a different output on php 7.0.20 vs php 7.1.0. It includes protected variables in the output, which is not what you would expect. It seems like the scope for call_user_func has changed between these php versions. If this change was on purpose, should it not have been documented as an item on the list of incompatible changes? http://php.net/manual/en/migration71.incompatible.php Test script: --------------- <?php namespace crm; class et{ protected $table = "b"; public $field = "d"; private $x = "private!"; public function dump(){ var_dump( call_user_func('get_object_vars', $this) ); } } $et = new et(); echo phpversion()."\n"; $et->dump(); Expected result: ---------------- private/protected vars exposed Actual result: -------------- private/protected vars exposed on php version higher than 7.1
Patches
Pull Requests
History
AllCommentsChangesGit/SVN commitsRelated reports
[2017-06-29 01:34 UTC] cmb@php.net
-Status: Open +Status: Verified -Assigned To: +Assigned To: dmitry
[2017-06-29 10:20 UTC] dmitry@php.net
It seems the behavior was originally broken in PHP-7.0, when we introduced INIT_USER_CALL opcode. The same code without "namespace crm;" prints private/protected members in PHP-7.*, but not in PHP-5.*.
Now, in PHP-7.1 the behavior of call_user_func() in namespace is consistent with behavior outside namespace (however, this was made unintendedly).
We should fix this for both cases in PHP-7.0 and above (e.g. introduce ZEND_CALL_CALLBACK flag and disable call_user_func("internal_func",...) optimisation), or document the behavior change.
@nikic, what do you think?
[2017-06-29 17:01 UTC] nikic@php.net
Note that this applies to all callbacks, e.g. also array_map: https://3v4l.org/FSHsW Interestingly it looks like HHVM is also using the PHP 7.1 behavior since version 3.19. I don't have a strong opinion on what we should do here. The new behavior is consistent with callback visibility handling (you can call private methods with call_user_func, because the scope of the parent user function is used). I would be fine with just documenting this. To execute a function in a clean scope, a simple way is to use a static closure, like so: public function dump() { $getObjectVars = static function($object) { return get_object_vars($object); }; var_dump($getObjectVars($this)); }
[2017-07-03 07:05 UTC] dmitry@php.net
-Type: Bug +Type: Documentation Problem
[2017-07-09 00:51 UTC] gmblar+php at gmail dot com
IMHO: Both calls should output the same. I don't expect that the scope changes if i use call_user_func.
var_dump(call_user_func('get_object_vars', $this));
var_dump(get_object_vars($this));
[2017-08-14 13:50 UTC] dmitry@php.net
-Package: *General Issues +Package: Documentation problem -Assigned To: dmitry +Assigned To: