- Fixed bug #52060 (Memory leak when passing a closure to method_exists()).
(Felipe)
+- Fixed bug #52057 (ReflectionClass fails on Closure class). (Felipe)
- Fixed bug #52019 (make lcov doesn't support TESTS variable anymore). (Patrick)
- Fixed bug #52010 (open_basedir restrictions mismatch on vacuum command).
(Ilia)
GET_REFLECTION_OBJECT_PTR(ce);
lc_name = zend_str_tolower_dup(name, name_len);
- if (zend_hash_exists(&ce->function_table, lc_name, name_len + 1)) {
+ if ((ce == zend_ce_closure && (name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
+ && memcmp(lc_name, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0)
+ || zend_hash_exists(&ce->function_table, lc_name, name_len + 1)) {
efree(lc_name);
RETURN_TRUE;
} else {
reflection_object *intern;
zend_class_entry *ce;
zend_function *mptr;
+ zval obj_tmp;
char *name, *lc_name;
int name_len;
method and not the closure definition itself */
reflection_method_factory(ce, mptr, NULL, return_value TSRMLS_CC);
efree(lc_name);
+ } else if (ce == zend_ce_closure && !intern->obj && (name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
+ && memcmp(lc_name, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
+ && object_init_ex(&obj_tmp, ce) == SUCCESS && (mptr = zend_get_closure_invoke_method(&obj_tmp TSRMLS_CC)) != NULL) {
+ /* don't assign closure_object since we only reflect the invoke handler
+ method and not the closure definition itself */
+ reflection_method_factory(ce, mptr, NULL, return_value TSRMLS_CC);
+ zval_dtor(&obj_tmp);
+ efree(lc_name);
} else if (zend_hash_find(&ce->function_table, lc_name, name_len + 1, (void**) &mptr) == SUCCESS) {
reflection_method_factory(ce, mptr, NULL, return_value TSRMLS_CC);
efree(lc_name);
--- /dev/null
+--TEST--
+Bug #52057 (ReflectionClass fails on Closure class)
+--FILE--
+<?php
+
+$closure = function($a) { echo $a; };
+
+$reflection = new ReflectionClass('closure');
+var_dump($reflection->hasMethod('__invoke')); // true
+
+$reflection = new ReflectionClass($closure);
+var_dump($reflection->hasMethod('__invoke')); // true
+
+$reflection = new ReflectionObject($closure);
+var_dump($reflection->hasMethod('__invoke')); // true
+
+$reflection = new ReflectionClass('closure');
+var_dump($h = $reflection->getMethod('__invoke')); // true
+var_dump($h->class.'::'.$h->getName());
+
+$reflection = new ReflectionClass($closure);
+var_dump($h = $reflection->getMethod('__invoke')); // true
+var_dump($h->class.'::'.$h->getName());
+
+$reflection = new ReflectionObject($closure);
+var_dump($h = $reflection->getMethod('__invoke')); // true
+var_dump($h->class.'::'.$h->getName());
+
+?>
+--EXPECTF--
+bool(true)
+bool(true)
+bool(true)
+object(ReflectionMethod)#%d (2) {
+ ["name"]=>
+ string(8) "__invoke"
+ ["class"]=>
+ string(7) "Closure"
+}
+string(17) "Closure::__invoke"
+object(ReflectionMethod)#%d (2) {
+ ["name"]=>
+ string(8) "__invoke"
+ ["class"]=>
+ string(7) "Closure"
+}
+string(17) "Closure::__invoke"
+object(ReflectionMethod)#%d (2) {
+ ["name"]=>
+ string(8) "__invoke"
+ ["class"]=>
+ string(7) "Closure"
+}
+string(17) "Closure::__invoke"