@@ -946,6 +946,18 @@ ZEND_API zval *zend_std_read_property(zend_object *zobj, zend_string *name, int
946
946
goto exit ;
947
947
}
948
948
949
+ if (UNEXPECTED (guard )) {
950
+ uint32_t guard_type = (type == BP_VAR_IS ) && zobj -> ce -> __isset
951
+ ? IN_ISSET : IN_GET ;
952
+ guard = zend_get_property_guard (zobj , name );
953
+ if (!((* guard ) & guard_type )) {
954
+ (* guard ) |= guard_type ;
955
+ retval = zend_std_read_property (zobj , name , type , cache_slot , rv );
956
+ (* guard ) &= ~guard_type ;
957
+ return retval ;
958
+ }
959
+ }
960
+
949
961
return zend_std_read_property (zobj , name , type , cache_slot , rv );
950
962
}
951
963
}
@@ -970,6 +982,43 @@ static zend_always_inline bool property_uses_strict_types(void) {
970
982
&& ZEND_CALL_USES_STRICT_TYPES (EG (current_execute_data ));
971
983
}
972
984
985
+ static zval * forward_write_to_lazy_object (zend_object * zobj ,
986
+ zend_string * name , zval * value , void * * cache_slot , bool guarded )
987
+ {
988
+ zval * variable_ptr ;
989
+
990
+ /* backup value as it may change during initialization */
991
+ zval backup ;
992
+ ZVAL_COPY (& backup , value );
993
+
994
+ zend_object * instance = zend_lazy_object_init (zobj );
995
+ if (UNEXPECTED (!instance )) {
996
+ zval_ptr_dtor (& backup );
997
+ return & EG (error_zval );
998
+ }
999
+
1000
+ if (UNEXPECTED (guarded )) {
1001
+ uint32_t * guard = zend_get_property_guard (instance , name );
1002
+ if (!((* guard ) & IN_SET )) {
1003
+ (* guard ) |= IN_SET ;
1004
+ variable_ptr = zend_std_write_property (instance , name , & backup , cache_slot );
1005
+ (* guard ) &= ~IN_SET ;
1006
+ goto exit ;
1007
+ }
1008
+ }
1009
+
1010
+ variable_ptr = zend_std_write_property (instance , name , & backup , cache_slot );
1011
+
1012
+ exit :
1013
+ zval_ptr_dtor (& backup );
1014
+
1015
+ if (variable_ptr == & backup ) {
1016
+ variable_ptr = value ;
1017
+ }
1018
+
1019
+ return variable_ptr ;
1020
+ }
1021
+
973
1022
ZEND_API zval * zend_std_write_property (zend_object * zobj , zend_string * name , zval * value , void * * cache_slot ) /* {{{ */
974
1023
{
975
1024
zval * variable_ptr , tmp ;
@@ -1151,7 +1200,8 @@ found:;
1151
1200
variable_ptr = value ;
1152
1201
} else if (EXPECTED (!IS_WRONG_PROPERTY_OFFSET (property_offset ))) {
1153
1202
if (UNEXPECTED (zend_lazy_object_must_init (zobj ))) {
1154
- goto lazy_init ;
1203
+ return forward_write_to_lazy_object (zobj , name , value ,
1204
+ cache_slot , /* guarded */ true);
1155
1205
}
1156
1206
1157
1207
goto write_std_property ;
@@ -1198,26 +1248,9 @@ found:;
1198
1248
exit :
1199
1249
return variable_ptr ;
1200
1250
1201
- lazy_init :;
1202
- /* backup value as it may change during initialization */
1203
- zval backup ;
1204
- ZVAL_COPY (& backup , value );
1205
-
1206
- zobj = zend_lazy_object_init (zobj );
1207
- if (UNEXPECTED (!zobj )) {
1208
- variable_ptr = & EG (error_zval );
1209
- zval_ptr_dtor (& backup );
1210
- goto exit ;
1211
- }
1212
-
1213
- variable_ptr = zend_std_write_property (zobj , name , & backup , cache_slot );
1214
- zval_ptr_dtor (& backup );
1215
-
1216
- if (variable_ptr == & backup ) {
1217
- variable_ptr = value ;
1218
- }
1219
-
1220
- return variable_ptr ;
1251
+ lazy_init :
1252
+ return forward_write_to_lazy_object (zobj , name , value , cache_slot ,
1253
+ /* guarded */ false);
1221
1254
}
1222
1255
/* }}} */
1223
1256
@@ -1538,6 +1571,17 @@ ZEND_API void zend_std_unset_property(zend_object *zobj, zend_string *name, void
1538
1571
if (!zobj ) {
1539
1572
return ;
1540
1573
}
1574
+
1575
+ if (UNEXPECTED (guard )) {
1576
+ guard = zend_get_property_guard (zobj , name );
1577
+ if (!((* guard ) & IN_UNSET )) {
1578
+ (* guard ) |= IN_UNSET ;
1579
+ zend_std_unset_property (zobj , name , cache_slot );
1580
+ (* guard ) &= ~IN_UNSET ;
1581
+ return ;
1582
+ }
1583
+ }
1584
+
1541
1585
zend_std_unset_property (zobj , name , cache_slot );
1542
1586
return ;
1543
1587
}
@@ -2327,6 +2371,8 @@ ZEND_API int zend_std_has_property(zend_object *zobj, zend_string *name, int has
2327
2371
}
2328
2372
(* guard ) &= ~IN_ISSET ;
2329
2373
OBJ_RELEASE (zobj );
2374
+ } else {
2375
+ goto lazy_init ;
2330
2376
}
2331
2377
}
2332
2378
@@ -2342,6 +2388,16 @@ ZEND_API int zend_std_has_property(zend_object *zobj, zend_string *name, int has
2342
2388
goto exit ;
2343
2389
}
2344
2390
2391
+ if (UNEXPECTED (zobj -> ce -> __isset )) {
2392
+ uint32_t * guard = zend_get_property_guard (zobj , name );
2393
+ if (!((* guard ) & IN_ISSET )) {
2394
+ (* guard ) |= IN_ISSET ;
2395
+ result = zend_std_has_property (zobj , name , has_set_exists , cache_slot );
2396
+ (* guard ) &= ~IN_ISSET ;
2397
+ return result ;
2398
+ }
2399
+ }
2400
+
2345
2401
return zend_std_has_property (zobj , name , has_set_exists , cache_slot );
2346
2402
}
2347
2403
}
0 commit comments