]> granicus.if.org Git - php/commitdiff
Fixed bug #74058
authorandrewnester <andrew.nester.dev@gmail.com>
Thu, 2 Mar 2017 13:59:32 +0000 (16:59 +0300)
committerNikita Popov <nikita.ppv@gmail.com>
Wed, 8 Mar 2017 23:10:00 +0000 (00:10 +0100)
Fall back from get_property_ptr_ptr to read_property if offsetGet
is overridden.

NEWS
ext/spl/spl_array.c
ext/spl/tests/bug74058.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 3df1bdfef9ec5a51dc817ec247050a4993a22ff3..3b6199f92a61d812b6a06440fd84ceb2564ed3a3 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,9 @@ PHP                                                                        NEWS
   . Fixed bug #74004 (LIBXML_NOWARNING flag ingnored on loadHTML*).
     (somedaysummer)
 
+- SPL:
+  . Fixed bug #74058 (ArrayObject can not notice changes). (Andrew Nester)
+
 16 Mar 2017, PHP 7.1.3
 
 - Core:
index d0cadcf16747c9eb1186a90efde201d4b56e59ff..8095c8cb1929432c72d48badd3f7ca6cd3d932d8 100644 (file)
@@ -901,6 +901,11 @@ static zval *spl_array_get_property_ptr_ptr(zval *object, zval *member, int type
 
        if ((intern->ar_flags & SPL_ARRAY_ARRAY_AS_PROPS) != 0
                && !std_object_handlers.has_property(object, member, 2, NULL)) {
+               /* If object has offsetGet() overridden, then fallback to read_property,
+                * which will call offsetGet(). */
+               if (intern->fptr_offset_get) {
+                       return NULL;
+               }
                return spl_array_get_dimension_ptr(1, intern, member, type);
        }
        return std_object_handlers.get_property_ptr_ptr(object, member, type, cache_slot);
diff --git a/ext/spl/tests/bug74058.phpt b/ext/spl/tests/bug74058.phpt
new file mode 100644 (file)
index 0000000..a416d8f
--- /dev/null
@@ -0,0 +1,81 @@
+--TEST--
+Bug #74058 (ArrayObject can not notice changes)
+--FILE--
+<?php
+
+class MyArrayObject extends ArrayObject
+{
+    public function __construct($input = [])
+    {
+        parent::__construct($input, ArrayObject::ARRAY_AS_PROPS);
+    }
+
+    public function offsetSet($x, $v)
+    {
+        echo "offsetSet('{$x}')\n";
+        return parent::offsetSet($x, $v);
+    }
+
+    public function offsetGet($x)
+    {
+        echo "offsetGet('{$x}')\n";
+        return parent::offsetGet($x);
+    }
+}
+
+class MyArray extends ArrayObject
+{
+    public function __construct($input = [])
+    {
+        parent::__construct($input);
+    }
+
+    public function offsetSet($x, $v)
+    {
+        echo "offsetSet('{$x}')\n";
+        return parent::offsetSet($x, $v);
+    }
+
+    public function offsetGet($x)
+    {
+        echo "offsetGet('{$x}')\n";
+        return parent::offsetGet($x);
+    }
+}
+
+$x = new MyArrayObject;
+$x->a1 = new stdClass();
+var_dump($x->a1);
+
+$x->a1->b = 'some value';
+var_dump($x->a1);
+
+$y = new MyArray();
+$y['a2'] = new stdClass();
+var_dump($y['a2']);
+
+$y['a2']->b = 'some value';
+var_dump($y['a2']);
+
+?>
+--EXPECTF--
+offsetSet('a1')
+offsetGet('a1')
+object(stdClass)#%s (0) {
+}
+offsetGet('a1')
+offsetGet('a1')
+object(stdClass)#%s (1) {
+  ["b"]=>
+  string(10) "some value"
+}
+offsetSet('a2')
+offsetGet('a2')
+object(stdClass)#%s (0) {
+}
+offsetGet('a2')
+offsetGet('a2')
+object(stdClass)#%s (1) {
+  ["b"]=>
+  string(10) "some value"
+}