summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikic@php.net>2016-09-30 22:08:08 +0200
committerNikita Popov <nikic@php.net>2016-09-30 22:10:01 +0200
commit02ba9d71abc9f830fc9707eb2a7daabf37298f7d (patch)
tree34cc2775549627b27367fb4ca9da7b495c7cc7f7
parente63443d8251227df26d9ca114f1bc8e7c0f1651f (diff)
downloadphp-git-02ba9d71abc9f830fc9707eb2a7daabf37298f7d.tar.gz
Unwrap reference returns in cufa etc
-rw-r--r--Zend/tests/dynamic_call_to_ref_returning_function.phpt39
-rw-r--r--Zend/zend_closures.c3
-rw-r--r--ext/reflection/php_reflection.c9
-rw-r--r--ext/standard/basic_functions.c12
4 files changed, 63 insertions, 0 deletions
diff --git a/Zend/tests/dynamic_call_to_ref_returning_function.phpt b/Zend/tests/dynamic_call_to_ref_returning_function.phpt
new file mode 100644
index 0000000000..c4b6a9bcff
--- /dev/null
+++ b/Zend/tests/dynamic_call_to_ref_returning_function.phpt
@@ -0,0 +1,39 @@
+--TEST--
+When performing a dynamic call to a ret-by-ref function, the reference should be unwrapped
+--FILE--
+<?php
+
+namespace Foo;
+
+function &retRef($x) {
+ return $x;
+}
+
+var_dump(call_user_func('Foo\retRef', 42));
+var_dump(call_user_func_array('Foo\retRef', [42]));
+
+$closure = function &($x) {
+ return $x;
+};
+var_dump($closure->call(new class {}, 42));
+
+var_dump((new \ReflectionFunction('Foo\retRef'))->invoke(42));
+var_dump((new \ReflectionFunction('Foo\retRef'))->invokeArgs([42]));
+
+class Bar {
+ function &method($x) {
+ return $x;
+ }
+}
+var_dump((new \ReflectionMethod('Foo\Bar', 'method'))->invoke(new Bar, 42));
+var_dump((new \ReflectionMethod('Foo\Bar', 'method'))->invokeArgs(new Bar, [42]));
+
+?>
+--EXPECT--
+int(42)
+int(42)
+int(42)
+int(42)
+int(42)
+int(42)
+int(42)
diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c
index bedf022a4b..eb726484f5 100644
--- a/Zend/zend_closures.c
+++ b/Zend/zend_closures.c
@@ -166,6 +166,9 @@ ZEND_METHOD(Closure, call)
}
if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(closure_result) != IS_UNDEF) {
+ if (Z_ISREF(closure_result)) {
+ zend_unwrap_reference(&closure_result);
+ }
ZVAL_COPY_VALUE(return_value, &closure_result);
}
diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c
index 52d35409d3..9ecb04d461 100644
--- a/ext/reflection/php_reflection.c
+++ b/ext/reflection/php_reflection.c
@@ -1985,6 +1985,9 @@ ZEND_METHOD(reflection_function, invoke)
}
if (Z_TYPE(retval) != IS_UNDEF) {
+ if (Z_ISREF(retval)) {
+ zend_unwrap_reference(&retval);
+ }
ZVAL_COPY_VALUE(return_value, &retval);
}
}
@@ -2048,6 +2051,9 @@ ZEND_METHOD(reflection_function, invokeArgs)
}
if (Z_TYPE(retval) != IS_UNDEF) {
+ if (Z_ISREF(retval)) {
+ zend_unwrap_reference(&retval);
+ }
ZVAL_COPY_VALUE(return_value, &retval);
}
}
@@ -3323,6 +3329,9 @@ static void reflection_method_invoke(INTERNAL_FUNCTION_PARAMETERS, int variadic)
}
if (Z_TYPE(retval) != IS_UNDEF) {
+ if (Z_ISREF(retval)) {
+ zend_unwrap_reference(&retval);
+ }
ZVAL_COPY_VALUE(return_value, &retval);
}
}
diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c
index fa90206a45..13e8a4e6eb 100644
--- a/ext/standard/basic_functions.c
+++ b/ext/standard/basic_functions.c
@@ -4823,6 +4823,9 @@ PHP_FUNCTION(call_user_func)
fci.retval = &retval;
if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
+ if (Z_ISREF(retval)) {
+ zend_unwrap_reference(&retval);
+ }
ZVAL_COPY_VALUE(return_value, &retval);
}
}
@@ -4846,6 +4849,9 @@ PHP_FUNCTION(call_user_func_array)
fci.retval = &retval;
if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
+ if (Z_ISREF(retval)) {
+ zend_unwrap_reference(&retval);
+ }
ZVAL_COPY_VALUE(return_value, &retval);
}
@@ -4880,6 +4886,9 @@ PHP_FUNCTION(forward_static_call)
}
if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
+ if (Z_ISREF(retval)) {
+ zend_unwrap_reference(&retval);
+ }
ZVAL_COPY_VALUE(return_value, &retval);
}
}
@@ -4908,6 +4917,9 @@ PHP_FUNCTION(forward_static_call_array)
}
if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
+ if (Z_ISREF(retval)) {
+ zend_unwrap_reference(&retval);
+ }
ZVAL_COPY_VALUE(return_value, &retval);
}