@@ -268,14 +268,17 @@ ZEND_API zend_object *zend_object_make_lazy(zend_object *obj,
268
268
269
269
obj = zend_objects_new (reflection_ce );
270
270
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 -- ) {
272
273
zval * p = & obj -> properties_table [i ];
273
274
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 )];
275
280
Z_PROP_FLAG_P (p ) = IS_PROP_UNINIT | IS_PROP_LAZY ;
276
281
lazy_properties_count ++ ;
277
- } else {
278
- Z_PROP_FLAG_P (p ) = 0 ;
279
282
}
280
283
}
281
284
} else {
@@ -408,12 +411,16 @@ static void zend_lazy_object_revert_init(zend_object *obj, zval *properties_tabl
408
411
zval * properties_table = obj -> properties_table ;
409
412
410
413
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 )];
412
420
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 ) ]);
414
422
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 )) {
417
424
ZEND_REF_ADD_TYPE_SOURCE (Z_REF_P (p ), prop_info );
418
425
}
419
426
}
@@ -526,10 +533,12 @@ static zend_object *zend_lazy_object_init_proxy(zend_object *obj)
526
533
obj -> properties = NULL ;
527
534
528
535
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 ;
533
542
}
534
543
}
535
544
@@ -723,13 +732,14 @@ zend_object *zend_lazy_object_clone(zend_object *old_obj)
723
732
zend_object * new_proxy = zend_objects_new (ce );
724
733
725
734
for (int i = 0 ; i < ce -> default_properties_count ; i ++ ) {
726
- zval * p = & new_proxy -> properties_table [i ];
727
- ZVAL_UNDEF (p );
728
- if (EXPECTED (ce -> properties_info_table [i ])) {
729
- Z_PROP_FLAG_P (p ) = IS_PROP_UNINIT | IS_PROP_LAZY ;
730
- } else {
731
- Z_PROP_FLAG_P (p ) = 0 ;
735
+ zend_property_info * prop_info = ce -> properties_info_table [i ];
736
+ if (!prop_info ) {
737
+ continue ;
732
738
}
739
+
740
+ zval * p = & new_proxy -> properties_table [OBJ_PROP_TO_NUM (prop_info -> offset )];
741
+ ZVAL_UNDEF (p );
742
+ Z_PROP_FLAG_P (p ) = IS_PROP_UNINIT | IS_PROP_LAZY ;
733
743
}
734
744
735
745
OBJ_EXTRA_FLAGS (new_proxy ) = OBJ_EXTRA_FLAGS (old_obj );
0 commit comments