summaryrefslogtreecommitdiff
path: root/Zend/zend_execute.c
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_execute.c')
-rw-r--r--Zend/zend_execute.c85
1 files changed, 85 insertions, 0 deletions
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 515ac3ba3e..60323ad854 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -585,6 +585,19 @@ static inline void zend_assign_to_variable_reference(zval *variable_ptr, zval *v
ZVAL_REF(variable_ptr, ref);
}
+static zend_never_inline zval* zend_assign_to_typed_property_reference(zend_property_info *prop_info, zval *prop, zval *value_ptr)
+{
+ if (!zend_verify_prop_assignable_by_ref(prop_info, value_ptr, EX_USES_STRICT_TYPES())) {
+ return &EG(uninitialized_zval);
+ }
+ if (Z_ISREF_P(prop)) {
+ ZEND_REF_DEL_TYPE_SOURCE(Z_REF_P(prop), prop_info);
+ }
+ zend_assign_to_variable_reference(prop, value_ptr);
+ ZEND_REF_ADD_TYPE_SOURCE(Z_REF_P(prop), prop_info);
+ return prop;
+}
+
static zend_never_inline ZEND_COLD int zend_wrong_assign_to_variable_reference(zval *variable_ptr, zval *value_ptr OPLINE_DC EXECUTE_DATA_DC)
{
zend_error(E_NOTICE, "Only variables should be assigned by reference");
@@ -2744,6 +2757,78 @@ static zend_always_inline void zend_fetch_property_address(zval *result, zval *c
}
}
+static zend_always_inline void zend_assign_to_property_reference(zval *container, uint32_t container_op_type, zval *prop_ptr, uint32_t prop_op_type, zval *value_ptr OPLINE_DC EXECUTE_DATA_DC)
+{
+ zval variable, *variable_ptr = &variable;
+ void **cache_addr = (prop_op_type == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_RETURNS_FUNCTION) : NULL;
+
+ zend_fetch_property_address(variable_ptr, container, container_op_type, prop_ptr, prop_op_type,
+ cache_addr, BP_VAR_W, 0, 0 OPLINE_CC EXECUTE_DATA_CC);
+
+ if (Z_TYPE_P(variable_ptr) == IS_INDIRECT) {
+ variable_ptr = Z_INDIRECT_P(variable_ptr);
+ }
+
+ if (UNEXPECTED(Z_ISERROR_P(variable_ptr))) {
+ variable_ptr = &EG(uninitialized_zval);
+ } else if (UNEXPECTED(Z_TYPE(variable) != IS_INDIRECT)) {
+ zend_throw_error(NULL, "Cannot assign by reference to overloaded object");
+ variable_ptr = &EG(uninitialized_zval);
+ } else if (/*OP_DATA_TYPE == IS_VAR &&*/ UNEXPECTED(Z_ISERROR_P(value_ptr))) {
+ variable_ptr = &EG(uninitialized_zval);
+ } else if (/*OP_DATA_TYPE == IS_VAR &&*/
+ (opline->extended_value & ZEND_RETURNS_FUNCTION) &&
+ UNEXPECTED(!Z_ISREF_P(value_ptr))) {
+
+ if (UNEXPECTED(!zend_wrong_assign_to_variable_reference(
+ variable_ptr, value_ptr OPLINE_CC EXECUTE_DATA_CC))) {
+ variable_ptr = &EG(uninitialized_zval);
+ }
+ } else {
+ zend_property_info *prop_info = NULL;
+
+ if (prop_op_type == IS_CONST) {
+ prop_info = (zend_property_info *) CACHED_PTR_EX(cache_addr + 2);
+ } else {
+ prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(container), variable_ptr);
+ }
+
+ if (UNEXPECTED(prop_info)) {
+ variable_ptr = zend_assign_to_typed_property_reference(prop_info, variable_ptr, value_ptr);
+ } else {
+ zend_assign_to_variable_reference(variable_ptr, value_ptr);
+ }
+ }
+
+ if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+ ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr);
+ }
+}
+
+static zend_never_inline void zend_assign_to_property_reference_this_const(zval *container, zval *prop_ptr, zval *value_ptr OPLINE_DC EXECUTE_DATA_DC)
+{
+ zend_assign_to_property_reference(container, IS_UNUSED, prop_ptr, IS_CONST, value_ptr
+ OPLINE_CC EXECUTE_DATA_CC);
+}
+
+static zend_never_inline void zend_assign_to_property_reference_var_const(zval *container, zval *prop_ptr, zval *value_ptr OPLINE_DC EXECUTE_DATA_DC)
+{
+ zend_assign_to_property_reference(container, IS_VAR, prop_ptr, IS_CONST, value_ptr
+ OPLINE_CC EXECUTE_DATA_CC);
+}
+
+static zend_never_inline void zend_assign_to_property_reference_this_var(zval *container, zval *prop_ptr, zval *value_ptr OPLINE_DC EXECUTE_DATA_DC)
+{
+ zend_assign_to_property_reference(container, IS_VAR, prop_ptr, IS_CONST, value_ptr
+ OPLINE_CC EXECUTE_DATA_CC);
+}
+
+static zend_never_inline void zend_assign_to_property_reference_var_var(zval *container, zval *prop_ptr, zval *value_ptr OPLINE_DC EXECUTE_DATA_DC)
+{
+ zend_assign_to_property_reference(container, IS_VAR, prop_ptr, IS_VAR, value_ptr
+ OPLINE_CC EXECUTE_DATA_CC);
+}
+
static zend_never_inline int zend_fetch_static_property_address_ex(zval **retval, zend_property_info **prop_info, uint32_t cache_slot, int fetch_type OPLINE_DC EXECUTE_DATA_DC) {
zend_free_op free_op1;
zend_string *name, *tmp_name;