summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2019-05-09 12:34:46 +0200
committerNikita Popov <nikita.ppv@gmail.com>2019-05-09 12:35:11 +0200
commit90318fbcbed95e9f4469d697d47f76b9bd12e17f (patch)
treef2082f92e25007e5e6bf744e61010e9ae0ea3b7e
parente46b3c3e70e299078ab3c2cf459cd90d1bac1acd (diff)
parent35c80583f08c0af3d01715cb8feeca6d0f284545 (diff)
downloadphp-git-90318fbcbed95e9f4469d697d47f76b9bd12e17f.tar.gz
Merge branch 'PHP-7.2' into PHP-7.3
-rw-r--r--NEWS3
-rw-r--r--ext/reflection/php_reflection.c40
-rw-r--r--ext/reflection/tests/bug75186.phpt25
3 files changed, 48 insertions, 20 deletions
diff --git a/NEWS b/NEWS
index dec04f9ca4..e3283b640c 100644
--- a/NEWS
+++ b/NEWS
@@ -18,6 +18,9 @@ PHP NEWS
- PDO_MySQL:
. Fixed bug #77944 (Wrong meta pdo_type for bigint on LLP64). (cmb)
+- Reflection:
+ . Fixed bug #75186 (Inconsistent reflection of Closure:::__invoke()). (Nikita)
+
- Session:
. Fixed bug #77911 (Wrong warning for session.sid_bits_per_character). (cmb)
diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c
index f30f47f2b7..c38160297d 100644
--- a/ext/reflection/php_reflection.c
+++ b/ext/reflection/php_reflection.c
@@ -4150,21 +4150,10 @@ ZEND_METHOD(reflection_class, getMethod)
/* }}} */
/* {{{ _addmethod */
-static void _addmethod(zend_function *mptr, zend_class_entry *ce, zval *retval, zend_long filter, zval *obj)
+static void _addmethod(zend_function *mptr, zend_class_entry *ce, zval *retval, zend_long filter)
{
- zval method;
- size_t len = ZSTR_LEN(mptr->common.function_name);
- zend_function *closure;
if (mptr->common.fn_flags & filter) {
- if (ce == zend_ce_closure && obj && (len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
- && memcmp(ZSTR_VAL(mptr->common.function_name), ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
- && (closure = zend_get_closure_invoke_method(Z_OBJ_P(obj))) != NULL)
- {
- mptr = closure;
- }
- /* don't assign closure_object since we only reflect the invoke handler
- method and not the closure definition itself, even if we have a
- closure */
+ zval method;
reflection_method_factory(ce, mptr, NULL, &method);
add_next_index_zval(retval, &method);
}
@@ -4178,9 +4167,8 @@ static int _addmethod_va(zval *el, int num_args, va_list args, zend_hash_key *ha
zend_class_entry *ce = *va_arg(args, zend_class_entry**);
zval *retval = va_arg(args, zval*);
long filter = va_arg(args, long);
- zval *obj = va_arg(args, zval *);
- _addmethod(mptr, ce, retval, filter, obj);
+ _addmethod(mptr, ce, retval, filter);
return ZEND_HASH_APPLY_KEEP;
}
/* }}} */
@@ -4205,12 +4193,24 @@ ZEND_METHOD(reflection_class, getMethods)
GET_REFLECTION_OBJECT_PTR(ce);
array_init(return_value);
- zend_hash_apply_with_arguments(&ce->function_table, (apply_func_args_t) _addmethod_va, 4, &ce, return_value, filter, intern->obj);
- if (Z_TYPE(intern->obj) != IS_UNDEF && instanceof_function(ce, zend_ce_closure)) {
- zend_function *closure = zend_get_closure_invoke_method(Z_OBJ(intern->obj));
+ zend_hash_apply_with_arguments(&ce->function_table, (apply_func_args_t) _addmethod_va, 4, &ce, return_value, filter);
+
+ if (instanceof_function(ce, zend_ce_closure)) {
+ zend_bool has_obj = Z_TYPE(intern->obj) != IS_UNDEF;
+ zval obj_tmp;
+ zend_object *obj;
+ if (!has_obj) {
+ object_init_ex(&obj_tmp, ce);
+ obj = Z_OBJ(obj_tmp);
+ } else {
+ obj = Z_OBJ(intern->obj);
+ }
+ zend_function *closure = zend_get_closure_invoke_method(obj);
if (closure) {
- _addmethod(closure, ce, return_value, filter, &intern->obj);
- _free_function(closure);
+ _addmethod(closure, ce, return_value, filter);
+ }
+ if (!has_obj) {
+ zval_ptr_dtor(&obj_tmp);
}
}
}
diff --git a/ext/reflection/tests/bug75186.phpt b/ext/reflection/tests/bug75186.phpt
new file mode 100644
index 0000000000..04563af32b
--- /dev/null
+++ b/ext/reflection/tests/bug75186.phpt
@@ -0,0 +1,25 @@
+--TEST--
+Bug #75186: Inconsistent reflection of Closure:::__invoke()
+--FILE--
+<?php
+
+$rc = new ReflectionClass(Closure::class);
+foreach ($rc->getMethods() as $method) {
+ if ($method->name == '__invoke') {
+ var_dump($method);
+ $method->invoke(
+ function($what) { echo "Hello $what!\n"; },
+ "World"
+ );
+ }
+}
+
+?>
+--EXPECTF--
+object(ReflectionMethod)#%d (2) {
+ ["name"]=>
+ string(8) "__invoke"
+ ["class"]=>
+ string(7) "Closure"
+}
+Hello World!