php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #43484 call_user_func_array(): questionable pass-by-val/pass-by-ref behaviour.
Submitted: 2007-12-03 14:09 UTC Modified: 2008-03-10 10:54 UTC
From: robin_fernandes at uk dot ibm dot com Assigned:
Status: Not a bug Package: Scripting Engine problem
PHP Version: 5.3CVS-2007-12-03 (snap) OS: Windows
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: robin_fernandes at uk dot ibm dot com
New email:
PHP Version: OS:

 

 [2007-12-03 14:09 UTC] robin_fernandes at uk dot ibm dot com
Description:
------------
This issue was originally raised as documentation bug 43079. Raising as Scripting Engine problem as suggested by vrana at php dot net.

The pass-by-value/pass-by-ref behaviour of call_user_func_array() is not intuitive (see the user contributed notes on the documentation page: http://php.net/call_user_func_array ).

It appears that the way in which an argument is passed depends not on the target function signature, but rather on whether its entry in $param_arr is referenced or not.

Specifically, it is possible to force an argument to be passed by
reference to a function which expects a pass-by-value argument, even
with call time pass by reference DISABLED in php.ini.

Reproduced on php5.3 and php6 snaps on Windows.

Reproduce code:
---------------
<?php
 function byRef(&$a, &$b) {
 	$a = 'changed.a';
 	$b = 'changed.b';
 }
 
 function byVal($a, $b) {
 	$a = 'changed.a';
 	$b = 'changed.b';
 }

 //Currently, this forces a pass-by-ref function to take args by val:
 $args = array('original.a', 'original.b');
 call_user_func_array('byRef', $args);
 var_dump($args);

 //Currently, this forces a pass-by-val function to take 1 arg by ref.
 //This works even with call-time pass-by-ref DISABLED in php.ini.
 $args = array('original.a', 'original.b');
 $ref = &$args[0];
 call_user_func_array('byVal', $args);
 var_dump($args); 
?>

Expected result:
----------------
array(2) {
  [0]=>
  string(9) "changed.a"
  [1]=>
  string(9) "changed.b"
}
array(2) {
  [0]=>
  &string(10) "original.a"
  [1]=>
  string(10) "original.b"
}

Actual result:
--------------
array(2) {
  [0]=>
  string(10) "original.a"
  [1]=>
  string(10) "original.b"
}
array(2) {
  [0]=>
  &string(9) "changed.a"
  [1]=>
  string(10) "original.b"
}

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2008-03-08 22:56 UTC] johannes@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php

 $args = array('original.a', 'original.b');

This puts a copy of the value 'original.a' into that array.
 [2008-03-10 10:54 UTC] robin_fernandes at uk dot ibm dot com
Hi Johannes,

Thanks for looking into this. I understand your comment, but I can't quite see how it relates to the behaviour described in the bug report.

The bug describes how, using call_user_func_array(), one can force a function defined with pass-by-value args to take those args by reference - even with call time pass by reference DISABLED in php.ini.

Note that this odd behaviour is now documented (thanks to bug 43079). But the documentation writer suggested raising a functional bug, because the behaviour is potentially dangerous.


Here is a simplified example:
<?php
 function byValue($a) {
   $a = 'This assignment should not affect global scope!';
 }

 $args = array('original');
 $ref = &$args[0]; //dummy reference - remove to change behaviour
 
 call_user_func_array('byValue', $args);
 var_dump($args); 
?>

---( Expected Output )---
array(1) {
  [0]=>
  string(8) "original"
}

---( Actual Output )---
array(1) {
  [0]=>
  &string(47) "This assignment should not affect global scope!"
}
 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Wed Apr 02 18:01:31 2025 UTC