Skip to content

Commit 8664ff7

Browse files
committed
Cleanup argument handling in ext/reflection
Closes GH-5850
1 parent 1f8a93a commit 8664ff7

15 files changed

+204
-248
lines changed

Zend/zend_closures.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -394,9 +394,9 @@ ZEND_API zend_function *zend_get_closure_invoke_method(zend_object *object) /* {
394394
}
395395
/* }}} */
396396

397-
ZEND_API const zend_function *zend_get_closure_method_def(zval *obj) /* {{{ */
397+
ZEND_API const zend_function *zend_get_closure_method_def(zend_object *obj) /* {{{ */
398398
{
399-
zend_closure *closure = (zend_closure *)Z_OBJ_P(obj);
399+
zend_closure *closure = (zend_closure *) obj;
400400
return &closure->func;
401401
}
402402
/* }}} */

Zend/zend_closures.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ extern ZEND_API zend_class_entry *zend_ce_closure;
3535
ZEND_API void zend_create_closure(zval *res, zend_function *op_array, zend_class_entry *scope, zend_class_entry *called_scope, zval *this_ptr);
3636
ZEND_API void zend_create_fake_closure(zval *res, zend_function *op_array, zend_class_entry *scope, zend_class_entry *called_scope, zval *this_ptr);
3737
ZEND_API zend_function *zend_get_closure_invoke_method(zend_object *obj);
38-
ZEND_API const zend_function *zend_get_closure_method_def(zval *obj);
38+
ZEND_API const zend_function *zend_get_closure_method_def(zend_object *obj);
3939
ZEND_API zval* zend_get_closure_this_ptr(zval *obj);
4040

4141
END_EXTERN_C()

ext/reflection/php_reflection.c

+83-116
Original file line numberDiff line numberDiff line change
@@ -1480,25 +1480,24 @@ ZEND_METHOD(Reflection, getModifierNames)
14801480
ZEND_METHOD(ReflectionFunction, __construct)
14811481
{
14821482
zval *object;
1483-
zval *closure = NULL;
1483+
zend_object *closure_obj = NULL;
14841484
reflection_object *intern;
14851485
zend_function *fptr;
14861486
zend_string *fname, *lcname;
14871487

14881488
object = ZEND_THIS;
14891489
intern = Z_REFLECTION_P(object);
14901490

1491-
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "O", &closure, zend_ce_closure) == SUCCESS) {
1492-
fptr = (zend_function*)zend_get_closure_method_def(closure);
1493-
} else {
1494-
ALLOCA_FLAG(use_heap)
1495-
1496-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &fname) == FAILURE) {
1497-
RETURN_THROWS();
1498-
}
1491+
ZEND_PARSE_PARAMETERS_START(1, 1)
1492+
Z_PARAM_STR_OR_OBJ_OF_CLASS(fname, closure_obj, zend_ce_closure)
1493+
ZEND_PARSE_PARAMETERS_END();
14991494

1495+
if (closure_obj) {
1496+
fptr = (zend_function*)zend_get_closure_method_def(closure_obj);
1497+
} else {
15001498
if (UNEXPECTED(ZSTR_VAL(fname)[0] == '\\')) {
15011499
/* Ignore leading "\" */
1500+
ALLOCA_FLAG(use_heap)
15021501
ZSTR_ALLOCA_ALLOC(lcname, ZSTR_LEN(fname) - 1, use_heap);
15031502
zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(fname) + 1, ZSTR_LEN(fname) - 1);
15041503
fptr = zend_fetch_function(lcname);
@@ -1519,8 +1518,8 @@ ZEND_METHOD(ReflectionFunction, __construct)
15191518
ZVAL_STR_COPY(reflection_prop_name(object), fptr->common.function_name);
15201519
intern->ptr = fptr;
15211520
intern->ref_type = REF_TYPE_FUNCTION;
1522-
if (closure) {
1523-
ZVAL_OBJ_COPY(&intern->obj, Z_OBJ_P(closure));
1521+
if (closure_obj) {
1522+
ZVAL_OBJ_COPY(&intern->obj, closure_obj);
15241523
} else {
15251524
ZVAL_UNDEF(&intern->obj);
15261525
}
@@ -1603,7 +1602,7 @@ ZEND_METHOD(ReflectionFunctionAbstract, getClosureScopeClass)
16031602
}
16041603
GET_REFLECTION_OBJECT();
16051604
if (!Z_ISUNDEF(intern->obj)) {
1606-
closure_func = zend_get_closure_method_def(&intern->obj);
1605+
closure_func = zend_get_closure_method_def(Z_OBJ(intern->obj));
16071606
if (closure_func && closure_func->common.scope) {
16081607
zend_reflection_class_factory(closure_func->common.scope, return_value);
16091608
}
@@ -2315,7 +2314,7 @@ ZEND_METHOD(ReflectionParameter, __construct)
23152314
ce = Z_OBJCE_P(reference);
23162315

23172316
if (instanceof_function(ce, zend_ce_closure)) {
2318-
fptr = (zend_function *)zend_get_closure_method_def(reference);
2317+
fptr = (zend_function *)zend_get_closure_method_def(Z_OBJ_P(reference));
23192318
Z_ADDREF_P(reference);
23202319
is_closure = 1;
23212320
} else if ((fptr = zend_hash_find_ptr(&ce->function_table, ZSTR_KNOWN(ZEND_STR_MAGIC_INVOKE))) == NULL) {
@@ -3017,7 +3016,6 @@ ZEND_METHOD(ReflectionMethod, __construct)
30173016
object = ZEND_THIS;
30183017
intern = Z_REFLECTION_P(object);
30193018

3020-
/* Find the class entry */
30213019
switch (Z_TYPE_P(classname)) {
30223020
case IS_STRING:
30233021
if ((ce = zend_lookup_class(Z_STR_P(classname))) == NULL) {
@@ -3519,38 +3517,31 @@ ZEND_METHOD(ReflectionMethod, setAccessible)
35193517
/* {{{ Constructor. Throws an Exception in case the given class constant does not exist */
35203518
ZEND_METHOD(ReflectionClassConstant, __construct)
35213519
{
3522-
zval *classname, *object;
3520+
zval *object;
3521+
zend_string *classname_str;
3522+
zend_object *classname_obj;
35233523
zend_string *constname;
35243524
reflection_object *intern;
35253525
zend_class_entry *ce;
35263526
zend_class_constant *constant = NULL;
35273527

3528-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "zS", &classname, &constname) == FAILURE) {
3529-
RETURN_THROWS();
3528+
ZEND_PARSE_PARAMETERS_START(2, 2)
3529+
Z_PARAM_STR_OR_OBJ(classname_str, classname_obj)
3530+
Z_PARAM_STR(constname)
3531+
ZEND_PARSE_PARAMETERS_END();
3532+
3533+
if (classname_obj) {
3534+
ce = classname_obj->ce;
3535+
} else {
3536+
if ((ce = zend_lookup_class(classname_str)) == NULL) {
3537+
zend_throw_exception_ex(reflection_exception_ptr, 0, "Class \"%s\" does not exist", ZSTR_VAL(classname_str));
3538+
RETURN_THROWS();
3539+
}
35303540
}
35313541

35323542
object = ZEND_THIS;
35333543
intern = Z_REFLECTION_P(object);
35343544

3535-
/* Find the class entry */
3536-
switch (Z_TYPE_P(classname)) {
3537-
case IS_STRING:
3538-
if ((ce = zend_lookup_class(Z_STR_P(classname))) == NULL) {
3539-
zend_throw_exception_ex(reflection_exception_ptr, 0,
3540-
"Class \"%s\" does not exist", Z_STRVAL_P(classname));
3541-
RETURN_THROWS();
3542-
}
3543-
break;
3544-
3545-
case IS_OBJECT:
3546-
ce = Z_OBJCE_P(classname);
3547-
break;
3548-
3549-
default:
3550-
zend_argument_error(reflection_exception_ptr, 1, "must be of type object|string, %s given", zend_zval_type_name(classname));
3551-
RETURN_THROWS();
3552-
}
3553-
35543545
if ((constant = zend_hash_find_ptr(&ce->constants_table, constname)) == NULL) {
35553546
zend_throw_exception_ex(reflection_exception_ptr, 0, "Constant %s::%s does not exist", ZSTR_VAL(ce->name), ZSTR_VAL(constname));
35563547
RETURN_THROWS();
@@ -3814,7 +3805,7 @@ ZEND_METHOD(ReflectionClass, getStaticProperties)
38143805
GET_REFLECTION_OBJECT_PTR(ce);
38153806

38163807
if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
3817-
return;
3808+
RETURN_THROWS();
38183809
}
38193810

38203811
if (ce->default_static_members_count && !CE_STATIC_MEMBERS(ce)) {
@@ -3863,7 +3854,7 @@ ZEND_METHOD(ReflectionClass, getStaticPropertyValue)
38633854
GET_REFLECTION_OBJECT_PTR(ce);
38643855

38653856
if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
3866-
return;
3857+
RETURN_THROWS();
38673858
}
38683859

38693860
old_scope = EG(fake_scope);
@@ -3901,7 +3892,7 @@ ZEND_METHOD(ReflectionClass, setStaticPropertyValue)
39013892
GET_REFLECTION_OBJECT_PTR(ce);
39023893

39033894
if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
3904-
return;
3895+
RETURN_THROWS();
39053896
}
39063897
old_scope = EG(fake_scope);
39073898
EG(fake_scope) = ce;
@@ -3945,7 +3936,7 @@ ZEND_METHOD(ReflectionClass, getDefaultProperties)
39453936
GET_REFLECTION_OBJECT_PTR(ce);
39463937
array_init(return_value);
39473938
if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
3948-
return;
3939+
RETURN_THROWS();
39493940
}
39503941
add_class_vars(ce, 1, return_value);
39513942
add_class_vars(ce, 0, return_value);
@@ -4967,38 +4958,30 @@ ZEND_METHOD(ReflectionClass, isSubclassOf)
49674958
{
49684959
reflection_object *intern, *argument;
49694960
zend_class_entry *ce, *class_ce;
4970-
zval *class_name;
4961+
zend_string *class_str;
4962+
zend_object *class_obj;
49714963

4972-
GET_REFLECTION_OBJECT_PTR(ce);
4964+
ZEND_PARSE_PARAMETERS_START(1, 1)
4965+
Z_PARAM_STR_OR_OBJ_OF_CLASS(class_str, class_obj, reflection_class_ptr)
4966+
ZEND_PARSE_PARAMETERS_END();
49734967

4974-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &class_name) == FAILURE) {
4975-
RETURN_THROWS();
4976-
}
4968+
if (class_obj) {
4969+
argument = reflection_object_from_obj(class_obj);
4970+
if (argument->ptr == NULL) {
4971+
zend_throw_error(NULL, "Internal error: Failed to retrieve the argument's reflection object");
4972+
RETURN_THROWS();
4973+
}
49774974

4978-
switch (Z_TYPE_P(class_name)) {
4979-
case IS_STRING:
4980-
if ((class_ce = zend_lookup_class(Z_STR_P(class_name))) == NULL) {
4981-
zend_throw_exception_ex(reflection_exception_ptr, 0,
4982-
"Class \"%s\" does not exist", Z_STRVAL_P(class_name));
4983-
RETURN_THROWS();
4984-
}
4985-
break;
4986-
case IS_OBJECT:
4987-
if (instanceof_function(Z_OBJCE_P(class_name), reflection_class_ptr)) {
4988-
argument = Z_REFLECTION_P(class_name);
4989-
if (argument->ptr == NULL) {
4990-
zend_throw_error(NULL, "Internal error: Failed to retrieve the argument's reflection object");
4991-
RETURN_THROWS();
4992-
}
4993-
class_ce = argument->ptr;
4994-
break;
4995-
}
4996-
/* no break */
4997-
default:
4998-
zend_argument_error(reflection_exception_ptr, 1, "must be of type ReflectionClass|string, %s given", zend_zval_type_name(class_name));
4975+
class_ce = argument->ptr;
4976+
} else {
4977+
if ((class_ce = zend_lookup_class(class_str)) == NULL) {
4978+
zend_throw_exception_ex(reflection_exception_ptr, 0, "Class \"%s\" does not exist", ZSTR_VAL(class_str));
49994979
RETURN_THROWS();
4980+
}
50004981
}
50014982

4983+
GET_REFLECTION_OBJECT_PTR(ce);
4984+
50024985
RETURN_BOOL((ce != class_ce && instanceof_function(ce, class_ce)));
50034986
}
50044987
/* }}} */
@@ -5007,44 +4990,36 @@ ZEND_METHOD(ReflectionClass, isSubclassOf)
50074990
ZEND_METHOD(ReflectionClass, implementsInterface)
50084991
{
50094992
reflection_object *intern, *argument;
4993+
zend_string *interface_str;
50104994
zend_class_entry *ce, *interface_ce;
5011-
zval *interface;
4995+
zend_object *interface_obj;
50124996

5013-
GET_REFLECTION_OBJECT_PTR(ce);
4997+
ZEND_PARSE_PARAMETERS_START(1, 1)
4998+
Z_PARAM_STR_OR_OBJ_OF_CLASS(interface_str, interface_obj, reflection_class_ptr)
4999+
ZEND_PARSE_PARAMETERS_END();
50145000

5015-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &interface) == FAILURE) {
5016-
RETURN_THROWS();
5017-
}
5001+
if (interface_obj) {
5002+
argument = reflection_object_from_obj(interface_obj);
5003+
if (argument->ptr == NULL) {
5004+
zend_throw_error(NULL, "Internal error: Failed to retrieve the argument's reflection object");
5005+
RETURN_THROWS();
5006+
}
50185007

5019-
switch (Z_TYPE_P(interface)) {
5020-
case IS_STRING:
5021-
if ((interface_ce = zend_lookup_class(Z_STR_P(interface))) == NULL) {
5022-
zend_throw_exception_ex(reflection_exception_ptr, 0,
5023-
"Interface \"%s\" does not exist", Z_STRVAL_P(interface));
5024-
RETURN_THROWS();
5025-
}
5026-
break;
5027-
case IS_OBJECT:
5028-
if (instanceof_function(Z_OBJCE_P(interface), reflection_class_ptr)) {
5029-
argument = Z_REFLECTION_P(interface);
5030-
if (argument->ptr == NULL) {
5031-
zend_throw_error(NULL, "Internal error: Failed to retrieve the argument's reflection object");
5032-
RETURN_THROWS();
5033-
}
5034-
interface_ce = argument->ptr;
5035-
break;
5036-
}
5037-
/* no break */
5038-
default:
5039-
zend_argument_error(reflection_exception_ptr, 1, "must be of type ReflectionClass|string, %s given", zend_zval_type_name(interface));
5008+
interface_ce = argument->ptr;
5009+
} else {
5010+
if ((interface_ce = zend_lookup_class(interface_str)) == NULL) {
5011+
zend_throw_exception_ex(reflection_exception_ptr, 0, "Interface \"%s\" does not exist", ZSTR_VAL(interface_str));
50405012
RETURN_THROWS();
5013+
}
50415014
}
50425015

50435016
if (!(interface_ce->ce_flags & ZEND_ACC_INTERFACE)) {
5044-
zend_throw_exception_ex(reflection_exception_ptr, 0,
5045-
"%s is not an interface", ZSTR_VAL(interface_ce->name));
5017+
zend_throw_exception_ex(reflection_exception_ptr, 0, "%s is not an interface", ZSTR_VAL(interface_ce->name));
50465018
RETURN_THROWS();
50475019
}
5020+
5021+
GET_REFLECTION_OBJECT_PTR(ce);
5022+
50485023
RETURN_BOOL(instanceof_function(ce, interface_ce));
50495024
}
50505025
/* }}} */
@@ -5178,7 +5153,8 @@ ZEND_METHOD(ReflectionObject, __construct)
51785153
/* {{{ Constructor. Throws an Exception in case the given property does not exist */
51795154
ZEND_METHOD(ReflectionProperty, __construct)
51805155
{
5181-
zval *classname;
5156+
zend_string *classname_str;
5157+
zend_object *classname_obj;
51825158
zend_string *name;
51835159
int dynam_prop = 0;
51845160
zval *object;
@@ -5187,39 +5163,30 @@ ZEND_METHOD(ReflectionProperty, __construct)
51875163
zend_property_info *property_info = NULL;
51885164
property_reference *reference;
51895165

5190-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "zS", &classname, &name) == FAILURE) {
5191-
RETURN_THROWS();
5192-
}
5166+
ZEND_PARSE_PARAMETERS_START(2, 2)
5167+
Z_PARAM_STR_OR_OBJ(classname_str, classname_obj)
5168+
Z_PARAM_STR(name)
5169+
ZEND_PARSE_PARAMETERS_END();
51935170

51945171
object = ZEND_THIS;
51955172
intern = Z_REFLECTION_P(object);
51965173

5197-
/* Find the class entry */
5198-
switch (Z_TYPE_P(classname)) {
5199-
case IS_STRING:
5200-
if ((ce = zend_lookup_class(Z_STR_P(classname))) == NULL) {
5201-
zend_throw_exception_ex(reflection_exception_ptr, 0,
5202-
"Class \"%s\" does not exist", Z_STRVAL_P(classname));
5203-
RETURN_THROWS();
5204-
}
5205-
break;
5206-
5207-
case IS_OBJECT:
5208-
ce = Z_OBJCE_P(classname);
5209-
break;
5210-
5211-
default:
5212-
zend_argument_error(reflection_exception_ptr, 1, "must be of type object|string, %s given", zend_zval_type_name(classname));
5174+
if (classname_obj) {
5175+
ce = classname_obj->ce;
5176+
} else {
5177+
if ((ce = zend_lookup_class(classname_str)) == NULL) {
5178+
zend_throw_exception_ex(reflection_exception_ptr, 0, "Class \"%s\" does not exist", ZSTR_VAL(classname_str));
52135179
RETURN_THROWS();
5180+
}
52145181
}
52155182

52165183
property_info = zend_hash_find_ptr(&ce->properties_info, name);
52175184
if (property_info == NULL
52185185
|| ((property_info->flags & ZEND_ACC_PRIVATE)
52195186
&& property_info->ce != ce)) {
52205187
/* Check for dynamic properties */
5221-
if (property_info == NULL && Z_TYPE_P(classname) == IS_OBJECT) {
5222-
if (zend_hash_exists(Z_OBJ_HT_P(classname)->get_properties(Z_OBJ_P(classname)), name)) {
5188+
if (property_info == NULL && classname_obj) {
5189+
if (zend_hash_exists(classname_obj->handlers->get_properties(classname_obj), name)) {
52235190
dynam_prop = 1;
52245191
}
52255192
}

0 commit comments

Comments
 (0)