Bug #74776 [Ver]: undocumented change: PHP 7.1 preserves scope of call_user_func, breaks usage

From: 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

« previous php.bugs (#209733) next »