Refactor ReflectionMethod::__construct()

Closes GH-6098
This commit is contained in:
Máté Kocsis 2020-09-09 02:21:51 +02:00
parent f33fd9b7fe
commit a59923befd
No known key found for this signature in database
GPG key ID: FD055E41728BF310
7 changed files with 76 additions and 75 deletions

View file

@ -2976,81 +2976,83 @@ ZEND_METHOD(ReflectionUnionType, getTypes)
/* {{{ Constructor. Throws an Exception in case the given method does not exist */
ZEND_METHOD(ReflectionMethod, __construct)
{
zval *classname;
zval *object, *orig_obj;
reflection_object *intern;
char *lcname;
zend_class_entry *ce;
zend_function *mptr;
char *name_str, *tmp;
size_t name_len, tmp_len;
zval ztmp;
zend_object *arg1_obj;
zend_string *arg1_str;
zend_string *arg2_str = NULL;
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "zs", &classname, &name_str, &name_len) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name_str, &name_len) == FAILURE) {
zend_object *orig_obj = NULL;
zend_class_entry *ce = NULL;
zend_string *class_name = NULL;
char *method_name;
size_t method_name_len;
char *lcname;
zval *object;
reflection_object *intern;
zend_function *mptr;
ZEND_PARSE_PARAMETERS_START(1, 2)
Z_PARAM_STR_OR_OBJ(arg1_str, arg1_obj)
Z_PARAM_OPTIONAL
Z_PARAM_STR_OR_NULL(arg2_str)
ZEND_PARSE_PARAMETERS_END();
if (arg1_obj) {
if (!arg2_str) {
zend_argument_value_error(2, "cannot be null when argument #1 ($objectOrMethod) is an object");
RETURN_THROWS();
}
if ((tmp = strstr(name_str, "::")) == NULL) {
orig_obj = arg1_obj;
ce = arg1_obj->ce;
method_name = ZSTR_VAL(arg2_str);
method_name_len = ZSTR_LEN(arg2_str);
} else if (arg2_str) {
class_name = zend_string_copy(arg1_str);
method_name = ZSTR_VAL(arg2_str);
method_name_len = ZSTR_LEN(arg2_str);
} else {
char *tmp;
size_t tmp_len;
char *name = ZSTR_VAL(arg1_str);
if ((tmp = strstr(name, "::")) == NULL) {
zend_argument_error(reflection_exception_ptr, 1, "must be a valid method name");
RETURN_THROWS();
}
classname = &ztmp;
tmp_len = tmp - name_str;
ZVAL_STRINGL(classname, name_str, tmp_len);
name_len = name_len - (tmp_len + 2);
name_str = tmp + 2;
orig_obj = NULL;
} else if (Z_TYPE_P(classname) == IS_OBJECT) {
orig_obj = classname;
} else {
orig_obj = NULL;
tmp_len = tmp - name;
class_name = zend_string_init(name, tmp_len, 0);
method_name = tmp + 2;
method_name_len = ZSTR_LEN(arg1_str) - tmp_len - 2;
}
if (class_name) {
if ((ce = zend_lookup_class(class_name)) == NULL) {
if (!EG(exception)) {
zend_throw_exception_ex(reflection_exception_ptr, 0, "Class \"%s\" does not exist", ZSTR_VAL(class_name));
}
zend_string_release(class_name);
RETURN_THROWS();
}
zend_string_release(class_name);
}
object = ZEND_THIS;
intern = Z_REFLECTION_P(object);
switch (Z_TYPE_P(classname)) {
case IS_STRING:
if ((ce = zend_lookup_class(Z_STR_P(classname))) == NULL) {
if (!EG(exception)) {
zend_throw_exception_ex(reflection_exception_ptr, 0,
"Class \"%s\" does not exist", Z_STRVAL_P(classname));
}
if (classname == &ztmp) {
zval_ptr_dtor_str(&ztmp);
}
RETURN_THROWS();
}
break;
lcname = zend_str_tolower_dup(method_name, method_name_len);
case IS_OBJECT:
ce = Z_OBJCE_P(classname);
break;
default:
if (classname == &ztmp) {
zval_ptr_dtor_str(&ztmp);
}
zend_argument_error(reflection_exception_ptr, 1, "must be of type object|string, %s given", zend_zval_type_name(classname));
RETURN_THROWS();
}
if (classname == &ztmp) {
zval_ptr_dtor_str(&ztmp);
}
lcname = zend_str_tolower_dup(name_str, name_len);
if (ce == zend_ce_closure && orig_obj && (name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
if (ce == zend_ce_closure && orig_obj && (method_name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
&& memcmp(lcname, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
&& (mptr = zend_get_closure_invoke_method(Z_OBJ_P(orig_obj))) != NULL)
&& (mptr = zend_get_closure_invoke_method(orig_obj)) != NULL)
{
/* do nothing, mptr already set */
} else if ((mptr = zend_hash_str_find_ptr(&ce->function_table, lcname, name_len)) == NULL) {
} else if ((mptr = zend_hash_str_find_ptr(&ce->function_table, lcname, method_name_len)) == NULL) {
efree(lcname);
zend_throw_exception_ex(reflection_exception_ptr, 0,
"Method %s::%s() does not exist", ZSTR_VAL(ce->name), name_str);
"Method %s::%s() does not exist", ZSTR_VAL(ce->name), method_name);
RETURN_THROWS();
}
efree(lcname);