@@ -268,14 +268,17 @@ ZEND_API zend_object *zend_object_make_lazy(zend_object *obj,
268268
269269 obj = zend_objects_new (reflection_ce );
270270
271- for (int i = 0 ; i < obj -> ce -> default_properties_count ; i ++ ) {
271+ /* Iterate in reverse to avoid overriding Z_PROP_FLAG_P() of child props with added hooks (GH-17870). */
272+ for (int i = obj -> ce -> default_properties_count - 1 ; i >= 0 ; i -- ) {
272273 zval * p = & obj -> properties_table [i ];
273274 ZVAL_UNDEF (p );
274- if (EXPECTED (obj -> ce -> properties_info_table [i ])) {
275+ Z_PROP_FLAG_P (p ) = 0 ;
276+
277+ zend_property_info * prop_info = obj -> ce -> properties_info_table [i ];
278+ if (prop_info ) {
279+ zval * p = & obj -> properties_table [OBJ_PROP_TO_NUM (prop_info -> offset )];
275280 Z_PROP_FLAG_P (p ) = IS_PROP_UNINIT | IS_PROP_LAZY ;
276281 lazy_properties_count ++ ;
277- } else {
278- Z_PROP_FLAG_P (p ) = 0 ;
279282 }
280283 }
281284 } else {
@@ -326,7 +329,7 @@ ZEND_API zend_object *zend_object_make_lazy(zend_object *obj,
326329 for (int i = 0 ; i < reflection_ce -> default_properties_count ; i ++ ) {
327330 zend_property_info * prop_info = obj -> ce -> properties_info_table [i ];
328331 if (EXPECTED (prop_info )) {
329- zval * p = & obj -> properties_table [i ];
332+ zval * p = & obj -> properties_table [OBJ_PROP_TO_NUM ( prop_info -> offset ) ];
330333 if (Z_TYPE_P (p ) != IS_UNDEF ) {
331334 if ((prop_info -> flags & ZEND_ACC_READONLY ) && !(Z_PROP_FLAG_P (p ) & IS_PROP_REINITABLE )
332335 /* TODO: test final property */
@@ -408,12 +411,16 @@ static void zend_lazy_object_revert_init(zend_object *obj, zval *properties_tabl
408411 zval * properties_table = obj -> properties_table ;
409412
410413 for (int i = 0 ; i < ce -> default_properties_count ; i ++ ) {
411- zval * p = & properties_table [i ];
414+ zend_property_info * prop_info = ce -> properties_info_table [i ];
415+ if (!prop_info ) {
416+ continue ;
417+ }
418+
419+ zval * p = & properties_table [OBJ_PROP_TO_NUM (prop_info -> offset )];
412420 zend_object_dtor_property (obj , p );
413- ZVAL_COPY_VALUE_PROP (p , & properties_table_snapshot [i ]);
421+ ZVAL_COPY_VALUE_PROP (p , & properties_table_snapshot [OBJ_PROP_TO_NUM ( prop_info -> offset ) ]);
414422
415- zend_property_info * prop_info = ce -> properties_info_table [i ];
416- if (Z_ISREF_P (p ) && prop_info && ZEND_TYPE_IS_SET (prop_info -> type )) {
423+ if (Z_ISREF_P (p ) && ZEND_TYPE_IS_SET (prop_info -> type )) {
417424 ZEND_REF_ADD_TYPE_SOURCE (Z_REF_P (p ), prop_info );
418425 }
419426 }
@@ -526,10 +533,12 @@ static zend_object *zend_lazy_object_init_proxy(zend_object *obj)
526533 obj -> properties = NULL ;
527534
528535 for (int i = 0 ; i < Z_OBJ (retval )-> ce -> default_properties_count ; i ++ ) {
529- if (EXPECTED (Z_OBJ (retval )-> ce -> properties_info_table [i ])) {
530- zend_object_dtor_property (obj , & obj -> properties_table [i ]);
531- ZVAL_UNDEF (& obj -> properties_table [i ]);
532- Z_PROP_FLAG_P (& obj -> properties_table [i ]) = IS_PROP_UNINIT | IS_PROP_LAZY ;
536+ zend_property_info * prop_info = Z_OBJ (retval )-> ce -> properties_info_table [i ];
537+ if (EXPECTED (prop_info )) {
538+ zval * prop = & obj -> properties_table [OBJ_PROP_TO_NUM (prop_info -> offset )];
539+ zend_object_dtor_property (obj , prop );
540+ ZVAL_UNDEF (prop );
541+ Z_PROP_FLAG_P (prop ) = IS_PROP_UNINIT | IS_PROP_LAZY ;
533542 }
534543 }
535544
@@ -722,13 +731,16 @@ zend_object *zend_lazy_object_clone(zend_object *old_obj)
722731 zend_class_entry * ce = old_obj -> ce ;
723732 zend_object * new_proxy = zend_objects_new (ce );
724733
725- for (int i = 0 ; i < ce -> default_properties_count ; i ++ ) {
734+ /* Iterate in reverse to avoid overriding Z_PROP_FLAG_P() of child props with added hooks (GH-17870). */
735+ for (int i = ce -> default_properties_count - 1 ; i >= 0 ; i -- ) {
726736 zval * p = & new_proxy -> properties_table [i ];
727737 ZVAL_UNDEF (p );
728- if (EXPECTED (ce -> properties_info_table [i ])) {
738+ Z_PROP_FLAG_P (p ) = 0 ;
739+
740+ zend_property_info * prop_info = ce -> properties_info_table [i ];
741+ if (prop_info ) {
742+ zval * p = & new_proxy -> properties_table [OBJ_PROP_TO_NUM (prop_info -> offset )];
729743 Z_PROP_FLAG_P (p ) = IS_PROP_UNINIT | IS_PROP_LAZY ;
730- } else {
731- Z_PROP_FLAG_P (p ) = 0 ;
732744 }
733745 }
734746
0 commit comments