Skip to content

Commit

Permalink
Use zend_std_build_properties() to access zend_object.properties
Browse files Browse the repository at this point in the history
The zend_object.properties HashTable needs to be built just in time by calling
rebuild_object_properties() on the object before accessing it. Normally this is
done automatically in zend_std_get_properties(), but we do it manually in a few
places.

In this change I introduce an inline variant of zend_std_build_properties(), and
refactor these places to use it instead of calling rebuild_object_properties()
manually.

rebuild_object_properties() renamed as rebuild_object_properties_internal(), to
enforce usage of zend_std_get_properties() or zend_std_build_properties_ex().

Closes phpGH-14996
  • Loading branch information
arnaud-lb committed Jul 18, 2024
1 parent 436baae commit 1fbb666
Show file tree
Hide file tree
Showing 14 changed files with 124 additions and 257 deletions.
5 changes: 5 additions & 0 deletions UPGRADING.INTERNALS
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ PHP 8.4 INTERNALS UPGRADE NOTES

* Added zend_hash_get_current_pos_ex() variant of zend_hash_get_current_pos().

* Renamed rebuild_object_properties() to rebuild_object_properties_internal().
This function should not be used outside of zend_std_get_properties_ex() and
zend_std_get_properties(). Use zend_std_get_properties_ex() or
zend_std_get_properties() instead.

========================
2. Build system changes
========================
Expand Down
11 changes: 3 additions & 8 deletions Zend/zend_API.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "zend_inheritance.h"
#include "zend_ini.h"
#include "zend_enum.h"
#include "zend_object_handlers.h"
#include "zend_observer.h"

#include <stdarg.h>
Expand Down Expand Up @@ -1764,10 +1765,7 @@ ZEND_API void object_properties_load(zend_object *object, HashTable *properties)
ZSTR_VAL(object->ce->name), property_info != ZEND_WRONG_PROPERTY_INFO ? zend_get_unmangled_property_name(key): "");
}

if (!object->properties) {
rebuild_object_properties(object);
}
prop = zend_hash_update(object->properties, key, prop);
prop = zend_hash_update(zend_std_get_properties_ex(object), key, prop);
zval_add_ref(prop);
}
} else {
Expand All @@ -1779,10 +1777,7 @@ ZEND_API void object_properties_load(zend_object *object, HashTable *properties)
ZSTR_VAL(object->ce->name), h);
}

if (!object->properties) {
rebuild_object_properties(object);
}
prop = zend_hash_index_update(object->properties, h, prop);
prop = zend_hash_index_update(zend_std_get_properties_ex(object), h, prop);
zval_add_ref(prop);
}
} ZEND_HASH_FOREACH_END();
Expand Down
21 changes: 7 additions & 14 deletions Zend/zend_object_handlers.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
called, we cal __call handler.
*/

ZEND_API void rebuild_object_properties(zend_object *zobj) /* {{{ */
ZEND_API void rebuild_object_properties_internal(zend_object *zobj) /* {{{ */
{
if (!zobj->properties) {
zend_property_info *prop_info;
Expand Down Expand Up @@ -130,7 +130,7 @@ ZEND_API HashTable *zend_std_build_object_properties_array(zend_object *zobj) /*
ZEND_API HashTable *zend_std_get_properties(zend_object *zobj) /* {{{ */
{
if (!zobj->properties) {
rebuild_object_properties(zobj);
rebuild_object_properties_internal(zobj);
}
return zobj->properties;
}
Expand Down Expand Up @@ -1124,10 +1124,7 @@ found:;
}

Z_TRY_ADDREF_P(value);
if (!zobj->properties) {
rebuild_object_properties(zobj);
}
variable_ptr = zend_hash_add_new(zobj->properties, name, value);
variable_ptr = zend_hash_add_new(zend_std_get_properties_ex(zobj), name, value);
}
}

Expand Down Expand Up @@ -1312,7 +1309,7 @@ ZEND_API zval *zend_std_get_property_ptr_ptr(zend_object *zobj, zend_string *nam
}
}
if (UNEXPECTED(!zobj->properties)) {
rebuild_object_properties(zobj);
rebuild_object_properties_internal(zobj);
}
if (UNEXPECTED(type == BP_VAR_RW || type == BP_VAR_R)) {
zend_error(E_WARNING, "Undefined property: %s::$%s", ZSTR_VAL(zobj->ce->name), ZSTR_VAL(name));
Expand Down Expand Up @@ -2028,13 +2025,9 @@ ZEND_API int zend_std_compare_objects(zval *o1, zval *o2) /* {{{ */
Z_UNPROTECT_RECURSION_P(o1);
return 0;
} else {
if (!zobj1->properties) {
rebuild_object_properties(zobj1);
}
if (!zobj2->properties) {
rebuild_object_properties(zobj2);
}
return zend_compare_symbol_tables(zobj1->properties, zobj2->properties);
return zend_compare_symbol_tables(
zend_std_get_properties_ex(zobj1),
zend_std_get_properties_ex(zobj2));
}
}
/* }}} */
Expand Down
11 changes: 10 additions & 1 deletion Zend/zend_object_handlers.h
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,16 @@ ZEND_API zend_function *zend_std_get_method(zend_object **obj_ptr, zend_string *
ZEND_API zend_string *zend_std_get_class_name(const zend_object *zobj);
ZEND_API int zend_std_compare_objects(zval *o1, zval *o2);
ZEND_API zend_result zend_std_get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr, bool check_only);
ZEND_API void rebuild_object_properties(zend_object *zobj);
/* Use zend_std_get_properties_ex() */
ZEND_API void rebuild_object_properties_internal(zend_object *zobj);

static inline HashTable *zend_std_get_properties_ex(zend_object *object)
{
if (!object->properties) {
rebuild_object_properties_internal(object);
}
return object->properties;
}

ZEND_API HashTable *zend_std_build_object_properties_array(zend_object *zobj);

Expand Down
7 changes: 2 additions & 5 deletions Zend/zend_vm_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -2495,9 +2495,6 @@ ZEND_VM_C_LABEL(fast_assign_obj):
}

if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}
if (OP_DATA_TYPE == IS_CONST) {
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) {
Z_ADDREF_P(value);
Expand All @@ -2521,8 +2518,8 @@ ZEND_VM_C_LABEL(fast_assign_obj):
} else if (OP_DATA_TYPE == IS_CV) {
Z_TRY_ADDREF_P(value);
}
}
zend_hash_add_new(zobj->properties, name, value);
}
zend_hash_add_new(zend_std_get_properties_ex(zobj), name, value);
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_COPY(EX_VAR(opline->result.var), value);
}
Expand Down
Loading

0 comments on commit 1fbb666

Please sign in to comment.