summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS4
-rw-r--r--Zend/tests/bug70321.phpt49
-rw-r--r--Zend/zend_execute.c6
3 files changed, 58 insertions, 1 deletions
diff --git a/NEWS b/NEWS
index f92f2838e2..d401f5f562 100644
--- 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
index 0000000000..19f691f418
--- /dev/null
+++ b/Zend/tests/bug70321.phpt
@@ -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) {
+ }
+}
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 59f936d2a3..76a2f21ce3 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -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");