summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/zend_compile.c54
-rw-r--r--Zend/zend_constants.c2
-rw-r--r--Zend/zend_objects.c2
-rw-r--r--Zend/zend_types.h9
-rw-r--r--Zend/zend_variables.c21
-rw-r--r--Zend/zend_vm_def.h16
-rw-r--r--Zend/zend_vm_execute.h165
-rw-r--r--ext/opcache/Optimizer/pass1_5.c1
-rw-r--r--ext/opcache/zend_accelerator_util_funcs.c2
-rw-r--r--ext/reflection/php_reflection.c2
-rw-r--r--ext/standard/array.c29
11 files changed, 209 insertions, 94 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 818ecf3632..d54e705a81 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -3089,7 +3089,7 @@ ZEND_API void function_add_ref(zend_function *function) /* {{{ */
ALLOC_HASHTABLE(op_array->static_variables);
zend_hash_init(op_array->static_variables, zend_hash_num_elements(static_variables), NULL, ZVAL_PTR_DTOR, 0);
- zend_hash_copy(op_array->static_variables, static_variables, zval_add_ref_unref);
+ zend_hash_copy(op_array->static_variables, static_variables, zval_add_ref);
}
op_array->run_time_cache = NULL;
} else if (function->type == ZEND_INTERNAL_FUNCTION) {
@@ -3743,6 +3743,27 @@ ZEND_API void zend_do_inherit_interfaces(zend_class_entry *ce, const zend_class_
zval_add_ref
#endif
+static int do_inherit_class_constant(zval *zv TSRMLS_DC, int num_args, va_list args, const zend_hash_key *hash_key) /* {{{ */
+{
+ zend_class_entry *ce = va_arg(args, zend_class_entry *);
+ zend_class_entry *parent_ce = va_arg(args, zend_class_entry *);
+
+ if (hash_key->key) {
+ if (!Z_ISREF_P(zv)) {
+ if (parent_ce->type == ZEND_INTERNAL_CLASS) {
+ ZVAL_NEW_PERSISTENT_REF(zv, zv);
+ } else {
+ ZVAL_NEW_REF(zv, zv);
+ }
+ }
+ if (zend_hash_add(&ce->constants_table, hash_key->key, zv)) {
+ Z_ADDREF_P(zv);
+ }
+ }
+ return ZEND_HASH_APPLY_KEEP;
+}
+/* }}} */
+
ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce TSRMLS_DC) /* {{{ */
{
zend_property_info *property_info;
@@ -3846,7 +3867,7 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
zend_hash_merge_ex(&ce->properties_info, &parent_ce->properties_info, (ce->type & ZEND_INTERNAL_CLASS ? zend_duplicate_property_info_internal_zval : zend_duplicate_property_info_zval), (merge_checker_func_t) do_inherit_property_access_check, ce);
- zend_hash_merge(&ce->constants_table, &parent_ce->constants_table, zval_property_ctor(parent_ce, ce), 0);
+ zend_hash_apply_with_arguments(&parent_ce->constants_table TSRMLS_CC, (apply_func_args_t)do_inherit_class_constant, 2, ce, parent_ce);
zend_hash_merge_ex(&ce->function_table, &parent_ce->function_table, do_inherit_method, (merge_checker_func_t) do_inherit_method_check, ce);
do_inherit_parent_constructor(ce);
@@ -3865,14 +3886,9 @@ static zend_bool do_inherit_constant_check(HashTable *child_constants_table, con
zval *old_constant;
if ((old_constant = zend_hash_find(child_constants_table, hash_key->key)) != NULL) {
-//??? if (old_constant != parent_constant) {
-//??? see Zend/tests/errmsg_025.phpt
- if ((Z_TYPE_P(old_constant) != Z_TYPE_P(parent_constant)) ||
- (Z_TYPE_P(old_constant) == IS_LONG && Z_LVAL_P(old_constant) != Z_LVAL_P(parent_constant)) ||
- (Z_TYPE_P(old_constant) == IS_BOOL && Z_LVAL_P(old_constant) != Z_LVAL_P(parent_constant)) ||
- (Z_TYPE_P(old_constant) == IS_DOUBLE && Z_DVAL_P(old_constant) != Z_DVAL_P(parent_constant)) ||
- (Z_TYPE_P(old_constant) == IS_STRING && Z_STR_P(old_constant) != Z_STR_P(parent_constant)) ||
- (Z_REFCOUNTED_P(old_constant) && Z_COUNTED_P(old_constant) != Z_COUNTED_P(parent_constant))) {
+ if (!Z_ISREF_P(old_constant) ||
+ !Z_ISREF_P(parent_constant) ||
+ Z_REFVAL_P(old_constant) != Z_REFVAL_P(parent_constant)) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot inherit previously-inherited or override constant %s from interface %s", hash_key->key->val, iface->name->val);
}
return 0;
@@ -3891,6 +3907,22 @@ static int do_interface_constant_check(zval *val TSRMLS_DC, int num_args, va_lis
}
/* }}} */
+static int do_inherit_iface_constant(zval *zv TSRMLS_DC, int num_args, va_list args, const zend_hash_key *hash_key) /* {{{ */
+{
+ zend_class_entry *ce = va_arg(args, zend_class_entry *);
+ zend_class_entry *iface = va_arg(args, zend_class_entry *);
+
+ if (hash_key->key && do_inherit_constant_check(&ce->constants_table, zv, hash_key, iface)) {
+ if (!Z_ISREF_P(zv)) {
+ ZVAL_NEW_REF(zv, zv);
+ }
+ Z_ADDREF_P(zv);
+ zend_hash_update(&ce->constants_table, hash_key->key, zv);
+ }
+ return ZEND_HASH_APPLY_KEEP;
+}
+/* }}} */
+
ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry *iface TSRMLS_DC) /* {{{ */
{
zend_uint i, ignore = 0;
@@ -3922,7 +3954,7 @@ ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry
}
ce->interfaces[ce->num_interfaces++] = iface;
- zend_hash_merge_ex(&ce->constants_table, &iface->constants_table, (copy_ctor_func_t) zval_add_ref, (merge_checker_func_t) do_inherit_constant_check, iface);
+ zend_hash_apply_with_arguments(&iface->constants_table TSRMLS_CC, (apply_func_args_t)do_inherit_iface_constant, 2, ce, iface);
zend_hash_merge_ex(&ce->function_table, &iface->function_table, do_inherit_method, (merge_checker_func_t) do_inherit_method_check, ce);
do_implement_interface(ce, iface TSRMLS_CC);
diff --git a/Zend/zend_constants.c b/Zend/zend_constants.c
index 8227f185d4..964c7f8165 100644
--- a/Zend/zend_constants.c
+++ b/Zend/zend_constants.c
@@ -379,6 +379,8 @@ ZEND_API int zend_get_constant_ex(const char *name, uint name_len, zval *result,
if ((flags & ZEND_FETCH_CLASS_SILENT) == 0) {
zend_error(E_ERROR, "Undefined class constant '%s::%s'", class_name->val, constant_name->val);
}
+ } else if (Z_ISREF_P(ret_constant)) {
+ ret_constant = Z_REFVAL_P(ret_constant);
}
} else if (!ce) {
retval = 0;
diff --git a/Zend/zend_objects.c b/Zend/zend_objects.c
index 37423b3dd8..390d6fc026 100644
--- a/Zend/zend_objects.c
+++ b/Zend/zend_objects.c
@@ -165,7 +165,7 @@ ZEND_API void zend_objects_clone_members(zend_object *new_object, zend_object *o
ZVAL_INDIRECT(&new_prop, new_object->properties_table + (Z_INDIRECT_P(prop) - old_object->properties_table));
} else {
ZVAL_COPY_VALUE(&new_prop, prop);
- zval_add_ref_unref(&new_prop);
+ zval_add_ref(&new_prop);
}
switch (zend_hash_get_current_key_ex(old_object->properties, &key, &num_key, 0, &pos)) {
case HASH_KEY_IS_STRING:
diff --git a/Zend/zend_types.h b/Zend/zend_types.h
index 8baf8643af..4390d99232 100644
--- a/Zend/zend_types.h
+++ b/Zend/zend_types.h
@@ -568,6 +568,15 @@ static inline zend_uchar zval_get_type(const zval* pz) {
Z_TYPE_INFO_P(z) = IS_REFERENCE_EX; \
} while (0)
+#define ZVAL_NEW_PERSISTENT_REF(z, r) do { \
+ zend_reference *_ref = malloc(sizeof(zend_reference)); \
+ GC_REFCOUNT(_ref) = 1; \
+ GC_TYPE_INFO(_ref) = IS_REFERENCE; \
+ ZVAL_COPY_VALUE(&_ref->val, r); \
+ Z_REF_P(z) = _ref; \
+ Z_TYPE_INFO_P(z) = IS_REFERENCE_EX; \
+ } while (0)
+
#define ZVAL_NEW_AST(z, a) do { \
zval *__z = (z); \
zend_ast_ref *_ast = emalloc(sizeof(zend_ast_ref)); \
diff --git a/Zend/zend_variables.c b/Zend/zend_variables.c
index 24e347a15b..9661af1773 100644
--- a/Zend/zend_variables.c
+++ b/Zend/zend_variables.c
@@ -161,6 +161,13 @@ ZEND_API void _zval_internal_dtor(zval *zvalue ZEND_FILE_LINE_DC)
case IS_RESOURCE:
zend_error(E_CORE_ERROR, "Internal zval's can't be arrays, objects or resources");
break;
+ case IS_REFERENCE: {
+ zend_reference *ref = (zend_reference*)Z_REF_P(zvalue);
+
+ zval_internal_ptr_dtor(&ref->val);
+ free(ref);
+ break;
+ }
case IS_LONG:
case IS_DOUBLE:
case IS_BOOL:
@@ -185,6 +192,13 @@ ZEND_API void _zval_internal_dtor_for_ptr(zval *zvalue ZEND_FILE_LINE_DC)
case IS_RESOURCE:
zend_error(E_CORE_ERROR, "Internal zval's can't be arrays, objects or resources");
break;
+ case IS_REFERENCE: {
+ zend_reference *ref = (zend_reference*)Z_REF_P(zvalue);
+
+ zval_internal_ptr_dtor(&ref->val);
+ free(ref);
+ break;
+ }
case IS_LONG:
case IS_DOUBLE:
case IS_BOOL:
@@ -210,12 +224,7 @@ ZEND_API void zval_add_ref_unref(zval *p)
{
if (Z_REFCOUNTED_P(p)) {
if (Z_ISREF_P(p)) {
- if (Z_REFCOUNT_P(p) == 1) {
- zval *q = Z_REFVAL_P(p);
- ZVAL_DUP(p, q);
- } else {
- Z_ADDREF_P(p);
- }
+ ZVAL_DUP(p, Z_REFVAL_P(p));
} else {
Z_ADDREF_P(p);
}
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index dbb89e6e63..610b46c58e 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -3693,6 +3693,9 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
}
if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(opline->op2.zv))) != NULL)) {
+ if (Z_ISREF_P(value)) {
+ value = Z_REFVAL_P(value);
+ }
if (Z_CONSTANT_P(value)) {
zend_class_entry *old_scope = EG(scope);
@@ -4005,6 +4008,7 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR)
zval tmp, *varname;
HashTable *target_symbol_table;
zend_free_op free_op1;
+ zend_bool tmp_is_dup = 0;
SAVE_OPLINE();
if (OP1_TYPE == IS_CV &&
@@ -4023,8 +4027,10 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR)
ZVAL_DUP(&tmp, varname);
convert_to_string(&tmp);
varname = &tmp;
+ tmp_is_dup = 1;
} else if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) {
- if (Z_REFCOUNTED_P(varname)) Z_ADDREF_P(varname);
+ ZVAL_COPY(&tmp, varname);
+ varname = &tmp;
}
if (OP2_TYPE != IS_UNUSED) {
@@ -4036,10 +4042,10 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR)
} else {
ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
- if (OP1_TYPE != IS_CONST && varname == &tmp) {
+ if (OP1_TYPE != IS_CONST && tmp_is_dup) {
zval_dtor(&tmp);
} else if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) {
- zval_ptr_dtor(varname);
+ zval_ptr_dtor(&tmp);
}
FREE_OP1();
HANDLE_EXCEPTION();
@@ -4058,10 +4064,10 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR)
zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
}
- if (OP1_TYPE != IS_CONST && varname == &tmp) {
+ if (OP1_TYPE != IS_CONST && tmp_is_dup) {
zval_dtor(&tmp);
} else if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) {
- zval_ptr_dtor(varname);
+ zval_ptr_dtor(&tmp);
}
FREE_OP1();
CHECK_EXCEPTION();
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 643ebd644f..a6d1be2270 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -3890,6 +3890,9 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCO
}
if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(opline->op2.zv))) != NULL)) {
+ if (Z_ISREF_P(value)) {
+ value = Z_REFVAL_P(value);
+ }
if (Z_CONSTANT_P(value)) {
zend_class_entry *old_scope = EG(scope);
@@ -4013,6 +4016,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HA
zval tmp, *varname;
HashTable *target_symbol_table;
+ zend_bool tmp_is_dup = 0;
SAVE_OPLINE();
if (IS_CONST == IS_CV &&
@@ -4031,8 +4035,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HA
ZVAL_DUP(&tmp, varname);
convert_to_string(&tmp);
varname = &tmp;
+ tmp_is_dup = 1;
} else if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
- if (Z_REFCOUNTED_P(varname)) Z_ADDREF_P(varname);
+ ZVAL_COPY(&tmp, varname);
+ varname = &tmp;
}
if (IS_CONST != IS_UNUSED) {
@@ -4044,10 +4050,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HA
} else {
ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
- if (IS_CONST != IS_CONST && varname == &tmp) {
+ if (IS_CONST != IS_CONST && tmp_is_dup) {
zval_dtor(&tmp);
} else if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
- zval_ptr_dtor(varname);
+ zval_ptr_dtor(&tmp);
}
HANDLE_EXCEPTION();
@@ -4066,10 +4072,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HA
zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
}
- if (IS_CONST != IS_CONST && varname == &tmp) {
+ if (IS_CONST != IS_CONST && tmp_is_dup) {
zval_dtor(&tmp);
} else if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
- zval_ptr_dtor(varname);
+ zval_ptr_dtor(&tmp);
}
CHECK_EXCEPTION();
@@ -5650,6 +5656,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HAND
zval tmp, *varname;
HashTable *target_symbol_table;
+ zend_bool tmp_is_dup = 0;
SAVE_OPLINE();
if (IS_CONST == IS_CV &&
@@ -5668,8 +5675,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HAND
ZVAL_DUP(&tmp, varname);
convert_to_string(&tmp);
varname = &tmp;
+ tmp_is_dup = 1;
} else if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
- if (Z_REFCOUNTED_P(varname)) Z_ADDREF_P(varname);
+ ZVAL_COPY(&tmp, varname);
+ varname = &tmp;
}
if (IS_VAR != IS_UNUSED) {
@@ -5681,10 +5690,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HAND
} else {
ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
- if (IS_CONST != IS_CONST && varname == &tmp) {
+ if (IS_CONST != IS_CONST && tmp_is_dup) {
zval_dtor(&tmp);
} else if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
- zval_ptr_dtor(varname);
+ zval_ptr_dtor(&tmp);
}
HANDLE_EXCEPTION();
@@ -5703,10 +5712,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HAND
zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
}
- if (IS_CONST != IS_CONST && varname == &tmp) {
+ if (IS_CONST != IS_CONST && tmp_is_dup) {
zval_dtor(&tmp);
} else if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
- zval_ptr_dtor(varname);
+ zval_ptr_dtor(&tmp);
}
CHECK_EXCEPTION();
@@ -6290,6 +6299,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_H
zval tmp, *varname;
HashTable *target_symbol_table;
+ zend_bool tmp_is_dup = 0;
SAVE_OPLINE();
if (IS_CONST == IS_CV &&
@@ -6308,8 +6318,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_H
ZVAL_DUP(&tmp, varname);
convert_to_string(&tmp);
varname = &tmp;
+ tmp_is_dup = 1;
} else if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
- if (Z_REFCOUNTED_P(varname)) Z_ADDREF_P(varname);
+ ZVAL_COPY(&tmp, varname);
+ varname = &tmp;
}
if (IS_UNUSED != IS_UNUSED) {
@@ -6321,10 +6333,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_H
} else {
ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
- if (IS_CONST != IS_CONST && varname == &tmp) {
+ if (IS_CONST != IS_CONST && tmp_is_dup) {
zval_dtor(&tmp);
} else if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
- zval_ptr_dtor(varname);
+ zval_ptr_dtor(&tmp);
}
HANDLE_EXCEPTION();
@@ -6343,10 +6355,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_H
zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
}
- if (IS_CONST != IS_CONST && varname == &tmp) {
+ if (IS_CONST != IS_CONST && tmp_is_dup) {
zval_dtor(&tmp);
} else if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
- zval_ptr_dtor(varname);
+ zval_ptr_dtor(&tmp);
}
CHECK_EXCEPTION();
@@ -8944,6 +8956,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HAND
zval tmp, *varname;
HashTable *target_symbol_table;
zend_free_op free_op1;
+ zend_bool tmp_is_dup = 0;
SAVE_OPLINE();
if (IS_TMP_VAR == IS_CV &&
@@ -8962,8 +8975,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HAND
ZVAL_DUP(&tmp, varname);
convert_to_string(&tmp);
varname = &tmp;
+ tmp_is_dup = 1;
} else if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
- if (Z_REFCOUNTED_P(varname)) Z_ADDREF_P(varname);
+ ZVAL_COPY(&tmp, varname);
+ varname = &tmp;
}
if (IS_CONST != IS_UNUSED) {
@@ -8975,10 +8990,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HAND
} else {
ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
- if (IS_TMP_VAR != IS_CONST && varname == &tmp) {
+ if (IS_TMP_VAR != IS_CONST && tmp_is_dup) {
zval_dtor(&tmp);
} else if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
- zval_ptr_dtor(varname);
+ zval_ptr_dtor(&tmp);
}
zval_dtor(free_op1.var);
HANDLE_EXCEPTION();
@@ -8997,10 +9012,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HAND
zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
}
- if (IS_TMP_VAR != IS_CONST && varname == &tmp) {
+ if (IS_TMP_VAR != IS_CONST && tmp_is_dup) {
zval_dtor(&tmp);
} else if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
- zval_ptr_dtor(varname);
+ zval_ptr_dtor(&tmp);
}
zval_dtor(free_op1.var);
CHECK_EXCEPTION();
@@ -10545,6 +10560,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLE
zval tmp, *varname;
HashTable *target_symbol_table;
zend_free_op free_op1;
+ zend_bool tmp_is_dup = 0;
SAVE_OPLINE();
if (IS_TMP_VAR == IS_CV &&
@@ -10563,8 +10579,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLE
ZVAL_DUP(&tmp, varname);
convert_to_string(&tmp);
varname = &tmp;
+ tmp_is_dup = 1;
} else if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
- if (Z_REFCOUNTED_P(varname)) Z_ADDREF_P(varname);
+ ZVAL_COPY(&tmp, varname);
+ varname = &tmp;
}
if (IS_VAR != IS_UNUSED) {
@@ -10576,10 +10594,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLE
} else {
ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
- if (IS_TMP_VAR != IS_CONST && varname == &tmp) {
+ if (IS_TMP_VAR != IS_CONST && tmp_is_dup) {
zval_dtor(&tmp);
} else if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
- zval_ptr_dtor(varname);
+ zval_ptr_dtor(&tmp);
}
zval_dtor(free_op1.var);
HANDLE_EXCEPTION();
@@ -10598,10 +10616,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLE
zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
}
- if (IS_TMP_VAR != IS_CONST && varname == &tmp) {
+ if (IS_TMP_VAR != IS_CONST && tmp_is_dup) {
zval_dtor(&tmp);
} else if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
- zval_ptr_dtor(varname);
+ zval_ptr_dtor(&tmp);
}
zval_dtor(free_op1.var);
CHECK_EXCEPTION();
@@ -11071,6 +11089,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HAN
zval tmp, *varname;
HashTable *target_symbol_table;
zend_free_op free_op1;
+ zend_bool tmp_is_dup = 0;
SAVE_OPLINE();
if (IS_TMP_VAR == IS_CV &&
@@ -11089,8 +11108,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HAN
ZVAL_DUP(&tmp, varname);
convert_to_string(&tmp);
varname = &tmp;
+ tmp_is_dup = 1;
} else if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
- if (Z_REFCOUNTED_P(varname)) Z_ADDREF_P(varname);
+ ZVAL_COPY(&tmp, varname);
+ varname = &tmp;
}
if (IS_UNUSED != IS_UNUSED) {
@@ -11102,10 +11123,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HAN
} else {
ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
- if (IS_TMP_VAR != IS_CONST && varname == &tmp) {
+ if (IS_TMP_VAR != IS_CONST && tmp_is_dup) {
zval_dtor(&tmp);
} else if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
- zval_ptr_dtor(varname);
+ zval_ptr_dtor(&tmp);
}
zval_dtor(free_op1.var);
HANDLE_EXCEPTION();
@@ -11124,10 +11145,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HAN
zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
}
- if (IS_TMP_VAR != IS_CONST && varname == &tmp) {
+ if (IS_TMP_VAR != IS_CONST && tmp_is_dup) {
zval_dtor(&tmp);
} else if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
- zval_ptr_dtor(varname);
+ zval_ptr_dtor(&tmp);
}
zval_dtor(free_op1.var);
CHECK_EXCEPTION();
@@ -15143,6 +15164,9 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE
}
if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(opline->op2.zv))) != NULL)) {
+ if (Z_ISREF_P(value)) {
+ value = Z_REFVAL_P(value);
+ }
if (Z_CONSTANT_P(value)) {
zend_class_entry *old_scope = EG(scope);
@@ -15266,6 +15290,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND
zval tmp, *varname;
HashTable *target_symbol_table;
zend_free_op free_op1;
+ zend_bool tmp_is_dup = 0;
SAVE_OPLINE();
if (IS_VAR == IS_CV &&
@@ -15284,8 +15309,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND
ZVAL_DUP(&tmp, varname);
convert_to_string(&tmp);
varname = &tmp;
+ tmp_is_dup = 1;
} else if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
- if (Z_REFCOUNTED_P(varname)) Z_ADDREF_P(varname);
+ ZVAL_COPY(&tmp, varname);
+ varname = &tmp;
}
if (IS_CONST != IS_UNUSED) {
@@ -15297,10 +15324,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND
} else {
ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
- if (IS_VAR != IS_CONST && varname == &tmp) {
+ if (IS_VAR != IS_CONST && tmp_is_dup) {
zval_dtor(&tmp);
} else if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
- zval_ptr_dtor(varname);
+ zval_ptr_dtor(&tmp);
}
zval_ptr_dtor_nogc(free_op1.var);
HANDLE_EXCEPTION();
@@ -15319,10 +15346,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND
zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
}
- if (IS_VAR != IS_CONST && varname == &tmp) {
+ if (IS_VAR != IS_CONST && tmp_is_dup) {
zval_dtor(&tmp);
} else if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
- zval_ptr_dtor(varname);
+ zval_ptr_dtor(&tmp);
}
zval_ptr_dtor_nogc(free_op1.var);
CHECK_EXCEPTION();
@@ -19691,6 +19718,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE
zval tmp, *varname;
HashTable *target_symbol_table;
zend_free_op free_op1;
+ zend_bool tmp_is_dup = 0;
SAVE_OPLINE();
if (IS_VAR == IS_CV &&
@@ -19709,8 +19737,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE
ZVAL_DUP(&tmp, varname);
convert_to_string(&tmp);
varname = &tmp;
+ tmp_is_dup = 1;
} else if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
- if (Z_REFCOUNTED_P(varname)) Z_ADDREF_P(varname);
+ ZVAL_COPY(&tmp, varname);
+ varname = &tmp;
}
if (IS_VAR != IS_UNUSED) {
@@ -19722,10 +19752,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE
} else {
ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
- if (IS_VAR != IS_CONST && varname == &tmp) {
+ if (IS_VAR != IS_CONST && tmp_is_dup) {
zval_dtor(&tmp);
} else if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
- zval_ptr_dtor(varname);
+ zval_ptr_dtor(&tmp);
}
zval_ptr_dtor_nogc(free_op1.var);
HANDLE_EXCEPTION();
@@ -19744,10 +19774,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE
zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
}
- if (IS_VAR != IS_CONST && varname == &tmp) {
+ if (IS_VAR != IS_CONST && tmp_is_dup) {
zval_dtor(&tmp);
} else if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
- zval_ptr_dtor(varname);
+ zval_ptr_dtor(&tmp);
}
zval_ptr_dtor_nogc(free_op1.var);
CHECK_EXCEPTION();
@@ -21114,6 +21144,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HAN
zval tmp, *varname;
HashTable *target_symbol_table;
zend_free_op free_op1;
+ zend_bool tmp_is_dup = 0;
SAVE_OPLINE();
if (IS_VAR == IS_CV &&
@@ -21132,8 +21163,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HAN
ZVAL_DUP(&tmp, varname);
convert_to_string(&tmp);
varname = &tmp;
+ tmp_is_dup = 1;
} else if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
- if (Z_REFCOUNTED_P(varname)) Z_ADDREF_P(varname);
+ ZVAL_COPY(&tmp, varname);
+ varname = &tmp;
}
if (IS_UNUSED != IS_UNUSED) {
@@ -21145,10 +21178,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HAN
} else {
ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
- if (IS_VAR != IS_CONST && varname == &tmp) {
+ if (IS_VAR != IS_CONST && tmp_is_dup) {
zval_dtor(&tmp);
} else if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
- zval_ptr_dtor(varname);
+ zval_ptr_dtor(&tmp);
}
zval_ptr_dtor_nogc(free_op1.var);
HANDLE_EXCEPTION();
@@ -21167,10 +21200,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HAN
zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
}
- if (IS_VAR != IS_CONST && varname == &tmp) {
+ if (IS_VAR != IS_CONST && tmp_is_dup) {
zval_dtor(&tmp);
} else if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
- zval_ptr_dtor(varname);
+ zval_ptr_dtor(&tmp);
}
zval_ptr_dtor_nogc(free_op1.var);
CHECK_EXCEPTION();
@@ -24567,6 +24600,9 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPC
}
if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(opline->op2.zv))) != NULL)) {
+ if (Z_ISREF_P(value)) {
+ value = Z_REFVAL_P(value);
+ }
if (Z_CONSTANT_P(value)) {
zend_class_entry *old_scope = EG(scope);
@@ -32432,6 +32468,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL
zval tmp, *varname;
HashTable *target_symbol_table;
+ zend_bool tmp_is_dup = 0;
SAVE_OPLINE();
if (IS_CV == IS_CV &&
@@ -32450,8 +32487,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL
ZVAL_DUP(&tmp, varname);
convert_to_string(&tmp);
varname = &tmp;
+ tmp_is_dup = 1;
} else if (IS_CV == IS_VAR || IS_CV == IS_CV) {
- if (Z_REFCOUNTED_P(varname)) Z_ADDREF_P(varname);
+ ZVAL_COPY(&tmp, varname);
+ varname = &tmp;
}
if (IS_CONST != IS_UNUSED) {
@@ -32463,10 +32502,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL
} else {
ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
- if (IS_CV != IS_CONST && varname == &tmp) {
+ if (IS_CV != IS_CONST && tmp_is_dup) {
zval_dtor(&tmp);
} else if (IS_CV == IS_VAR || IS_CV == IS_CV) {
- zval_ptr_dtor(varname);
+ zval_ptr_dtor(&tmp);
}
HANDLE_EXCEPTION();
@@ -32485,10 +32524,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL
zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
}
- if (IS_CV != IS_CONST && varname == &tmp) {
+ if (IS_CV != IS_CONST && tmp_is_dup) {
zval_dtor(&tmp);
} else if (IS_CV == IS_VAR || IS_CV == IS_CV) {
- zval_ptr_dtor(varname);
+ zval_ptr_dtor(&tmp);
}
CHECK_EXCEPTION();
@@ -36614,6 +36653,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER
zval tmp, *varname;
HashTable *target_symbol_table;
+ zend_bool tmp_is_dup = 0;
SAVE_OPLINE();
if (IS_CV == IS_CV &&
@@ -36632,8 +36672,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER
ZVAL_DUP(&tmp, varname);
convert_to_string(&tmp);
varname = &tmp;
+ tmp_is_dup = 1;
} else if (IS_CV == IS_VAR || IS_CV == IS_CV) {
- if (Z_REFCOUNTED_P(varname)) Z_ADDREF_P(varname);
+ ZVAL_COPY(&tmp, varname);
+ varname = &tmp;
}
if (IS_VAR != IS_UNUSED) {
@@ -36645,10 +36687,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER
} else {
ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
- if (IS_CV != IS_CONST && varname == &tmp) {
+ if (IS_CV != IS_CONST && tmp_is_dup) {
zval_dtor(&tmp);
} else if (IS_CV == IS_VAR || IS_CV == IS_CV) {
- zval_ptr_dtor(varname);
+ zval_ptr_dtor(&tmp);
}
HANDLE_EXCEPTION();
@@ -36667,10 +36709,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER
zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
}
- if (IS_CV != IS_CONST && varname == &tmp) {
+ if (IS_CV != IS_CONST && tmp_is_dup) {
zval_dtor(&tmp);
} else if (IS_CV == IS_VAR || IS_CV == IS_CV) {
- zval_ptr_dtor(varname);
+ zval_ptr_dtor(&tmp);
}
CHECK_EXCEPTION();
@@ -37919,6 +37961,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAND
zval tmp, *varname;
HashTable *target_symbol_table;
+ zend_bool tmp_is_dup = 0;
SAVE_OPLINE();
if (IS_CV == IS_CV &&
@@ -37937,8 +37980,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAND
ZVAL_DUP(&tmp, varname);
convert_to_string(&tmp);
varname = &tmp;
+ tmp_is_dup = 1;
} else if (IS_CV == IS_VAR || IS_CV == IS_CV) {
- if (Z_REFCOUNTED_P(varname)) Z_ADDREF_P(varname);
+ ZVAL_COPY(&tmp, varname);
+ varname = &tmp;
}
if (IS_UNUSED != IS_UNUSED) {
@@ -37950,10 +37995,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAND
} else {
ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
- if (IS_CV != IS_CONST && varname == &tmp) {
+ if (IS_CV != IS_CONST && tmp_is_dup) {
zval_dtor(&tmp);
} else if (IS_CV == IS_VAR || IS_CV == IS_CV) {
- zval_ptr_dtor(varname);
+ zval_ptr_dtor(&tmp);
}
HANDLE_EXCEPTION();
@@ -37972,10 +38017,10 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAND
zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
}
- if (IS_CV != IS_CONST && varname == &tmp) {
+ if (IS_CV != IS_CONST && tmp_is_dup) {
zval_dtor(&tmp);
} else if (IS_CV == IS_VAR || IS_CV == IS_CV) {
- zval_ptr_dtor(varname);
+ zval_ptr_dtor(&tmp);
}
CHECK_EXCEPTION();
diff --git a/ext/opcache/Optimizer/pass1_5.c b/ext/opcache/Optimizer/pass1_5.c
index 3bf59be84b..9edff53d39 100644
--- a/ext/opcache/Optimizer/pass1_5.c
+++ b/ext/opcache/Optimizer/pass1_5.c
@@ -294,6 +294,7 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
if ((c = zend_hash_find(&ce->constants_table,
Z_STR(ZEND_OP2_LITERAL(opline)))) != NULL) {
+ ZVAL_DEREF(c);
if (ZEND_IS_CONSTANT_TYPE(Z_TYPE_P(c))) {
if (!zend_get_persistent_constant(Z_STR_P(c), &t, 1 TSRMLS_CC) ||
ZEND_IS_CONSTANT_TYPE(Z_TYPE(t))) {
diff --git a/ext/opcache/zend_accelerator_util_funcs.c b/ext/opcache/zend_accelerator_util_funcs.c
index 6df81e6ee6..61d662a4f8 100644
--- a/ext/opcache/zend_accelerator_util_funcs.c
+++ b/ext/opcache/zend_accelerator_util_funcs.c
@@ -692,7 +692,7 @@ static void zend_class_copy_ctor(zend_class_entry **pce)
zend_hash_clone_prop_info(&ce->properties_info, &old_ce->properties_info, old_ce, ce TSRMLS_CC);
/* constants table */
- zend_hash_clone_zval(&ce->constants_table, &old_ce->constants_table, 0);
+ zend_hash_clone_zval(&ce->constants_table, &old_ce->constants_table, 1);
ce->name = STR_DUP(ce->name, 0);
diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c
index 1ef849f92a..224bec75ba 100644
--- a/ext/reflection/php_reflection.c
+++ b/ext/reflection/php_reflection.c
@@ -4010,7 +4010,7 @@ ZEND_METHOD(reflection_class, getConstants)
GET_REFLECTION_OBJECT_PTR(ce);
array_init(return_value);
zend_hash_apply_with_argument(&ce->constants_table, (apply_func_arg_t)zval_update_constant_inline_change, ce TSRMLS_CC);
- zend_hash_copy(Z_ARRVAL_P(return_value), &ce->constants_table, zval_add_ref);
+ zend_hash_copy(Z_ARRVAL_P(return_value), &ce->constants_table, zval_add_ref_unref);
}
/* }}} */
diff --git a/ext/standard/array.c b/ext/standard/array.c
index 4f32345630..bef42feaac 100644
--- a/ext/standard/array.c
+++ b/ext/standard/array.c
@@ -1081,23 +1081,21 @@ static int php_array_walk(HashTable *target_hash, zval *userdata, int recursive
continue;
}
}
- ZVAL_COPY(&args[0], zv);
if (recursive &&
- (Z_TYPE(args[0]) == IS_ARRAY ||
- (Z_ISREF(args[0]) && Z_TYPE_P(Z_REFVAL(args[0])) == IS_ARRAY))) {
+ (Z_TYPE_P(zv) == IS_ARRAY ||
+ (Z_ISREF_P(zv) && Z_TYPE_P(Z_REFVAL_P(zv)) == IS_ARRAY))) {
HashTable *thash;
zend_fcall_info orig_array_walk_fci;
zend_fcall_info_cache orig_array_walk_fci_cache;
- if (Z_ISREF(args[0])) {
- thash = Z_ARRVAL_P(Z_REFVAL(args[0]));
+ if (Z_ISREF_P(zv)) {
+ thash = Z_ARRVAL_P(Z_REFVAL_P(zv));
} else {
- SEPARATE_ZVAL(&args[0]);
- thash = Z_ARRVAL(args[0]);
+ SEPARATE_ZVAL(zv);
+ thash = Z_ARRVAL_P(zv);
}
if (thash->nApplyCount > 1) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "recursion detected");
- zval_ptr_dtor(&args[0]);
if (userdata) {
zval_ptr_dtor(&args[2]);
}
@@ -1116,11 +1114,25 @@ static int php_array_walk(HashTable *target_hash, zval *userdata, int recursive
BG(array_walk_fci) = orig_array_walk_fci;
BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
} else {
+ int was_ref = Z_ISREF_P(zv);
+
+ ZVAL_COPY(&args[0], zv);
+
/* Allocate space for key */
zend_hash_get_current_key_zval(target_hash, &args[1]);
/* Call the userland function */
if (zend_call_function(&BG(array_walk_fci), &BG(array_walk_fci_cache) TSRMLS_CC) == SUCCESS) {
+ if (!was_ref && Z_ISREF(args[0])) {
+ /* copy reference back */
+ zval garbage;
+
+ ZVAL_COPY_VALUE(&garbage, zv);
+ ZVAL_COPY_VALUE(zv, &args[0]);
+ zval_ptr_dtor(&garbage);
+ } else {
+ zval_ptr_dtor(&args[0]);
+ }
zval_ptr_dtor(&retval);
} else {
zval_ptr_dtor(&args[0]);
@@ -1132,7 +1144,6 @@ static int php_array_walk(HashTable *target_hash, zval *userdata, int recursive
}
}
- zval_ptr_dtor(&args[0]);
if (Z_TYPE(args[1]) != IS_UNDEF) {
zval_ptr_dtor(&args[1]);
ZVAL_UNDEF(&args[1]);