From 6a2eee520accd26b2b2388ff433887f21f892690 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 12 Apr 2016 14:33:56 +0200 Subject: [PATCH 1/2] Drop unnecessary ZEND_SEPARATE code The following write ops will separate if necessary. --- Zend/zend_vm_def.h | 4 +--- Zend/zend_vm_execute.h | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 8e658f5d889..cabebe4ec2a 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -7302,10 +7302,8 @@ ZEND_VM_HANDLER(156, ZEND_SEPARATE, VAR, UNUSED) if (UNEXPECTED(Z_REFCOUNT_P(var_ptr) == 1)) { ZVAL_UNREF(var_ptr); } - } else if (Z_COPYABLE_P(var_ptr) && Z_REFCOUNT_P(var_ptr) > 1) { - Z_DELREF_P(var_ptr); - ZVAL_DUP(EX_VAR(opline->op1.var), var_ptr); } + ZEND_VM_NEXT_OPCODE(); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index bdc1bd7df4d..b7f0e3c5aea 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -19510,10 +19510,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEPARATE_SPEC_VAR_UNUSED_HANDL if (UNEXPECTED(Z_REFCOUNT_P(var_ptr) == 1)) { ZVAL_UNREF(var_ptr); } - } else if (Z_COPYABLE_P(var_ptr) && Z_REFCOUNT_P(var_ptr) > 1) { - Z_DELREF_P(var_ptr); - ZVAL_DUP(EX_VAR(opline->op1.var), var_ptr); } + ZEND_VM_NEXT_OPCODE(); } From 4e585eb42941cead2a1a3f9824c84d03af621391 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 12 Apr 2016 14:39:05 +0200 Subject: [PATCH 2/2] Fix ZEND_SEPARATE for by-val func returning ref zval --- Zend/tests/modify_isref_value_return.phpt | 25 +++++++++++++++++++++++ Zend/zend_vm_def.h | 3 +++ Zend/zend_vm_execute.h | 3 +++ 3 files changed, 31 insertions(+) create mode 100644 Zend/tests/modify_isref_value_return.phpt diff --git a/Zend/tests/modify_isref_value_return.phpt b/Zend/tests/modify_isref_value_return.phpt new file mode 100644 index 00000000000..1b3122711ea --- /dev/null +++ b/Zend/tests/modify_isref_value_return.phpt @@ -0,0 +1,25 @@ +--TEST-- +Indirect modification of isref by-value return value not possible +--FILE-- +b =& $arr; + +(new ReflectionProperty('A', 'b'))->getValue($a)[] = 42; + +var_dump($a); + +?> +--EXPECT-- +object(A)#1 (1) { + ["b"]=> + &array(0) { + } +} diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index cabebe4ec2a..05b6a9c8bf6 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -7301,6 +7301,9 @@ ZEND_VM_HANDLER(156, ZEND_SEPARATE, VAR, UNUSED) if (UNEXPECTED(Z_ISREF_P(var_ptr))) { if (UNEXPECTED(Z_REFCOUNT_P(var_ptr) == 1)) { ZVAL_UNREF(var_ptr); + } else if (!(Z_VAR_FLAGS_P(var_ptr) & IS_VAR_RET_REF)) { + Z_DELREF_P(var_ptr); + ZVAL_COPY(var_ptr, Z_REFVAL_P(var_ptr)); } } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index b7f0e3c5aea..9f177563152 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -19509,6 +19509,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEPARATE_SPEC_VAR_UNUSED_HANDL if (UNEXPECTED(Z_ISREF_P(var_ptr))) { if (UNEXPECTED(Z_REFCOUNT_P(var_ptr) == 1)) { ZVAL_UNREF(var_ptr); + } else if (!(Z_VAR_FLAGS_P(var_ptr) & IS_VAR_RET_REF)) { + Z_DELREF_P(var_ptr); + ZVAL_COPY(var_ptr, Z_REFVAL_P(var_ptr)); } }