@@ -1010,15 +1010,47 @@ static zval *spl_array_it_get_current_data(zend_object_iterator *iter) /* {{{ */
1010
1010
spl_array_object * object = Z_SPLARRAY_P (& iter -> data );
1011
1011
HashTable * aht = spl_array_get_hash_table (object );
1012
1012
1013
+ zval * data ;
1013
1014
if (object -> ar_flags & SPL_ARRAY_OVERLOADED_CURRENT ) {
1014
- return zend_user_it_get_current_data (iter );
1015
+ data = zend_user_it_get_current_data (iter );
1015
1016
} else {
1016
- zval * data = zend_hash_get_current_data_ex (aht , spl_array_get_pos_ptr (aht , object ));
1017
+ data = zend_hash_get_current_data_ex (aht , spl_array_get_pos_ptr (aht , object ));
1017
1018
if (data && Z_TYPE_P (data ) == IS_INDIRECT ) {
1018
1019
data = Z_INDIRECT_P (data );
1019
1020
}
1020
- return data ;
1021
1021
}
1022
+ // ZEND_FE_FETCH_RW converts the value to a reference but doesn't know the source is a property.
1023
+ // Typed properties must add a type source to the reference, and readonly properties must fail.
1024
+ zend_execute_data * execute_data = EG (current_execute_data );
1025
+ if (data
1026
+ && Z_TYPE_P (data ) != IS_REFERENCE
1027
+ && execute_data
1028
+ && ZEND_USER_CODE (execute_data -> func -> type )
1029
+ && execute_data -> opline
1030
+ && execute_data -> opline -> opcode == ZEND_FE_FETCH_RW
1031
+ && !(object -> ar_flags & SPL_ARRAY_IS_SELF )
1032
+ && !(object -> ar_flags & SPL_ARRAY_USE_OTHER )
1033
+ && Z_TYPE (object -> array ) == IS_OBJECT ) {
1034
+ zend_string * key ;
1035
+ zend_hash_get_current_key_ex (aht , & key , NULL , spl_array_get_pos_ptr (aht , object ));
1036
+ zend_class_entry * ce = Z_OBJCE (object -> array );
1037
+ zend_property_info * prop_info = zend_get_property_info (ce , key , true);
1038
+ if (ZEND_TYPE_IS_SET (prop_info -> type )) {
1039
+ if (prop_info -> flags & ZEND_ACC_READONLY ) {
1040
+ zend_throw_error (NULL ,
1041
+ "Cannot acquire reference to readonly property %s::$%s" ,
1042
+ ZSTR_VAL (prop_info -> ce -> name ), ZSTR_VAL (key ));
1043
+ return NULL ;
1044
+ }
1045
+ zend_refcounted * gc = Z_COUNTED_P (data );
1046
+ zval * ref ;
1047
+ ZVAL_NEW_EMPTY_REF (data );
1048
+ ref = Z_REFVAL_P (data );
1049
+ ZVAL_COPY_VALUE_EX (ref , data , gc , Z_TYPE_P (data ));
1050
+ ZEND_REF_ADD_TYPE_SOURCE (Z_REF_P (data ), prop_info );
1051
+ }
1052
+ }
1053
+ return data ;
1022
1054
}
1023
1055
/* }}} */
1024
1056
0 commit comments