Skip to content

Commit 9104f15

Browse files
committed
Expose zend_reflection_property_set_raw_value, zend_reflection_property_set_raw_value_without_lazy_initialization
1 parent 1195f27 commit 9104f15

File tree

2 files changed

+84
-49
lines changed

2 files changed

+84
-49
lines changed

ext/reflection/php_reflection.c

Lines changed: 72 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -6013,11 +6013,11 @@ ZEND_METHOD(ReflectionProperty, setValue)
60136013
* 'scope' on 'object'. The result may be different from 'ref->prop' when the
60146014
* property is overridden on 'object' and was not private in 'scope'.
60156015
* The effective prop may add hooks or change flags. */
6016-
static zend_property_info *reflection_property_get_effective_prop(
6017-
property_reference *ref, zend_class_entry *scope, zend_object *object) {
6018-
zend_property_info *prop = ref->prop;
6016+
static const zend_property_info *reflection_property_get_effective_prop(
6017+
const zend_property_info *prop, zend_string *unmangled_name,
6018+
const zend_class_entry *scope, zend_object *object) {
60196019
if (scope != object->ce && !(prop && (prop->flags & ZEND_ACC_PRIVATE))) {
6020-
prop = zend_hash_find_ptr(&object->ce->properties_info, ref->unmangled_name);
6020+
prop = zend_hash_find_ptr(&object->ce->properties_info, unmangled_name);
60216021
}
60226022
return prop;
60236023
}
@@ -6050,8 +6050,8 @@ ZEND_METHOD(ReflectionProperty, getRawValue)
60506050
}
60516051
}
60526052

6053-
zend_property_info *prop = reflection_property_get_effective_prop(ref,
6054-
intern->ce, Z_OBJ_P(object));
6053+
const zend_property_info *prop = reflection_property_get_effective_prop(ref->prop,
6054+
ref->unmangled_name, intern->ce, Z_OBJ_P(object));
60556055

60566056
if (UNEXPECTED(prop && (prop->flags & ZEND_ACC_STATIC))) {
60576057
zend_throw_exception(reflection_exception_ptr, "May not use getRawValue on static properties", 0);
@@ -6081,13 +6081,15 @@ ZEND_METHOD(ReflectionProperty, getRawValue)
60816081
}
60826082
}
60836083

6084-
static void reflection_property_set_raw_value(zend_property_info *prop,
6085-
zend_string *unmangled_name, void *cache_slot[3], reflection_object *intern,
6086-
zend_object *object, zval *value)
6084+
static void zend_reflection_property_set_raw_value_ex(const zend_property_info *prop,
6085+
zend_string *unmangled_name, void *cache_slot[3],
6086+
const zend_class_entry *scope, zend_object *object, zval *value)
60876087
{
6088+
ZEND_ASSERT(!prop || !(prop->flags & ZEND_ACC_STATIC));
6089+
60886090
if (!prop || !prop->hooks || !prop->hooks[ZEND_PROPERTY_HOOK_SET]) {
60896091
const zend_class_entry *old_scope = EG(fake_scope);
6090-
EG(fake_scope) = intern->ce;
6092+
EG(fake_scope) = scope;
60916093
object->handlers->write_property(object, unmangled_name, value, cache_slot);
60926094
EG(fake_scope) = old_scope;
60936095
} else {
@@ -6096,6 +6098,22 @@ static void reflection_property_set_raw_value(zend_property_info *prop,
60966098
}
60976099
}
60986100

6101+
PHPAPI void zend_reflection_property_set_raw_value(const zend_property_info *prop,
6102+
zend_string *unmangled_name, void *cache_slot[3],
6103+
const zend_class_entry *scope, zend_object *object, zval *value)
6104+
{
6105+
prop = reflection_property_get_effective_prop(prop,
6106+
unmangled_name, scope, object);
6107+
6108+
if (UNEXPECTED(prop && (prop->flags & ZEND_ACC_STATIC))) {
6109+
zend_throw_exception(reflection_exception_ptr, "May not use setRawValue on static properties", 0);
6110+
return;
6111+
}
6112+
6113+
zend_reflection_property_set_raw_value_ex(prop, unmangled_name, cache_slot,
6114+
scope, object, value);
6115+
}
6116+
60996117
ZEND_METHOD(ReflectionProperty, setRawValue)
61006118
{
61016119
reflection_object *intern;
@@ -6110,26 +6128,18 @@ ZEND_METHOD(ReflectionProperty, setRawValue)
61106128
Z_PARAM_ZVAL(value)
61116129
} ZEND_PARSE_PARAMETERS_END();
61126130

6113-
zend_property_info *prop = reflection_property_get_effective_prop(ref,
6114-
intern->ce, Z_OBJ_P(object));
6115-
6116-
if (UNEXPECTED(prop && (prop->flags & ZEND_ACC_STATIC))) {
6117-
zend_throw_exception(reflection_exception_ptr, "May not use setRawValue on static properties", 0);
6118-
RETURN_THROWS();
6119-
}
6120-
6121-
reflection_property_set_raw_value(prop, ref->unmangled_name,
6122-
ref->cache_slot, intern, Z_OBJ_P(object), value);
6131+
zend_reflection_property_set_raw_value(ref->prop, ref->unmangled_name,
6132+
ref->cache_slot, intern->ce, Z_OBJ_P(object), value);
61236133
}
61246134

61256135
static zend_result reflection_property_check_lazy_compatible(
6126-
zend_property_info *prop, zend_string *unmangled_name,
6127-
reflection_object *intern, zend_object *object, const char *method)
6136+
const zend_property_info *prop, zend_string *unmangled_name,
6137+
const zend_class_entry *scope, zend_object *object, const char *method)
61286138
{
61296139
if (!prop) {
61306140
zend_throw_exception_ex(reflection_exception_ptr, 0,
61316141
"Can not use %s on dynamic property %s::$%s",
6132-
method, ZSTR_VAL(intern->ce->name),
6142+
method, ZSTR_VAL(scope->name),
61336143
ZSTR_VAL(unmangled_name));
61346144
return FAILURE;
61356145
}
@@ -6164,32 +6174,23 @@ static zend_result reflection_property_check_lazy_compatible(
61646174
return SUCCESS;
61656175
}
61666176

6167-
/* {{{ Set property value without triggering initializer while skipping hooks if any */
6168-
ZEND_METHOD(ReflectionProperty, setRawValueWithoutLazyInitialization)
6177+
PHPAPI void zend_reflection_property_set_raw_value_without_lazy_initialization(
6178+
const zend_property_info *prop, zend_string *unmangled_name,
6179+
void *cache_slot[3], const zend_class_entry *scope,
6180+
zend_object *object, zval *value)
61696181
{
6170-
reflection_object *intern;
6171-
property_reference *ref;
6172-
zend_object *object;
6173-
zval *value;
6174-
6175-
GET_REFLECTION_OBJECT_PTR(ref);
6176-
6177-
ZEND_PARSE_PARAMETERS_START(2, 2) {
6178-
Z_PARAM_OBJ_OF_CLASS(object, intern->ce)
6179-
Z_PARAM_ZVAL(value)
6180-
} ZEND_PARSE_PARAMETERS_END();
6181-
61826182
while (zend_object_is_lazy_proxy(object)
61836183
&& zend_lazy_object_initialized(object)) {
61846184
object = zend_lazy_object_get_instance(object);
61856185
}
61866186

6187-
zend_property_info *prop = reflection_property_get_effective_prop(ref,
6188-
intern->ce, object);
6187+
prop = reflection_property_get_effective_prop(prop,
6188+
unmangled_name, scope, object);
61896189

6190-
if (reflection_property_check_lazy_compatible(prop, ref->unmangled_name,
6191-
intern, object, "setRawValueWithoutLazyInitialization") == FAILURE) {
6192-
RETURN_THROWS();
6190+
if (reflection_property_check_lazy_compatible(prop, unmangled_name,
6191+
scope, object, "setRawValueWithoutLazyInitialization") == FAILURE) {
6192+
ZEND_ASSERT(EG(exception));
6193+
return;
61936194
}
61946195

61956196
zval *var_ptr = OBJ_PROP(object, prop->offset);
@@ -6198,8 +6199,8 @@ ZEND_METHOD(ReflectionProperty, setRawValueWithoutLazyInitialization)
61986199
/* Do not trigger initialization */
61996200
Z_PROP_FLAG_P(var_ptr) &= ~IS_PROP_LAZY;
62006201

6201-
reflection_property_set_raw_value(prop, ref->unmangled_name,
6202-
ref->cache_slot, intern, object, value);
6202+
zend_reflection_property_set_raw_value_ex(prop, unmangled_name,
6203+
cache_slot, scope, object, value);
62036204

62046205
/* Mark property as lazy again if an exception prevented update */
62056206
if (EG(exception) && prop_was_lazy && Z_TYPE_P(var_ptr) == IS_UNDEF
@@ -6218,6 +6219,26 @@ ZEND_METHOD(ReflectionProperty, setRawValueWithoutLazyInitialization)
62186219
}
62196220
}
62206221

6222+
/* {{{ Set property value without triggering initializer while skipping hooks if any */
6223+
ZEND_METHOD(ReflectionProperty, setRawValueWithoutLazyInitialization)
6224+
{
6225+
reflection_object *intern;
6226+
property_reference *ref;
6227+
zend_object *object;
6228+
zval *value;
6229+
6230+
GET_REFLECTION_OBJECT_PTR(ref);
6231+
6232+
ZEND_PARSE_PARAMETERS_START(2, 2) {
6233+
Z_PARAM_OBJ_OF_CLASS(object, intern->ce)
6234+
Z_PARAM_ZVAL(value)
6235+
} ZEND_PARSE_PARAMETERS_END();
6236+
6237+
zend_reflection_property_set_raw_value_without_lazy_initialization(
6238+
ref->prop, ref->unmangled_name, ref->cache_slot, intern->ce,
6239+
object, value);
6240+
}
6241+
62216242
/* {{{ Mark property as non-lazy, and initialize to default value */
62226243
ZEND_METHOD(ReflectionProperty, skipLazyInitialization)
62236244
{
@@ -6232,7 +6253,7 @@ ZEND_METHOD(ReflectionProperty, skipLazyInitialization)
62326253
} ZEND_PARSE_PARAMETERS_END();
62336254

62346255
if (reflection_property_check_lazy_compatible(ref->prop,
6235-
ref->unmangled_name, intern, object,
6256+
ref->unmangled_name, intern->ce, object,
62366257
"skipLazyInitialization") == FAILURE) {
62376258
RETURN_THROWS();
62386259
}
@@ -6703,7 +6724,7 @@ ZEND_METHOD(ReflectionProperty, isReadable)
67036724

67046725
GET_REFLECTION_OBJECT_PTR(ref);
67056726

6706-
zend_property_info *prop = ref->prop;
6727+
const zend_property_info *prop = ref->prop;
67076728
if (prop && obj) {
67086729
if (prop->flags & ZEND_ACC_STATIC) {
67096730
zend_throw_exception(reflection_exception_ptr, "null is expected as object argument for static properties", 0);
@@ -6713,7 +6734,8 @@ ZEND_METHOD(ReflectionProperty, isReadable)
67136734
zend_throw_exception(reflection_exception_ptr, "Given object is not an instance of the class this property was declared in", 0);
67146735
RETURN_THROWS();
67156736
}
6716-
prop = reflection_property_get_effective_prop(ref, intern->ce, obj);
6737+
prop = reflection_property_get_effective_prop(ref->prop,
6738+
ref->unmangled_name, intern->ce, obj);
67176739
}
67186740

67196741
zend_class_entry *ce = obj ? obj->ce : intern->ce;
@@ -6809,7 +6831,7 @@ ZEND_METHOD(ReflectionProperty, isWritable)
68096831

68106832
GET_REFLECTION_OBJECT_PTR(ref);
68116833

6812-
zend_property_info *prop = ref->prop;
6834+
const zend_property_info *prop = ref->prop;
68136835
if (prop && obj) {
68146836
if (prop->flags & ZEND_ACC_STATIC) {
68156837
zend_throw_exception(reflection_exception_ptr, "null is expected as object argument for static properties", 0);
@@ -6819,7 +6841,8 @@ ZEND_METHOD(ReflectionProperty, isWritable)
68196841
zend_throw_exception(reflection_exception_ptr, "Given object is not an instance of the class this property was declared in", 0);
68206842
RETURN_THROWS();
68216843
}
6822-
prop = reflection_property_get_effective_prop(ref, intern->ce, obj);
6844+
prop = reflection_property_get_effective_prop(ref->prop,
6845+
ref->unmangled_name, intern->ce, obj);
68236846
}
68246847

68256848
zend_class_entry *ce = obj ? obj->ce : intern->ce;

ext/reflection/php_reflection.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,18 @@ extern PHPAPI zend_class_entry *reflection_lazy_object_ptr;
5050

5151
PHPAPI void zend_reflection_class_factory(zend_class_entry *ce, zval *object);
5252

53+
/* Sets the value of a property, bypassing a set hook if defined. */
54+
PHPAPI void zend_reflection_property_set_raw_value(
55+
const zend_property_info *prop, zend_string *unmangled_name,
56+
void *cache_slot[3], const zend_class_entry *scope,
57+
zend_object *object, zval *value);
58+
59+
/* Same as zend_reflection_property_set_raw_value(), but skips lazy object initialization. */
60+
PHPAPI void zend_reflection_property_set_raw_value_without_lazy_initialization(
61+
const zend_property_info *prop, zend_string *unmangled_name,
62+
void *cache_slot[3], const zend_class_entry *scope,
63+
zend_object *object, zval *value);
64+
5365
END_EXTERN_C()
5466

5567
#endif /* PHP_REFLECTION_H */

0 commit comments

Comments
 (0)