php.net |  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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: iamonyourroof at gmail dot com
New email:
PHP Version: OS:

 

 [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 01:34 UTC] 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-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:
 [2018-07-08 22:36 UTC] cmb@php.net
Since variable functions “always” behaved this way[1], I think
this is a reasonable change.

[1] <https://3v4l.org/bL349>
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sun Nov 24 13:01:32 2024 UTC