]> granicus.if.org Git - php/commitdiff
- Fixed sefaults (tests added)
authorChristian Seiler <cseiler@php.net>
Mon, 11 Aug 2008 22:30:44 +0000 (22:30 +0000)
committerChristian Seiler <cseiler@php.net>
Mon, 11 Aug 2008 22:30:44 +0000 (22:30 +0000)
ext/reflection/php_reflection.c
ext/reflection/tests/closures_003.phpt [new file with mode: 0644]
ext/reflection/tests/closures_004.phpt [new file with mode: 0644]
ext/reflection/tests/reflectionParameter_invalidMethodInConstructor.phpt [new file with mode: 0644]

index a1223540a00cf9d5430f3f6a01b575458c986fb4..386e35196a1559bf2dcf66ed22fcbb5e7366f880 100644 (file)
@@ -228,6 +228,28 @@ static void reflection_register_implement(zend_class_entry *class_entry, zend_cl
 }
 /* }}} */
 
+static zend_function *_copy_function(zend_function *fptr TSRMLS_DC) /* {{{ */
+{
+       if (fptr
+               && fptr->type == ZEND_INTERNAL_FUNCTION
+               && (fptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0)
+       {
+               zend_function *copy_fptr;
+               copy_fptr = emalloc(sizeof(zend_function));
+               memcpy(copy_fptr, fptr, sizeof(zend_function));
+               if (UG(unicode)) {
+                       copy_fptr->internal_function.function_name.u = eustrdup(fptr->internal_function.function_name.u);
+               } else {
+                       copy_fptr->internal_function.function_name.s = estrdup(fptr->internal_function.function_name.s);
+               }
+               return copy_fptr;
+       } else {
+               /* no copy needed */
+               return fptr;
+       }
+}
+/* }}} */
+
 static void _free_function(zend_function *fptr TSRMLS_DC) /* {{{ */
 {
        if (fptr
@@ -1812,7 +1834,7 @@ ZEND_METHOD(reflection_function, getParameters)
                zval *parameter;   
 
                ALLOC_ZVAL(parameter);
-               reflection_parameter_factory(fptr, arg_info, i, fptr->common.required_num_args, parameter TSRMLS_CC);
+               reflection_parameter_factory(_copy_function(fptr TSRMLS_CC), arg_info, i, fptr->common.required_num_args, parameter TSRMLS_CC);
                add_next_index_zval(return_value, parameter);
 
                arg_info++;
@@ -1956,7 +1978,7 @@ ZEND_METHOD(reflection_parameter, __construct)
                                } else if (zend_u_hash_find(&ce->function_table, Z_TYPE_PP(method), lcname, lcname_len + 1, (void **) &fptr) == FAILURE) {
                                        efree(lcname.v);
                                        zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
-                                               "Method %R::%R() does not exist", Z_TYPE_PP(classref), Z_UNIVAL_PP(classref), Z_TYPE_PP(method), Z_UNIVAL_PP(method));
+                                               "Method %v::%R() does not exist", ce->name, Z_TYPE_PP(method), Z_UNIVAL_PP(method));
                                        return;
                                }
                                efree(lcname.v);
@@ -2064,9 +2086,9 @@ ZEND_METHOD(reflection_parameter, getDeclaringFunction)
        GET_REFLECTION_OBJECT_PTR(param);
 
        if (!param->fptr->common.scope) {
-               reflection_function_factory(param->fptr, return_value TSRMLS_CC);
+               reflection_function_factory(_copy_function(param->fptr TSRMLS_CC), return_value TSRMLS_CC);
        } else {
-               reflection_method_factory(param->fptr->common.scope, param->fptr, return_value TSRMLS_CC);
+               reflection_method_factory(param->fptr->common.scope, _copy_function(param->fptr TSRMLS_CC), return_value TSRMLS_CC);
        }
 }
 /* }}} */
@@ -2458,7 +2480,14 @@ ZEND_METHOD(reflection_method, getClosure)
                        /* Returns from this function */
                }
 
-               zend_create_closure(return_value, mptr, mptr->common.scope, obj TSRMLS_CC);
+               /* This is an original closure object and __invoke is to be called. */
+               if (Z_OBJCE_P(obj) == zend_ce_closure && mptr->type == ZEND_INTERNAL_FUNCTION &&
+                       (mptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0)
+               {
+                       RETURN_ZVAL(obj, 1, 0);
+               } else {
+                       zend_create_closure(return_value, mptr, mptr->common.scope, obj TSRMLS_CC);
+               }
        }
 }
 /* }}} */
diff --git a/ext/reflection/tests/closures_003.phpt b/ext/reflection/tests/closures_003.phpt
new file mode 100644 (file)
index 0000000..cc30939
--- /dev/null
@@ -0,0 +1,25 @@
+--TEST--
+Reflection on closures: Segfaults with getParameters() and getDeclaringFunction()
+--FILE-- 
+<?php
+
+$closure = function($a, $b = 0) { };
+
+$method = new ReflectionMethod ($closure);
+$params = $method->getParameters ();
+unset ($method);
+$method = $params[0]->getDeclaringFunction ();
+unset ($params);
+echo $method->getName ()."\n";
+
+$parameter = new ReflectionParameter ($closure, 'b');
+$method = $parameter->getDeclaringFunction ();
+unset ($parameter);
+echo $method->getName ()."\n";
+
+?>
+===DONE===
+--EXPECTF--
+__invoke
+__invoke
+===DONE===
diff --git a/ext/reflection/tests/closures_004.phpt b/ext/reflection/tests/closures_004.phpt
new file mode 100644 (file)
index 0000000..6b75045
--- /dev/null
@@ -0,0 +1,27 @@
+--TEST--
+Reflection on closures: Segfault with getClosure() on closure itself
+--FILE-- 
+<?php
+
+$closure = function() { echo "Invoked!\n"; };
+
+$method = new ReflectionMethod ($closure);
+
+$closure2 = $method->getClosure ($closure);
+
+$closure2 ();
+$closure2->__invoke ();
+
+unset ($closure);
+
+$closure2 ();
+$closure2->__invoke ();
+
+?>
+===DONE===
+--EXPECTF--
+Invoked!
+Invoked!
+Invoked!
+Invoked!
+===DONE===
diff --git a/ext/reflection/tests/reflectionParameter_invalidMethodInConstructor.phpt b/ext/reflection/tests/reflectionParameter_invalidMethodInConstructor.phpt
new file mode 100644 (file)
index 0000000..3118c17
--- /dev/null
@@ -0,0 +1,31 @@
+--TEST--
+ReflectionParameter::__construct(): Invalid method as constructor
+--FILE-- 
+<?php
+
+// Invalid class name
+try {
+       new ReflectionParameter (array ('A', 'b'), 0);
+} catch (ReflectionException $e) { echo $e->getMessage ()."\n"; }
+
+// Invalid class method
+try {
+       new ReflectionParameter (array ('C', 'b'), 0);
+} catch (ReflectionException $e) { echo $e->getMessage ()."\n"; }
+
+// Invalid object method
+try {
+       new ReflectionParameter (array (new C, 'b'), 0);
+} catch (ReflectionException $e) { echo $e->getMessage ()."\n"; }
+
+echo "Done.\n";
+
+class C {
+}
+
+?>
+--EXPECTF--
+Class A does not exist
+Method C::b() does not exist
+Method C::b() does not exist
+Done.