|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2010-09-28 03:44 UTC] cataphract@php.net
Description:
------------
The function zend_call_function interprets ZEND_SEND_PREFER_REF as if it were ZEND_SEND_BY_REF.
Test script:
---------------
<?php
$a = 'a';
$b = 7;
echo "direct call\n";
test_passing(1, $a, 7);
echo "call via zend_call_function\n";
//separate definition to put the refcount of the third parameter=2.
//If it were 1, zend_call_function would use its special "convert
//into reference" case and wouldn't error out
//i.e., this works: call_user_func_array('test_passing', array(1, &$a, 7));
$arguments = array(1, &$a, 7);
call_user_func_array('test_passing', $arguments);
------
PHP_FUNCTION(test_passing)
{
zval ***params;
unsigned param_count;
int i;
param_count = ZEND_NUM_ARGS();
params = emalloc(param_count * sizeof *params);
for (i = 0; i < (int) param_count; i++) {
params[i] = (zval **) (zend_vm_stack_top(TSRMLS_C) - 1 - (param_count - i));
php_printf("[%p, refcount=%u] ", *params[i], (*params[i])->refcount__gc);
php_var_dump(params[i], 0 TSRMLS_CC);
}
efree(params);
}
ZEND_BEGIN_ARG_INFO_EX(arginfo_test_passing, 0, 0, 3)
ZEND_ARG_INFO(0, req_pass_by_val)
ZEND_ARG_INFO(1, req_pass_by_ref)
ZEND_ARG_INFO(2, req_prefer_ pass_by_ref)
ZEND_END_ARG_INFO()
Expected result:
----------------
Both calls would be successful.
Actual result:
--------------
Only the direct call is successful:
direct call
[0x5ddbed0, refcount=1] int(1)
[0x5ddc530, refcount=2] &string(1) "a"
[0x5ddbf20, refcount=1] int(7)
call via zend_call_function
PHP Warning: Parameter 3 to test_passing() expected to be a reference, value gi
ven in - on line 12
Patcheszend_call_user_function_prefer_ref (last revision 2010-09-28 01:57 UTC by cataphract@php.net)Pull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Thu Oct 30 14:00:01 2025 UTC |
The test you added doesn't test the issue. The problem is not zend_call_function + ZEND_SEND_PREF_REF not accepting reference; it's not accepting values. This is the correct test: <?php var_dump(array_multisort(array("row1" => 2, "row2" => 1))); $ar1 = array("row1" => 2, "row2" => 1); var_dump(call_user_func_array("array_multisort", array($ar1))); var_dump($ar1); The "normal" call works, because even though it's a value, it's accepted because of ZEND_SEND_PREFER_REF. The call via call_user_func_array still fails because of this bug.Note that array($ar1) creates an array with a copy of $ar1 and its modification doesn't affect the original $ar1 value. Probably the proper test would be <?php $args = array(array("row1" => 2, "row2" => 1)); call_user_func_array("array_multisort", $args); var_dump($args[0]); ?> I'll check if it works tomorrow. But anyway it's not the thing you like.This last test is exactly the same thing, and still gives an error. The only thing that would be different would be call_user_func_array("array_multisort", array(array("row1" => 2, "row2" => 1))); because now the inner array refcount would be 1 and in that case zend_call_function flips is_ref. This code $args = array(array("row1" => 2, "row2" => 1)); call_user_func_array("array_multisort", $args); should still pass $args[0] by value. The fact that it can't be modified is irrelevant; array_multisort explicitly declares it can accept a value (probably because it can accept multiple arrays and one may want to modify only some).