Patch ReflectionMethod-invoke-static-bindings for Reflection related Bug #62113
Patch version 2012-05-22 21:38 UTC
Return to Bug #62113 |
Download this patch
Patch Revisions:
Developer: nathanbruer@gmail.com
ext/reflection/php_reflection.c | 105 ++++++++++++++++++++++++++++++++-------
1 file changed, 87 insertions(+), 18 deletions(-)
diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c
index 406da93..858a0f2 100644
--- a/ext/reflection/php_reflection.c
+++ b/ext/reflection/php_reflection.c
@@ -2807,7 +2807,7 @@ ZEND_METHOD(reflection_method, invoke)
int result, num_args = 0;
zend_fcall_info fci;
zend_fcall_info_cache fcc;
- zend_class_entry *obj_ce;
+ zend_class_entry *obj_ce, **ce_p;
METHOD_NOTSTATIC(reflection_method_ptr);
@@ -2842,8 +2842,42 @@ ZEND_METHOD(reflection_method, invoke)
* Else, we verify that the given object is an instance of the class.
*/
if (mptr->common.fn_flags & ZEND_ACC_STATIC) {
+ object_ptr = *params[0];
+ if (IS_ZEND_STD_OBJECT(*object_ptr)) {
+ obj_ce = Z_OBJCE_P(object_ptr);
+ } else if (Z_TYPE_P(object_ptr) == IS_NULL) {
+ obj_ce = mptr->common.scope;
+ } else {
+ char *class_name;
+ int class_name_len;
+ zval tmp_zval;
+ INIT_ZVAL(tmp_zval);
+
+ if (Z_TYPE_P(object_ptr) == IS_STRING) {
+ class_name = Z_STRVAL_P(object_ptr);
+ class_name_len = Z_STRLEN_P(object_ptr);
+ } else {
+ tmp_zval = *object_ptr;
+ zval_copy_ctor(&tmp_zval);
+ convert_to_string(&tmp_zval);
+ class_name = Z_STRVAL(tmp_zval);
+ class_name_len = Z_STRLEN(tmp_zval);
+ }
+
+ if ((class_name_len == sizeof("static") - 1) &&
+ (memcmp("static", class_name, sizeof("static") - 1) == 0)) {
+ obj_ce = mptr->common.scope;
+ }
+ else if (zend_lookup_class_ex(class_name, class_name_len, NULL, 1, &ce_p TSRMLS_CC) == FAILURE) {
+ zend_error(E_WARNING, "Class '%s' not found", class_name);
+ zval_dtor(&tmp_zval);
+ RETURN_NULL();
+ } else {
+ obj_ce = *ce_p;
+ }
+ zval_dtor(&tmp_zval);
+ }
object_ptr = NULL;
- obj_ce = mptr->common.scope;
} else {
if (Z_TYPE_PP(params[0]) != IS_OBJECT) {
efree(params);
@@ -2853,13 +2887,14 @@ ZEND_METHOD(reflection_method, invoke)
obj_ce = Z_OBJCE_PP(params[0]);
- if (!instanceof_function(obj_ce, mptr->common.scope TSRMLS_CC)) {
- if (params) {
- efree(params);
- }
- _DO_THROW("Given object is not an instance of the class this method was declared in");
+ /* This should not be required any more as you can invoke a method from any object. */
+ //if (!instanceof_function(obj_ce, mptr->common.scope TSRMLS_CC)) {
+ // if (params) {
+ // efree(params);
+ // }
+ // _DO_THROW("Given object is not an instance of the class this method was declared in");
/* Returns from this function */
- }
+ //}
object_ptr = *params[0];
}
@@ -2877,7 +2912,7 @@ ZEND_METHOD(reflection_method, invoke)
fcc.initialized = 1;
fcc.function_handler = mptr;
fcc.calling_scope = obj_ce;
- fcc.called_scope = intern->ce;
+ fcc.called_scope = obj_ce;
fcc.object_ptr = object_ptr;
result = zend_call_function(&fci, &fcc TSRMLS_CC);
@@ -2911,14 +2946,14 @@ ZEND_METHOD(reflection_method, invokeArgs)
int result;
zend_fcall_info fci;
zend_fcall_info_cache fcc;
- zend_class_entry *obj_ce;
+ zend_class_entry *obj_ce, **ce_p;
zval *param_array;
METHOD_NOTSTATIC(reflection_method_ptr);
GET_REFLECTION_OBJECT_PTR(mptr);
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o!a", &object, ¶m_array) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|a", &object, ¶m_array) == FAILURE) {
return;
}
@@ -2939,7 +2974,6 @@ ZEND_METHOD(reflection_method, invokeArgs)
}
return;
}
-
argc = zend_hash_num_elements(Z_ARRVAL_P(param_array));
params = safe_emalloc(sizeof(zval **), argc, 0);
@@ -2953,8 +2987,42 @@ ZEND_METHOD(reflection_method, invokeArgs)
* Else, we verify that the given object is an instance of the class.
*/
if (mptr->common.fn_flags & ZEND_ACC_STATIC) {
+
+ if (IS_ZEND_STD_OBJECT(*object)) {
+ obj_ce = Z_OBJCE_P(object);
+ } else if (Z_TYPE_P(object) == IS_NULL) {
+ obj_ce = mptr->common.scope;
+ } else {
+ char *class_name;
+ int class_name_len;
+ zval tmp_zval;
+ INIT_ZVAL(tmp_zval);
+
+ if (Z_TYPE_P(object) == IS_STRING) {
+ class_name = Z_STRVAL_P(object);
+ class_name_len = Z_STRLEN_P(object);
+ } else {
+ tmp_zval = *object;
+ zval_copy_ctor(&tmp_zval);
+ convert_to_string(&tmp_zval);
+ class_name = Z_STRVAL(tmp_zval);
+ class_name_len = Z_STRLEN(tmp_zval);
+ }
+
+ if ((class_name_len == sizeof("static") - 1) &&
+ (memcmp("static", class_name, sizeof("static") - 1) == 0)) {
+ obj_ce = mptr->common.scope;
+ }
+ else if (zend_lookup_class_ex(class_name, class_name_len, NULL, 1, &ce_p TSRMLS_CC) == FAILURE) {
+ zend_error(E_WARNING, "Class '%s' not found", class_name);
+ zval_dtor(&tmp_zval);
+ RETURN_NULL();
+ } else {
+ obj_ce = *ce_p;
+ }
+ zval_dtor(&tmp_zval);
+ }
object = NULL;
- obj_ce = mptr->common.scope;
} else {
if (!object) {
efree(params);
@@ -2966,11 +3034,12 @@ ZEND_METHOD(reflection_method, invokeArgs)
obj_ce = Z_OBJCE_P(object);
- if (!instanceof_function(obj_ce, mptr->common.scope TSRMLS_CC)) {
- efree(params);
- _DO_THROW("Given object is not an instance of the class this method was declared in");
+ /* This should not be required any more as you can invoke a method from any object. */
+ //if (!instanceof_function(obj_ce, mptr->common.scope TSRMLS_CC)) {
+ // efree(params);
+ // _DO_THROW("Given object is not an instance of the class this method was declared in");
/* Returns from this function */
- }
+ //}
}
fci.size = sizeof(fci);
@@ -2986,7 +3055,7 @@ ZEND_METHOD(reflection_method, invokeArgs)
fcc.initialized = 1;
fcc.function_handler = mptr;
fcc.calling_scope = obj_ce;
- fcc.called_scope = intern->ce;
+ fcc.called_scope = obj_ce;
fcc.object_ptr = object;
result = zend_call_function(&fci, &fcc TSRMLS_CC);
|