php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #52940 call_user_func_array still allows call-time pass-by-reference
Submitted: 2010-09-28 04:53 UTC Modified: 2010-10-01 13:54 UTC
From: cataphract@php.net Assigned: dmitry (profile)
Status: Closed Package: Scripting Engine problem
PHP Version: trunk-SVN-2010-09-28 (SVN) OS: Windows 7 x64; Debian Lenny x64
Private report: No CVE-ID: None
 [2010-09-28 04:53 UTC] cataphract@php.net
Description:
------------
zend_call_function does not properly convert references into non-references, hence allowing passing by reference arguments to functions that expect values.

See also bug #43484.

This is harder to do with internal function because there's currently a variable separation for those. However, it's still not impossible, because if I'm not mistaken there are ways to make the engine give you a variable with is_ref = 1, refcount  <= 1.

I propose making the behavior for internal functions consistent with that of user functions by separating the variable all time if it's a reference and the parameter is to be sent by value; for cases where is_ref = 1, refcount <= 1, the reference flag should be cleared.

Test script:
---------------
<?php
$a = 1;
function test($a) {
$a++;
}

test($a);
echo $a;

call_user_func_array('test', array(&$a));
echo $a;

Expected result:
----------------
11

Actual result:
--------------
12

Patches

no_call_time_pass_by_ref_via_ZCF (last revision 2010-09-28 04:49 UTC by cataphract@php.net)

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2010-09-28 06:49 UTC] cataphract@php.net
The following patch has been added/updated:

Patch Name: no_call_time_pass_by_ref_via_ZCF
Revision:   1285649367
URL:        http://bugs.php.net/patch-display.php?bug=52940&patch=no_call_time_pass_by_ref_via_ZCF&revision=1285649367
 [2010-09-28 06:51 UTC] cataphract@php.net
I ended up implemented a better strategy than separate+clear flag, as that broke a few tests that expected the fci.params's zvals not to have the reference flag changed.

This patch breaks only two tests that explicitly tested for the previous behavior.
 [2010-09-28 07:11 UTC] cataphract@php.net
I've left the exception that was introduced for bug #50394, though I think it should be removed for trunk.

It makes no sense to disallow this:

<?php
class A {
function __call($name, $args) {
var_dump($args);
}
}

$a = new A;
$b = 6;
$a->foobar(&$a);

yet allow this:

<?php
class A {
function __call($name, $args) {
var_dump($args);
}
}

$a = new A;
$b = 6;
call_user_func_array(array($a, 'foobar'), array(&$b));


The problem described in bug #50394 could easily be worked around by, instead of passing by reference to __call, give the argument in an array instead:

<?php
function foo( &$x ) { $x++; }

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

$arg = 1;
$args = array( &$arg );
$proxy = new Proxy;
call_user_func_array( array( $proxy, 'bar' ), array($args) );
var_dump($arg);
 [2010-09-28 11:44 UTC] pajoye@php.net
-Status: Open +Status: Assigned -Assigned To: +Assigned To: dmitry
 [2010-09-28 11:44 UTC] pajoye@php.net
hi Dmitry,

Can you look at this pls?
 [2010-09-29 23:13 UTC] cataphract@php.net
Fixing this would also fix bug #51986.
 [2010-10-01 13:53 UTC] dmitry@php.net
Automatic comment from SVN on behalf of dmitry
Revision: http://svn.php.net/viewvc/?view=revision&amp;revision=303919
Log: Fixed bug #52940 (call_user_func_array still allows call-time pass-by-reference). (cataphract@php.net)
 [2010-10-01 13:54 UTC] dmitry@php.net
-Status: Assigned +Status: Closed
 [2010-10-01 13:54 UTC] dmitry@php.net
This bug has been fixed in SVN.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.


 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Mar 19 10:01:30 2024 UTC