]> granicus.if.org Git - php/commitdiff
Re-Fixed bug #70321 (Magic getter breaks reference to array property)
authorXinchen Hui <laruence@php.net>
Sun, 23 Aug 2015 03:40:49 +0000 (11:40 +0800)
committerXinchen Hui <laruence@php.net>
Sun, 23 Aug 2015 03:42:33 +0000 (11:42 +0800)
NEWS
Zend/tests/bug70321.phpt [new file with mode: 0644]
Zend/zend_execute.c

diff --git a/NEWS b/NEWS
index f92f2838e20efade4df03f7ad7ee5b1ce5b9a992..d401f5f5621d2ba1b963884ca9c79b235bf99a4c 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -3,9 +3,11 @@ PHP                                                                        NEWS
 03 Sep 2015, PHP 7.0.0 RC 2
 
 - Core:
-  . Fixed bug #70145 (From field incorrectly parsed from headers). (Anatol)
   . Fixed bug #70300 (Syntactical inconsistency with new group use syntax).
     (marcio dot web2 at gmail dot com)
+  . Fixed bug #70321 (Magic getter breaks reference to array property).
+    (Laruence)
+  . Fixed bug #70145 (From field incorrectly parsed from headers). (Anatol)
   . Fixed bug causing exception traces with anon classes to be truncated. (Bob)
 
 - PDO_OCI:
diff --git a/Zend/tests/bug70321.phpt b/Zend/tests/bug70321.phpt
new file mode 100644 (file)
index 0000000..19f691f
--- /dev/null
@@ -0,0 +1,49 @@
+--TEST--
+bug #70321 (Magic getter breaks reference to array property)
+--FILE--
+<?php
+class foo implements arrayAccess
+{
+       private $bar;
+       public function __construct()
+       {
+               $this->bar = new bar();
+       }
+       public function & __get($key)
+       {
+               $bar = $this->bar;
+               return $bar;
+       }
+
+       public function & offsetGet($key) {
+               $bar = $this->bar;
+               return $bar;
+       }
+       public function offsetSet($key, $val) {
+       }
+       public function offsetUnset($key) {
+       }
+       public function offsetExists($key) {
+       }
+}
+class bar { public $onBaz = []; }
+
+$foo = new foo();
+$foo->bar->onBaz[] = function() {};
+var_dump($foo->bar->onBaz);
+
+$foo = new foo();
+$foo["bar"]->onBaz[] = function() {};
+var_dump($foo->bar->onBaz);
+?>
+--EXPECTF--
+array(1) {
+  [0]=>
+  object(Closure)#%d (0) {
+  }
+}
+array(1) {
+  [0]=>
+  object(Closure)#%d (0) {
+  }
+}
index 59f936d2a374245f47082e243b1a96713d7a3d1d..76a2f21ce3c33809368e3ad41cc3e2a9012743a8 100644 (file)
@@ -1721,6 +1721,8 @@ convert_to_array:
                                                zend_class_entry *ce = Z_OBJCE_P(container);
                                                zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ZSTR_VAL(ce->name));
                                        }
+                               } else if (UNEXPECTED(Z_REFCOUNT_P(retval) == 1)) {
+                                       ZVAL_UNREF(retval);
                                }
                                if (result != retval) {
                                        ZVAL_INDIRECT(result, retval);
@@ -1925,6 +1927,8 @@ static zend_always_inline void zend_fetch_property_address(zval *result, zval *c
                                (ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type, cache_slot, result)) != NULL) {
                                if (ptr != result) {
                                        ZVAL_INDIRECT(result, ptr);
+                               } else if (UNEXPECTED(Z_ISREF_P(ptr) && Z_REFCOUNT_P(ptr) == 1)) {
+                                       ZVAL_UNREF(ptr);
                                }
                        } else {
                                zend_throw_error(NULL, "Cannot access undefined property for object with overloaded property access");
@@ -1937,6 +1941,8 @@ static zend_always_inline void zend_fetch_property_address(zval *result, zval *c
                zval *ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type, cache_slot, result);
                if (ptr != result) {
                        ZVAL_INDIRECT(result, ptr);
+               } else if (UNEXPECTED(Z_ISREF_P(ptr) && Z_REFCOUNT_P(ptr) == 1)) {
+                       ZVAL_UNREF(ptr);
                }
        } else {
                zend_error(E_WARNING, "This object doesn't support property references");