--- /dev/null
+--TEST--
+call_user_func() behavior with references
+--FILE--
+<?php
+
+function test(&$ref1, &$ref2) {
+ $ref1 += 42;
+ $ref2 -= 42;
+ return true;
+}
+
+$i = $j = 0;
+var_dump(call_user_func('test', $i, $j));
+var_dump($i, $j);
+
+var_dump(call_user_func_array('test', [$i, $j]));
+var_dump($i, $j);
+
+$x =& $i; $y =& $j;
+var_dump(call_user_func('test', $i, $j));
+var_dump($i, $j);
+
+var_dump(call_user_func_array('test', [$i, $j]));
+var_dump($i, $j);
+
+?>
+--EXPECTF--
+Warning: Parameter 1 to test() expected to be a reference, value given in %s on line %d
+
+Warning: Parameter 2 to test() expected to be a reference, value given in %s on line %d
+bool(true)
+int(0)
+int(0)
+
+Warning: Parameter 1 to test() expected to be a reference, value given in %s on line %d
+
+Warning: Parameter 2 to test() expected to be a reference, value given in %s on line %d
+bool(true)
+int(0)
+int(0)
+
+Warning: Parameter 1 to test() expected to be a reference, value given in %s on line %d
+
+Warning: Parameter 2 to test() expected to be a reference, value given in %s on line %d
+bool(true)
+int(0)
+int(0)
+
+Warning: Parameter 1 to test() expected to be a reference, value given in %s on line %d
+
+Warning: Parameter 2 to test() expected to be a reference, value given in %s on line %d
+bool(true)
+int(0)
+int(0)
if (ARG_SHOULD_BE_SENT_BY_REF(func, i + 1)) {
if (UNEXPECTED(!Z_ISREF_P(arg))) {
- if (fci->no_separation &&
- !ARG_MAY_BE_SENT_BY_REF(func, i + 1)) {
- if (i) {
- /* hack to clean up the stack */
- ZEND_CALL_NUM_ARGS(call) = i;
- zend_vm_stack_free_args(call);
- }
- zend_vm_stack_free_call_frame(call);
-
- zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given",
- i+1,
+ if (!fci->no_separation) {
+ /* Separation is enabled -- create a ref */
+ ZVAL_NEW_REF(arg, arg);
+ } else if (!ARG_MAY_BE_SENT_BY_REF(func, i + 1)) {
+ /* By-value send is not allowed -- emit a warning,
+ * but still perform the call with a by-value send. */
+ zend_error(E_WARNING,
+ "Parameter %d to %s%s%s() expected to be a reference, value given", i+1,
func->common.scope ? ZSTR_VAL(func->common.scope->name) : "",
func->common.scope ? "::" : "",
ZSTR_VAL(func->common.function_name));
- if (EG(current_execute_data) == &dummy_execute_data) {
- EG(current_execute_data) = dummy_execute_data.prev_execute_data;
- }
- return FAILURE;
}
-
- ZVAL_NEW_REF(arg, arg);
}
- Z_ADDREF_P(arg);
} else {
if (Z_ISREF_P(arg) &&
!(func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
/* don't separate references for __call */
arg = Z_REFVAL_P(arg);
}
- if (Z_OPT_REFCOUNTED_P(arg)) {
- Z_ADDREF_P(arg);
- }
}
+
param = ZEND_CALL_ARG(call, i+1);
- ZVAL_COPY_VALUE(param, arg);
+ ZVAL_COPY(param, arg);
}
if (UNEXPECTED(func->op_array.fn_flags & ZEND_ACC_CLOSURE)) {
if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
if (UNEXPECTED(!Z_ISREF_P(arg))) {
if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
-
- zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given",
+ /* By-value send is not allowed -- emit a warning,
+ * but still perform the call. */
+ zend_error(E_WARNING,
+ "Parameter %d to %s%s%s() expected to be a reference, value given",
arg_num,
EX(call)->func->common.scope ? ZSTR_VAL(EX(call)->func->common.scope->name) : "",
EX(call)->func->common.scope ? "::" : "",
ZSTR_VAL(EX(call)->func->common.function_name));
- if (ZEND_CALL_INFO(EX(call)) & ZEND_CALL_CLOSURE) {
- OBJ_RELEASE((zend_object*)EX(call)->func->common.prototype);
- }
- if (Z_TYPE(EX(call)->This) == IS_OBJECT) {
- OBJ_RELEASE(Z_OBJ(EX(call)->This));
- }
- EX(call)->func = (zend_function*)&zend_pass_function;
- Z_OBJ(EX(call)->This) = NULL;
- ZEND_SET_CALL_INFO(EX(call), 0, ZEND_CALL_INFO(EX(call)) & ~ZEND_CALL_RELEASE_THIS);
- break;
}
}
} else {
param = ZEND_CALL_VAR(EX(call), opline->result.var);
if (UNEXPECTED(ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num))) {
+ ZVAL_DEREF(arg);
zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given",
opline->op2.num,
EX(call)->func->common.scope ? ZSTR_VAL(EX(call)->func->common.scope->name) : "",
EX(call)->func->common.scope ? "::" : "",
ZSTR_VAL(EX(call)->func->common.function_name));
-
- if (ZEND_CALL_INFO(EX(call)) & ZEND_CALL_CLOSURE) {
- OBJ_RELEASE((zend_object*)EX(call)->func->common.prototype);
- }
- if (Z_TYPE(EX(call)->This) == IS_OBJECT) {
- OBJ_RELEASE(Z_OBJ(EX(call)->This));
- }
- ZVAL_UNDEF(param);
- EX(call)->func = (zend_function*)&zend_pass_function;
- Z_OBJ(EX(call)->This) = NULL;
- ZEND_SET_CALL_INFO(EX(call), 0, ZEND_CALL_INFO(EX(call)) & ~ZEND_CALL_RELEASE_THIS);
-
- FREE_OP1();
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
} else {
if (Z_ISREF_P(arg) &&
!(EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
if (UNEXPECTED(!Z_ISREF_P(arg))) {
if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
-
- zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given",
+ /* By-value send is not allowed -- emit a warning,
+ * but still perform the call. */
+ zend_error(E_WARNING,
+ "Parameter %d to %s%s%s() expected to be a reference, value given",
arg_num,
EX(call)->func->common.scope ? ZSTR_VAL(EX(call)->func->common.scope->name) : "",
EX(call)->func->common.scope ? "::" : "",
ZSTR_VAL(EX(call)->func->common.function_name));
- if (ZEND_CALL_INFO(EX(call)) & ZEND_CALL_CLOSURE) {
- OBJ_RELEASE((zend_object*)EX(call)->func->common.prototype);
- }
- if (Z_TYPE(EX(call)->This) == IS_OBJECT) {
- OBJ_RELEASE(Z_OBJ(EX(call)->This));
- }
- EX(call)->func = (zend_function*)&zend_pass_function;
- Z_OBJ(EX(call)->This) = NULL;
- ZEND_SET_CALL_INFO(EX(call), 0, ZEND_CALL_INFO(EX(call)) & ~ZEND_CALL_RELEASE_THIS);
- break;
}
}
} else {
param = ZEND_CALL_VAR(EX(call), opline->result.var);
if (UNEXPECTED(ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num))) {
+ ZVAL_DEREF(arg);
zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given",
opline->op2.num,
EX(call)->func->common.scope ? ZSTR_VAL(EX(call)->func->common.scope->name) : "",
EX(call)->func->common.scope ? "::" : "",
ZSTR_VAL(EX(call)->func->common.function_name));
-
- if (ZEND_CALL_INFO(EX(call)) & ZEND_CALL_CLOSURE) {
- OBJ_RELEASE((zend_object*)EX(call)->func->common.prototype);
- }
- if (Z_TYPE(EX(call)->This) == IS_OBJECT) {
- OBJ_RELEASE(Z_OBJ(EX(call)->This));
- }
- ZVAL_UNDEF(param);
- EX(call)->func = (zend_function*)&zend_pass_function;
- Z_OBJ(EX(call)->This) = NULL;
- ZEND_SET_CALL_INFO(EX(call), 0, ZEND_CALL_INFO(EX(call)) & ~ZEND_CALL_RELEASE_THIS);
-
- zval_ptr_dtor_nogc(free_op1);
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
} else {
if (Z_ISREF_P(arg) &&
!(EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
param = ZEND_CALL_VAR(EX(call), opline->result.var);
if (UNEXPECTED(ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num))) {
+ ZVAL_DEREF(arg);
zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given",
opline->op2.num,
EX(call)->func->common.scope ? ZSTR_VAL(EX(call)->func->common.scope->name) : "",
EX(call)->func->common.scope ? "::" : "",
ZSTR_VAL(EX(call)->func->common.function_name));
-
- if (ZEND_CALL_INFO(EX(call)) & ZEND_CALL_CLOSURE) {
- OBJ_RELEASE((zend_object*)EX(call)->func->common.prototype);
- }
- if (Z_TYPE(EX(call)->This) == IS_OBJECT) {
- OBJ_RELEASE(Z_OBJ(EX(call)->This));
- }
- ZVAL_UNDEF(param);
- EX(call)->func = (zend_function*)&zend_pass_function;
- Z_OBJ(EX(call)->This) = NULL;
- ZEND_SET_CALL_INFO(EX(call), 0, ZEND_CALL_INFO(EX(call)) & ~ZEND_CALL_RELEASE_THIS);
-
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
} else {
if (Z_ISREF_P(arg) &&
!(EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
';
$a->setStub('<?php
try {
-Phar::webPhar("test.phar", "/index.php", null, array(), "sort");
+Phar::webPhar("test.phar", "/index.php", null, array(), function() { throw new Exception; });
} catch (Exception $e) {
die($e->getMessage() . "\n");
}
--FILE_EXTERNAL--
files/frontcontroller17.phar
--EXPECTF--
-%ahar error: failed to call rewrite callback
\ No newline at end of file
+%ahar error: rewrite callback must return a string or false
';
$a->setStub('<?php
try {
-Phar::webPhar("test.phar", "/index.php", null, array(), "sort");
+Phar::webPhar("test.phar", "/index.php", null, array(), function() { throw new Exception; });
} catch (Exception $e) {
die($e->getMessage() . "\n");
}
--FILE_EXTERNAL--
files/frontcontroller17.phar
--EXPECTF--
-%ahar error: failed to call rewrite callback
\ No newline at end of file
+%ahar error: rewrite callback must return a string or false
string(9) "x.changed"
Warning: Parameter 1 to C::__construct() expected to be a reference, value given in %sbug42976.php on line 15
-
-Warning: ReflectionClass::newInstance(): Invocation of C's constructor failed in %sbug42976.php on line 15
string(10) "x.original"
Warning: Parameter 1 to C::__construct() expected to be a reference, value given in %sbug42976.php on line 18
-
-Warning: ReflectionClass::newInstanceArgs(): Invocation of C's constructor failed in %sbug42976.php on line 18
string(10) "x.original"
Done
?>
--EXPECTF--
Warning: Parameter 1 to sort() expected to be a reference, value given in %sbug41970.php on line 5
-NULL
+bool(true)
Warning: strlen() expects parameter 1 to be string, array given in %sbug41970.php on line 6
NULL
Warning: Parameter 1 to sort() expected to be a reference, value given in %sbug41970.php on line 7
-NULL
+bool(true)
Warning: strlen() expects parameter 1 to be string, array given in %sbug41970.php on line 8
NULL