diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2019-05-09 12:29:33 +0200 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2019-05-09 12:33:53 +0200 |
commit | 35c80583f08c0af3d01715cb8feeca6d0f284545 (patch) | |
tree | 79143a9e78e8aaf0c4ae089ba97165994c62b23a | |
parent | e359812ce3b01f184601fde75e3963b550fc599d (diff) | |
download | php-git-35c80583f08c0af3d01715cb8feeca6d0f284545.tar.gz |
Fixed bug #75186
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | ext/reflection/php_reflection.c | 41 | ||||
-rw-r--r-- | ext/reflection/tests/bug75186.phpt | 25 |
3 files changed, 48 insertions, 21 deletions
@@ -14,6 +14,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 0a59d9a74c..012f23982d 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -4203,22 +4203,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) - { - _fix_closure_prototype(closure); - 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); } @@ -4232,9 +4220,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; } /* }}} */ @@ -4260,13 +4247,25 @@ 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) { _fix_closure_prototype(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! |