@@ -733,6 +733,8 @@ ZEND_API zval *zend_std_read_property(zend_object *zobj, zend_string *name, int
733
733
uintptr_t property_offset ;
734
734
const zend_property_info * prop_info = NULL ;
735
735
uint32_t * guard = NULL ;
736
+ bool obj_needs_deref = false;
737
+ zend_object * prev_zobj ;
736
738
737
739
#if DEBUG_OBJECT_HANDLERS
738
740
fprintf (stderr , "Read object #%d property: %s\n" , zobj -> handle , ZSTR_VAL (name ));
@@ -906,12 +908,8 @@ ZEND_API zval *zend_std_read_property(zend_object *zobj, zend_string *name, int
906
908
goto call_getter ;
907
909
}
908
910
909
- bool obj_is_freed = GC_REFCOUNT (zobj ) == 1 ;
910
- OBJ_RELEASE (zobj );
911
- if (UNEXPECTED (obj_is_freed )) {
912
- retval = & EG (uninitialized_zval );
913
- goto exit ;
914
- }
911
+ obj_needs_deref = true;
912
+ prev_zobj = zobj ;
915
913
} else if (zobj -> ce -> __get && !((* guard ) & IN_GET )) {
916
914
goto call_getter_addref ;
917
915
}
@@ -960,7 +958,7 @@ ZEND_API zval *zend_std_read_property(zend_object *zobj, zend_string *name, int
960
958
zobj = zend_lazy_object_init (zobj );
961
959
if (!zobj ) {
962
960
retval = & EG (uninitialized_zval );
963
- goto exit ;
961
+ goto exit_slow ;
964
962
}
965
963
966
964
if (UNEXPECTED (guard )) {
@@ -971,11 +969,12 @@ ZEND_API zval *zend_std_read_property(zend_object *zobj, zend_string *name, int
971
969
(* guard ) |= guard_type ;
972
970
retval = zend_std_read_property (zobj , name , type , cache_slot , rv );
973
971
(* guard ) &= ~guard_type ;
974
- return retval ;
972
+ goto exit_slow ;
975
973
}
976
974
}
977
975
978
- return zend_std_read_property (zobj , name , type , cache_slot , rv );
976
+ retval = zend_std_read_property (zobj , name , type , cache_slot , rv );
977
+ goto exit_slow ;
979
978
}
980
979
}
981
980
if (type != BP_VAR_IS ) {
@@ -987,6 +986,16 @@ ZEND_API zval *zend_std_read_property(zend_object *zobj, zend_string *name, int
987
986
}
988
987
retval = & EG (uninitialized_zval );
989
988
989
+ exit_slow :
990
+ if (obj_needs_deref ) {
991
+ /* Move value to rv in case zobj gets destroyed. */
992
+ if (retval != rv ) {
993
+ ZVAL_COPY (rv , retval );
994
+ retval = rv ;
995
+ }
996
+ OBJ_RELEASE (prev_zobj );
997
+ }
998
+
990
999
exit :
991
1000
return retval ;
992
1001
}
0 commit comments