summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikic@php.net>2016-04-12 14:39:05 +0200
committerNikita Popov <nikic@php.net>2016-04-12 14:44:29 +0200
commit4e585eb42941cead2a1a3f9824c84d03af621391 (patch)
tree484d543175afdbf9a971e26caab1211069f78823
parent6a2eee520accd26b2b2388ff433887f21f892690 (diff)
downloadphp-git-4e585eb42941cead2a1a3f9824c84d03af621391.tar.gz
Fix ZEND_SEPARATE for by-val func returning ref zval
-rw-r--r--Zend/tests/modify_isref_value_return.phpt25
-rw-r--r--Zend/zend_vm_def.h3
-rw-r--r--Zend/zend_vm_execute.h3
3 files changed, 31 insertions, 0 deletions
diff --git a/Zend/tests/modify_isref_value_return.phpt b/Zend/tests/modify_isref_value_return.phpt
new file mode 100644
index 0000000000..1b3122711e
--- /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--
+<?php
+
+class A {
+ public $b;
+}
+
+$arr = [];
+
+$a = new A;
+$a->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 cabebe4ec2..05b6a9c8bf 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 b7f0e3c5ae..9f17756315 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));
}
}