]> granicus.if.org Git - php/commitdiff
Fix ZEND_SEPARATE for by-val func returning ref zval
authorNikita Popov <nikic@php.net>
Tue, 12 Apr 2016 12:39:05 +0000 (14:39 +0200)
committerNikita Popov <nikic@php.net>
Tue, 12 Apr 2016 12:44:29 +0000 (14:44 +0200)
Zend/tests/modify_isref_value_return.phpt [new file with mode: 0644]
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

diff --git a/Zend/tests/modify_isref_value_return.phpt b/Zend/tests/modify_isref_value_return.phpt
new file mode 100644 (file)
index 0000000..1b31227
--- /dev/null
@@ -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) {
+  }
+}
index cabebe4ec2af3a9d99b7b3cee6314213fb04ded0..05b6a9c8bf60dd7aee44d5c2085aa92434294465 100644 (file)
@@ -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));
                }
        }
 
index b7f0e3c5aeacf059b1870e91dc70c81ad02696b6..9f177563152954434bbbb0ccd40fbe5c5546b452 100644 (file)
@@ -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));
                }
        }