|  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
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
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
Block user comment
Status: Assign to:
Bug Type:
From: iamonyourroof at gmail dot com
New email:
PHP Version: OS:


 [2017-06-18 13:42 UTC] iamonyourroof at gmail dot com

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?

Test script:

    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";

Expected result:
private/protected vars exposed

Actual result:
private/protected vars exposed on php version higher than 7.1


Add a Patch

Pull Requests

Add a Pull Request


AllCommentsChangesGit/SVN commitsRelated reports
 [2017-06-29 01:34 UTC]
-Status: Open +Status: Verified -Assigned To: +Assigned To: dmitry
 [2017-06-29 01:34 UTC]
It seems this behavioral change has been introduced with commit
6499162[1]. Therefore, I'm assigning to dmitry for clarification.

[1] <>
 [2017-06-29 10:20 UTC]
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]
Note that this applies to all callbacks, e.g. also array_map: 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); };
 [2017-07-03 07:05 UTC]
-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));

 [2017-08-14 13:50 UTC]
-Package: *General Issues +Package: Documentation problem -Assigned To: dmitry +Assigned To:
 [2018-07-08 22:36 UTC]
Since variable functions “always” behaved this way[1], I think
this is a reasonable change.

[1] <>
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Jul 16 07:01:31 2024 UTC