ID:               50394
 User updated by:  tstarling at wikimedia dot org
 Reported By:      tstarling at wikimedia dot org
 Status:           To be documented
-Bug Type:         Documentation problem
+Bug Type:         Scripting Engine problem
 Operating System: Linux
 PHP Version:      5.3.1
 New Comment:

For the record, I've isolated this further, and the annotation suggests
it was introduced in r287466 by stas in the course of fixing another
bug.


Previous Comments:
------------------------------------------------------------------------

[2009-12-07 18:48:45] j...@php.net

Feel free. 

------------------------------------------------------------------------

[2009-12-07 09:51:29] tstarling at wikimedia dot org

I fail to see the relationship with bug #49946. That's just someone
reporting behaviour as a bug which was clearly documented in the 5.3
release notes as a deliberate change. I'm not complaining about the
warning, which I just added to demonstrate the problem. I'm not
complaining about the new behaviour of zend_call_function() as of PHP
5.3.0, I'm complaining about the lost reference in __call in PHP 5.3.1.

The fact that the reference is lost makes it impossible for __call to
implement an "out" parameter.

Your own code still demostrates the bug nicely, if you change the $arg
in the foreach to &$arg and then make foo() attempt to modify its
parameter:

<?php

function foo( &$x ) {
        $x = 2;
}

class Proxy {
    function __call( $name, $args ) {
        debug_zval_dump( $args );       

        $pass = array();
        foreach ($args as &$arg)
            $pass[] =& $arg;
            
        call_user_func_array( 'foo', $pass );
    }
}

$arg = 1;
$args = array( &$arg );
$proxy = new Proxy;
call_user_func_array( array( $proxy, 'bar' ), $args );
debug_zval_dump( $arg );

?>

The final debug_zval_dump() produces 2 in PHP 5.3.0 and 1 in PHP 5.3.1.


Jani, I seem to remember that last time our paths crossed, the issue
ended up on php-dev:

http://marc.info/?l=php-internals&m=124226646727485&w=2

I'm happy to take this one there as well if necessary.

------------------------------------------------------------------------

[2009-12-07 08:00:05] j...@php.net

See bug #49946 and Johannes' comment. This works (in both 5.3 and
5.2):

<?php

function foo( &$x ) {}

class Proxy {
    function __call( $name, $args ) {
        debug_zval_dump( $args );       

        $pass = array();
        foreach ($args as $arg)
            $pass[] =& $arg;
            
        call_user_func_array( 'foo', $pass );
    }
}
         
$arg = 1;
$args = array( &$arg );
$proxy = new Proxy;
call_user_func_array( array( $proxy, 'bar' ), $args );

?>

This really should be documented on the manual at
http://php.net/call_user_func_array


------------------------------------------------------------------------

[2009-12-07 01:40:18] tstarling at wikimedia dot org

Description:
------------
This is a regression in the PHP 5.3.1 release. When you call a __call()
function with a reference parameter, it is silently converted to a
value, by the time it reaches the second argument to __call().

This breaks MediaWiki and has no obvious workaround.

Reproduce code:
---------------
function foo( &$x ) {}

class Proxy {
        function __call( $name, $args ) {
                debug_zval_dump( $args );
                call_user_func_array( 'foo', $args );
        }
}

$arg = 1;
$args = array( &$arg );
$proxy = new Proxy;
call_user_func_array( array( &$proxy, 'bar' ), $args );


Expected result:
----------------
PHP 5.3.0 produces:

array(1) refcount(4){
  [0]=>
  &long(1) refcount(5)
}


Actual result:
--------------
array(1) refcount(4){
  [0]=>
  long(1) refcount(3)
}

Warning: Parameter 1 to foo() expected to be a reference, value given
in /home/tstarling/src/php/stuff/test-reference-call.php on line 8



------------------------------------------------------------------------


-- 
Edit this bug report at http://bugs.php.net/?id=50394&edit=1

Reply via email to