diff options
| -rw-r--r-- | Zend/tests/dynamic_call_to_ref_returning_function.phpt | 39 | ||||
| -rw-r--r-- | Zend/zend_closures.c | 3 | ||||
| -rw-r--r-- | ext/reflection/php_reflection.c | 9 | ||||
| -rw-r--r-- | ext/standard/basic_functions.c | 12 | 
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);  	} | 
