Skip to content

Commit 0e3045a

Browse files
committed
Store pointer to property_info in reflection
Instead of constructing a dummy property_info for dynamic properties, leave the field as NULL and handle this as appropriate. This was originally part of an alternative fix for bug #78774, but I think doing it this way is generally preferrable independently of that.
1 parent 7f9e739 commit 0e3045a

File tree

1 file changed

+40
-61
lines changed

1 file changed

+40
-61
lines changed

ext/reflection/php_reflection.c

Lines changed: 40 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,8 @@ PHPAPI zend_class_entry *reflection_reference_ptr;
112112

113113
/* Struct for properties */
114114
typedef struct _property_reference {
115-
zend_property_info prop;
115+
zend_property_info *prop;
116116
zend_string *unmangled_name;
117-
zend_bool dynamic;
118117
} property_reference;
119118

120119
/* Struct for parameters */
@@ -159,6 +158,10 @@ static inline reflection_object *reflection_object_from_obj(zend_object *obj) {
159158

160159
static zend_object_handlers reflection_object_handlers;
161160

161+
static uint32_t zend_always_inline prop_get_flags(property_reference *ref) {
162+
return ref->prop ? ref->prop->flags : ZEND_ACC_PUBLIC;
163+
}
164+
162165
static inline zend_bool is_closure_invoke(zend_class_entry *ce, zend_string *lcname) {
163166
return ce == zend_ce_closure
164167
&& zend_string_equals_literal(lcname, ZEND_INVOKE_FUNC_NAME);
@@ -280,7 +283,7 @@ static zval *reflection_instantiate(zend_class_entry *pce, zval *object) /* {{{
280283

281284
static void _const_string(smart_str *str, char *name, zval *value, char *indent);
282285
static void _function_string(smart_str *str, zend_function *fptr, zend_class_entry *scope, char* indent);
283-
static void _property_string(smart_str *str, zend_property_info *prop, const char *prop_name, char* indent, zend_bool dynamic);
286+
static void _property_string(smart_str *str, zend_property_info *prop, const char *prop_name, char* indent);
284287
static void _class_const_string(smart_str *str, char *name, zend_class_constant *c, char* indent);
285288
static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, char *indent);
286289
static void _extension_string(smart_str *str, zend_module_entry *module, char *indent);
@@ -395,7 +398,7 @@ static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, char
395398

396399
ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
397400
if ((prop->flags & ZEND_ACC_STATIC) && (!(prop->flags & ZEND_ACC_PRIVATE) || prop->ce == ce)) {
398-
_property_string(str, prop, NULL, ZSTR_VAL(sub_indent), 0);
401+
_property_string(str, prop, NULL, ZSTR_VAL(sub_indent));
399402
}
400403
} ZEND_HASH_FOREACH_END();
401404
}
@@ -443,7 +446,7 @@ static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, char
443446
ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
444447
if (!(prop->flags & ZEND_ACC_STATIC)
445448
&& (!(prop->flags & ZEND_ACC_PRIVATE) || prop->ce == ce)) {
446-
_property_string(str, prop, NULL, ZSTR_VAL(sub_indent), 0);
449+
_property_string(str, prop, NULL, ZSTR_VAL(sub_indent));
447450
}
448451
} ZEND_HASH_FOREACH_END();
449452
}
@@ -460,7 +463,7 @@ static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, char
460463
if (prop_name && ZSTR_LEN(prop_name) && ZSTR_VAL(prop_name)[0]) { /* skip all private and protected properties */
461464
if (!zend_hash_exists(&ce->properties_info, prop_name)) {
462465
count++;
463-
_property_string(&prop_str, NULL, ZSTR_VAL(prop_name), ZSTR_VAL(sub_indent), 0);
466+
_property_string(&prop_str, NULL, ZSTR_VAL(prop_name), ZSTR_VAL(sub_indent));
464467
}
465468
}
466469
} ZEND_HASH_FOREACH_END();
@@ -812,18 +815,14 @@ static void _function_string(smart_str *str, zend_function *fptr, zend_class_ent
812815
/* }}} */
813816

814817
/* {{{ _property_string */
815-
static void _property_string(smart_str *str, zend_property_info *prop, const char *prop_name, char* indent, zend_bool dynamic)
818+
static void _property_string(smart_str *str, zend_property_info *prop, const char *prop_name, char* indent)
816819
{
817820
smart_str_append_printf(str, "%sProperty [ ", indent);
818821
if (!prop) {
819822
smart_str_append_printf(str, "<dynamic> public $%s", prop_name);
820823
} else {
821824
if (!(prop->flags & ZEND_ACC_STATIC)) {
822-
if (dynamic) {
823-
smart_str_appends(str, "<implicit> ");
824-
} else {
825-
smart_str_appends(str, "<default> ");
826-
}
825+
smart_str_appends(str, "<default> ");
827826
}
828827

829828
/* These are mutually exclusive */
@@ -1192,12 +1191,12 @@ static void reflection_method_factory(zend_class_entry *ce, zend_function *metho
11921191
/* }}} */
11931192

11941193
/* {{{ reflection_property_factory */
1195-
static void reflection_property_factory(zend_class_entry *ce, zend_string *name, zend_property_info *prop, zval *object, zend_bool dynamic)
1194+
static void reflection_property_factory(zend_class_entry *ce, zend_string *name, zend_property_info *prop, zval *object)
11961195
{
11971196
reflection_object *intern;
11981197
property_reference *reference;
11991198

1200-
if (!(prop->flags & ZEND_ACC_PRIVATE)) {
1199+
if (!prop || !(prop->flags & ZEND_ACC_PRIVATE)) {
12011200
/* we have to search the class hierarchy for this (implicit) public or protected property */
12021201
zend_class_entry *tmp_ce = ce, *store_ce = ce;
12031202
zend_property_info *tmp_info = NULL;
@@ -1217,22 +1216,21 @@ static void reflection_property_factory(zend_class_entry *ce, zend_string *name,
12171216
reflection_instantiate(reflection_property_ptr, object);
12181217
intern = Z_REFLECTION_P(object);
12191218
reference = (property_reference*) emalloc(sizeof(property_reference));
1220-
reference->prop = *prop;
1219+
reference->prop = prop;
12211220
reference->unmangled_name = zend_string_copy(name);
1222-
reference->dynamic = dynamic;
12231221
intern->ptr = reference;
12241222
intern->ref_type = REF_TYPE_PROPERTY;
12251223
intern->ce = ce;
12261224
intern->ignore_visibility = 0;
12271225
ZVAL_STR_COPY(reflection_prop_name(object), name);
1228-
ZVAL_STR_COPY(reflection_prop_class(object), prop->ce->name);
1226+
ZVAL_STR_COPY(reflection_prop_class(object), prop ? prop->ce->name : ce->name);
12291227
}
12301228
/* }}} */
12311229

12321230
static void reflection_property_factory_str(zend_class_entry *ce, const char *name_str, size_t name_len, zend_property_info *prop, zval *object)
12331231
{
12341232
zend_string *name = zend_string_init(name_str, name_len, 0);
1235-
reflection_property_factory(ce, name, prop, object, 0);
1233+
reflection_property_factory(ce, name, prop, object);
12361234
zend_string_release(name);
12371235
}
12381236

@@ -4212,19 +4210,13 @@ ZEND_METHOD(reflection_class, getProperty)
42124210
GET_REFLECTION_OBJECT_PTR(ce);
42134211
if ((property_info = zend_hash_find_ptr(&ce->properties_info, name)) != NULL) {
42144212
if (!(property_info->flags & ZEND_ACC_PRIVATE) || property_info->ce == ce) {
4215-
reflection_property_factory(ce, name, property_info, return_value, 0);
4213+
reflection_property_factory(ce, name, property_info, return_value);
42164214
return;
42174215
}
42184216
} else if (Z_TYPE(intern->obj) != IS_UNDEF) {
42194217
/* Check for dynamic properties */
42204218
if (zend_hash_exists(Z_OBJ_HT(intern->obj)->get_properties(Z_OBJ(intern->obj)), name)) {
4221-
zend_property_info property_info_tmp;
4222-
property_info_tmp.flags = ZEND_ACC_PUBLIC;
4223-
property_info_tmp.name = name;
4224-
property_info_tmp.doc_comment = NULL;
4225-
property_info_tmp.ce = ce;
4226-
4227-
reflection_property_factory(ce, name, &property_info_tmp, return_value, 1);
4219+
reflection_property_factory(ce, name, NULL, return_value);
42284220
return;
42294221
}
42304222
}
@@ -4275,7 +4267,7 @@ static void _addproperty(zend_property_info *pptr, zend_string *key, zend_class_
42754267

42764268
if (pptr->flags & filter) {
42774269
zval property;
4278-
reflection_property_factory(ce, key, pptr, &property, 0);
4270+
reflection_property_factory(ce, key, pptr, &property);
42794271
add_next_index_zval(retval, &property);
42804272
}
42814273
}
@@ -4284,7 +4276,6 @@ static void _addproperty(zend_property_info *pptr, zend_string *key, zend_class_
42844276
/* {{{ _adddynproperty */
42854277
static void _adddynproperty(zval *ptr, zend_string *key, zend_class_entry *ce, zval *retval)
42864278
{
4287-
zend_property_info property_info;
42884279
zval property;
42894280

42904281
/* under some circumstances, the properties hash table may contain numeric
@@ -4299,12 +4290,7 @@ static void _adddynproperty(zval *ptr, zend_string *key, zend_class_entry *ce, z
42994290
return;
43004291
}
43014292

4302-
property_info.doc_comment = NULL;
4303-
property_info.flags = ZEND_ACC_PUBLIC;
4304-
property_info.name = key;
4305-
property_info.ce = ce;
4306-
property_info.offset = -1;
4307-
reflection_property_factory(ce, key, &property_info, &property, 1);
4293+
reflection_property_factory(ce, key, NULL, &property);
43084294
add_next_index_zval(retval, &property);
43094295
}
43104296
/* }}} */
@@ -5281,16 +5267,7 @@ ZEND_METHOD(reflection_property, __construct)
52815267
}
52825268

52835269
reference = (property_reference*) emalloc(sizeof(property_reference));
5284-
if (dynam_prop) {
5285-
reference->prop.flags = ZEND_ACC_PUBLIC;
5286-
reference->prop.name = name;
5287-
reference->prop.doc_comment = NULL;
5288-
reference->prop.ce = ce;
5289-
reference->dynamic = 1;
5290-
} else {
5291-
reference->prop = *property_info;
5292-
reference->dynamic = 0;
5293-
}
5270+
reference->prop = dynam_prop ? NULL : property_info;
52945271
reference->unmangled_name = zend_string_copy(name);
52955272
intern->ptr = reference;
52965273
intern->ref_type = REF_TYPE_PROPERTY;
@@ -5311,7 +5288,7 @@ ZEND_METHOD(reflection_property, __toString)
53115288
return;
53125289
}
53135290
GET_REFLECTION_OBJECT_PTR(ref);
5314-
_property_string(&str, &ref->prop, ZSTR_VAL(ref->unmangled_name), "", ref->dynamic);
5291+
_property_string(&str, ref->prop, ZSTR_VAL(ref->unmangled_name), "");
53155292
RETURN_STR(smart_str_extract(&str));
53165293
}
53175294
/* }}} */
@@ -5336,7 +5313,7 @@ static void _property_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask) /* {{{
53365313
return;
53375314
}
53385315
GET_REFLECTION_OBJECT_PTR(ref);
5339-
RETURN_BOOL(ref->prop.flags & mask);
5316+
RETURN_BOOL(prop_get_flags(ref) & mask);
53405317
}
53415318
/* }}} */
53425319

@@ -5383,7 +5360,7 @@ ZEND_METHOD(reflection_property, isDefault)
53835360
return;
53845361
}
53855362
GET_REFLECTION_OBJECT_PTR(ref);
5386-
RETURN_BOOL(!ref->dynamic);
5363+
RETURN_BOOL(ref->prop != NULL);
53875364
}
53885365
/* }}} */
53895366

@@ -5400,7 +5377,7 @@ ZEND_METHOD(reflection_property, getModifiers)
54005377
}
54015378
GET_REFLECTION_OBJECT_PTR(ref);
54025379

5403-
RETURN_LONG((ref->prop.flags & keep_flags));
5380+
RETURN_LONG(prop_get_flags(ref) & keep_flags);
54045381
}
54055382
/* }}} */
54065383

@@ -5415,14 +5392,14 @@ ZEND_METHOD(reflection_property, getValue)
54155392

54165393
GET_REFLECTION_OBJECT_PTR(ref);
54175394

5418-
if (!(ref->prop.flags & ZEND_ACC_PUBLIC) && intern->ignore_visibility == 0) {
5395+
if (!(prop_get_flags(ref) & ZEND_ACC_PUBLIC) && intern->ignore_visibility == 0) {
54195396
name = _default_load_name(ZEND_THIS);
54205397
zend_throw_exception_ex(reflection_exception_ptr, 0,
54215398
"Cannot access non-public member %s::$%s", ZSTR_VAL(intern->ce->name), Z_STRVAL_P(name));
54225399
return;
54235400
}
54245401

5425-
if (ref->prop.flags & ZEND_ACC_STATIC) {
5402+
if (prop_get_flags(ref) & ZEND_ACC_STATIC) {
54265403
member_p = zend_read_static_property_ex(intern->ce, ref->unmangled_name, 0);
54275404
if (member_p) {
54285405
ZVAL_COPY_DEREF(return_value, member_p);
@@ -5434,7 +5411,8 @@ ZEND_METHOD(reflection_property, getValue)
54345411
return;
54355412
}
54365413

5437-
if (!instanceof_function(Z_OBJCE_P(object), ref->prop.ce)) {
5414+
/* TODO: Should this always use intern->ce? */
5415+
if (!instanceof_function(Z_OBJCE_P(object), ref->prop ? ref->prop->ce : intern->ce)) {
54385416
_DO_THROW("Given object is not an instance of the class this property was declared in");
54395417
return;
54405418
}
@@ -5464,14 +5442,14 @@ ZEND_METHOD(reflection_property, setValue)
54645442

54655443
GET_REFLECTION_OBJECT_PTR(ref);
54665444

5467-
if (!(ref->prop.flags & ZEND_ACC_PUBLIC) && intern->ignore_visibility == 0) {
5445+
if (!(prop_get_flags(ref) & ZEND_ACC_PUBLIC) && intern->ignore_visibility == 0) {
54685446
name = _default_load_name(ZEND_THIS);
54695447
zend_throw_exception_ex(reflection_exception_ptr, 0,
54705448
"Cannot access non-public member %s::$%s", ZSTR_VAL(intern->ce->name), Z_STRVAL_P(name));
54715449
return;
54725450
}
54735451

5474-
if (ref->prop.flags & ZEND_ACC_STATIC) {
5452+
if (prop_get_flags(ref) & ZEND_ACC_STATIC) {
54755453
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "z", &value) == FAILURE) {
54765454
if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &tmp, &value) == FAILURE) {
54775455
return;
@@ -5500,14 +5478,14 @@ ZEND_METHOD(reflection_property, isInitialized)
55005478

55015479
GET_REFLECTION_OBJECT_PTR(ref);
55025480

5503-
if (!(ref->prop.flags & ZEND_ACC_PUBLIC) && intern->ignore_visibility == 0) {
5481+
if (!(prop_get_flags(ref) & ZEND_ACC_PUBLIC) && intern->ignore_visibility == 0) {
55045482
name = _default_load_name(getThis());
55055483
zend_throw_exception_ex(reflection_exception_ptr, 0,
55065484
"Cannot access non-public member %s::$%s", ZSTR_VAL(intern->ce->name), Z_STRVAL_P(name));
55075485
return;
55085486
}
55095487

5510-
if (ref->prop.flags & ZEND_ACC_STATIC) {
5488+
if (prop_get_flags(ref) & ZEND_ACC_STATIC) {
55115489
member_p = zend_read_static_property_ex(intern->ce, ref->unmangled_name, 1);
55125490
if (member_p) {
55135491
RETURN_BOOL(!Z_ISUNDEF_P(member_p));
@@ -5521,7 +5499,8 @@ ZEND_METHOD(reflection_property, isInitialized)
55215499
return;
55225500
}
55235501

5524-
if (!instanceof_function(Z_OBJCE_P(object), ref->prop.ce)) {
5502+
/* TODO: Should this always use intern->ce? */
5503+
if (!instanceof_function(Z_OBJCE_P(object), ref->prop ? ref->prop->ce : intern->ce)) {
55255504
_DO_THROW("Given object is not an instance of the class this property was declared in");
55265505
return;
55275506
}
@@ -5579,8 +5558,8 @@ ZEND_METHOD(reflection_property, getDocComment)
55795558
return;
55805559
}
55815560
GET_REFLECTION_OBJECT_PTR(ref);
5582-
if (ref->prop.doc_comment) {
5583-
RETURN_STR_COPY(ref->prop.doc_comment);
5561+
if (ref->prop && ref->prop->doc_comment) {
5562+
RETURN_STR_COPY(ref->prop->doc_comment);
55845563
}
55855564
RETURN_FALSE;
55865565
}
@@ -5616,11 +5595,11 @@ ZEND_METHOD(reflection_property, getType)
56165595

56175596
GET_REFLECTION_OBJECT_PTR(ref);
56185597

5619-
if (!ZEND_TYPE_IS_SET(ref->prop.type)) {
5598+
if (!ref->prop || !ZEND_TYPE_IS_SET(ref->prop->type)) {
56205599
RETURN_NULL();
56215600
}
56225601

5623-
reflection_type_factory(ref->prop.type, return_value);
5602+
reflection_type_factory(ref->prop->type, return_value);
56245603
}
56255604
/* }}} */
56265605

@@ -5637,7 +5616,7 @@ ZEND_METHOD(reflection_property, hasType)
56375616

56385617
GET_REFLECTION_OBJECT_PTR(ref);
56395618

5640-
RETVAL_BOOL(ZEND_TYPE_IS_SET(ref->prop.type));
5619+
RETVAL_BOOL(ref->prop && ZEND_TYPE_IS_SET(ref->prop->type));
56415620
}
56425621
/* }}} */
56435622

0 commit comments

Comments
 (0)