Skip to content

Commit 1fbb666

Browse files
committed
Use zend_std_build_properties() to access zend_object.properties
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 GH-14996
1 parent 436baae commit 1fbb666

14 files changed

+124
-257
lines changed

UPGRADING.INTERNALS

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,11 @@ PHP 8.4 INTERNALS UPGRADE NOTES
9494

9595
* Added zend_hash_get_current_pos_ex() variant of zend_hash_get_current_pos().
9696

97+
* Renamed rebuild_object_properties() to rebuild_object_properties_internal().
98+
This function should not be used outside of zend_std_get_properties_ex() and
99+
zend_std_get_properties(). Use zend_std_get_properties_ex() or
100+
zend_std_get_properties() instead.
101+
97102
========================
98103
2. Build system changes
99104
========================

Zend/zend_API.c

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "zend_inheritance.h"
3232
#include "zend_ini.h"
3333
#include "zend_enum.h"
34+
#include "zend_object_handlers.h"
3435
#include "zend_observer.h"
3536

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

1767-
if (!object->properties) {
1768-
rebuild_object_properties(object);
1769-
}
1770-
prop = zend_hash_update(object->properties, key, prop);
1768+
prop = zend_hash_update(zend_std_get_properties_ex(object), key, prop);
17711769
zval_add_ref(prop);
17721770
}
17731771
} else {
@@ -1779,10 +1777,7 @@ ZEND_API void object_properties_load(zend_object *object, HashTable *properties)
17791777
ZSTR_VAL(object->ce->name), h);
17801778
}
17811779

1782-
if (!object->properties) {
1783-
rebuild_object_properties(object);
1784-
}
1785-
prop = zend_hash_index_update(object->properties, h, prop);
1780+
prop = zend_hash_index_update(zend_std_get_properties_ex(object), h, prop);
17861781
zval_add_ref(prop);
17871782
}
17881783
} ZEND_HASH_FOREACH_END();

Zend/zend_object_handlers.c

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
called, we cal __call handler.
6363
*/
6464

65-
ZEND_API void rebuild_object_properties(zend_object *zobj) /* {{{ */
65+
ZEND_API void rebuild_object_properties_internal(zend_object *zobj) /* {{{ */
6666
{
6767
if (!zobj->properties) {
6868
zend_property_info *prop_info;
@@ -130,7 +130,7 @@ ZEND_API HashTable *zend_std_build_object_properties_array(zend_object *zobj) /*
130130
ZEND_API HashTable *zend_std_get_properties(zend_object *zobj) /* {{{ */
131131
{
132132
if (!zobj->properties) {
133-
rebuild_object_properties(zobj);
133+
rebuild_object_properties_internal(zobj);
134134
}
135135
return zobj->properties;
136136
}
@@ -1124,10 +1124,7 @@ found:;
11241124
}
11251125

11261126
Z_TRY_ADDREF_P(value);
1127-
if (!zobj->properties) {
1128-
rebuild_object_properties(zobj);
1129-
}
1130-
variable_ptr = zend_hash_add_new(zobj->properties, name, value);
1127+
variable_ptr = zend_hash_add_new(zend_std_get_properties_ex(zobj), name, value);
11311128
}
11321129
}
11331130

@@ -1312,7 +1309,7 @@ ZEND_API zval *zend_std_get_property_ptr_ptr(zend_object *zobj, zend_string *nam
13121309
}
13131310
}
13141311
if (UNEXPECTED(!zobj->properties)) {
1315-
rebuild_object_properties(zobj);
1312+
rebuild_object_properties_internal(zobj);
13161313
}
13171314
if (UNEXPECTED(type == BP_VAR_RW || type == BP_VAR_R)) {
13181315
zend_error(E_WARNING, "Undefined property: %s::$%s", ZSTR_VAL(zobj->ce->name), ZSTR_VAL(name));
@@ -2028,13 +2025,9 @@ ZEND_API int zend_std_compare_objects(zval *o1, zval *o2) /* {{{ */
20282025
Z_UNPROTECT_RECURSION_P(o1);
20292026
return 0;
20302027
} else {
2031-
if (!zobj1->properties) {
2032-
rebuild_object_properties(zobj1);
2033-
}
2034-
if (!zobj2->properties) {
2035-
rebuild_object_properties(zobj2);
2036-
}
2037-
return zend_compare_symbol_tables(zobj1->properties, zobj2->properties);
2028+
return zend_compare_symbol_tables(
2029+
zend_std_get_properties_ex(zobj1),
2030+
zend_std_get_properties_ex(zobj2));
20382031
}
20392032
}
20402033
/* }}} */

Zend/zend_object_handlers.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,16 @@ ZEND_API zend_function *zend_std_get_method(zend_object **obj_ptr, zend_string *
267267
ZEND_API zend_string *zend_std_get_class_name(const zend_object *zobj);
268268
ZEND_API int zend_std_compare_objects(zval *o1, zval *o2);
269269
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);
270-
ZEND_API void rebuild_object_properties(zend_object *zobj);
270+
/* Use zend_std_get_properties_ex() */
271+
ZEND_API void rebuild_object_properties_internal(zend_object *zobj);
272+
273+
static inline HashTable *zend_std_get_properties_ex(zend_object *object)
274+
{
275+
if (!object->properties) {
276+
rebuild_object_properties_internal(object);
277+
}
278+
return object->properties;
279+
}
271280

272281
ZEND_API HashTable *zend_std_build_object_properties_array(zend_object *zobj);
273282

Zend/zend_vm_def.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2495,9 +2495,6 @@ ZEND_VM_C_LABEL(fast_assign_obj):
24952495
}
24962496

24972497
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
2498-
if (EXPECTED(zobj->properties == NULL)) {
2499-
rebuild_object_properties(zobj);
2500-
}
25012498
if (OP_DATA_TYPE == IS_CONST) {
25022499
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) {
25032500
Z_ADDREF_P(value);
@@ -2521,8 +2518,8 @@ ZEND_VM_C_LABEL(fast_assign_obj):
25212518
} else if (OP_DATA_TYPE == IS_CV) {
25222519
Z_TRY_ADDREF_P(value);
25232520
}
2524-
}
2525-
zend_hash_add_new(zobj->properties, name, value);
2521+
}
2522+
zend_hash_add_new(zend_std_get_properties_ex(zobj), name, value);
25262523
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
25272524
ZVAL_COPY(EX_VAR(opline->result.var), value);
25282525
}

0 commit comments

Comments
 (0)