Bug #74776 [Ver]: undocumented change: PHP 7.1 preserves scope of call_user_func, breaks usage
| From: | nikic@php.net | Date: | Thu, 29 Jun 2017 17:01:56 +0000 |
| Subject: | Bug #74776 [Ver]: undocumented change: PHP 7.1 preserves scope of call_user_func, breaks usage | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-209733@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=74776&edit=1
ID: 74776
Updated by: nikic@php.net
Reported by: iamonyourroof at gmail dot com
Summary: undocumented change: PHP 7.1 preserves scope of
call_user_func, breaks usage
Status: Verified
Type: Bug
Package: *General Issues
Operating System: Linux
PHP Version: 7.1.6
Assigned To: dmitry
Block user comment: N
Private report: N
New Comment:
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));
}
Previous Comments:
------------------------------------------------------------------------
[2017-06-29 10:20:03] 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 01:34:02] cmb@php.net
It seems this behavioral change has been introduced with commit
6499162[1]. Therefore, I'm assigning to dmitry for clarification.
[1] <https://github.com/php/php-src/commit/6499162>
------------------------------------------------------------------------
[2017-06-18 13:42:48] 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
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=74776&edit=1