From: Christian Seiler Date: Mon, 11 Aug 2008 22:30:44 +0000 (+0000) Subject: - Fixed sefaults (tests added) X-Git-Tag: BEFORE_HEAD_NS_CHANGE~764 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d40f3ef30e2c22149513d8ec48794063e5e9d89a;p=php - Fixed sefaults (tests added) --- diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index a1223540a0..386e35196a 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -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 index 0000000000..cc309397b5 --- /dev/null +++ b/ext/reflection/tests/closures_003.phpt @@ -0,0 +1,25 @@ +--TEST-- +Reflection on closures: Segfaults with getParameters() and getDeclaringFunction() +--FILE-- +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 index 0000000000..6b75045910 --- /dev/null +++ b/ext/reflection/tests/closures_004.phpt @@ -0,0 +1,27 @@ +--TEST-- +Reflection on closures: Segfault with getClosure() on closure itself +--FILE-- +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 index 0000000000..3118c17be8 --- /dev/null +++ b/ext/reflection/tests/reflectionParameter_invalidMethodInConstructor.phpt @@ -0,0 +1,31 @@ +--TEST-- +ReflectionParameter::__construct(): Invalid method as constructor +--FILE-- +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.