]> granicus.if.org Git - php/commitdiff
Fixed bug #39297 (Memory corryption because of indirect modification of overloaded...
authorDmitry Stogov <dmitry@php.net>
Wed, 8 Nov 2006 13:38:44 +0000 (13:38 +0000)
committerDmitry Stogov <dmitry@php.net>
Wed, 8 Nov 2006 13:38:44 +0000 (13:38 +0000)
Zend/tests/bug39297.phpt [new file with mode: 0755]
Zend/zend_object_handlers.c

diff --git a/Zend/tests/bug39297.phpt b/Zend/tests/bug39297.phpt
new file mode 100755 (executable)
index 0000000..92f91a5
--- /dev/null
@@ -0,0 +1,45 @@
+--TEST--
+Bug #39297 (Memory corryption because of indirect modification of overloaded array)
+--FILE--
+<?php
+function compareByRef(&$first, &$second) {
+    return $first === $second;
+}
+
+class MyTree implements ArrayAccess {
+    public $parent;
+    public $children = array();
+
+    public function offsetExists($offset) {
+    }
+
+    public function offsetUnset($offset) {
+    }
+
+    public function offsetSet($offset, $value) {
+       echo "offsetSet()\n";
+        $cannonicalName = strtolower($offset);
+        $this->children[$cannonicalName] = $value;
+        $value->parent = $this;
+    }    
+    
+    public function offsetGet($offset) {
+       echo "offsetGet()\n";
+        $cannonicalName = strtolower($offset);
+        return $this->children[$cannonicalName];
+    }
+
+}
+
+$id = 'Test';
+
+$root = new MyTree();
+$child = new MyTree();
+$root[$id] = $child;
+
+var_dump(compareByRef($root[$id], $child));
+?>
+--EXPECT--
+offsetSet()
+offsetGet()
+bool(true)
index 79e64b25428f8a2c563320d690c7355f9655f119..03953182ea18e750b6c99d7320605f49158bf68d 100644 (file)
@@ -477,6 +477,19 @@ zval *zend_std_read_dimension(zval *object, zval *offset, int type TSRMLS_DC)
                /* Undo PZVAL_LOCK() */
                retval->refcount--;
 
+               if ((type == BP_VAR_W || type == BP_VAR_RW  || type == BP_VAR_UNSET) && retval->refcount > 0) {
+                       zval *tmp = retval;
+
+                       ALLOC_ZVAL(retval);
+                       *retval = *tmp;
+                       zval_copy_ctor(retval);
+                       retval->is_ref = 0;
+                       retval->refcount = 0;
+                       if (Z_TYPE_P(retval) != IS_OBJECT) {
+                               zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ce->name);
+                       }
+               }
+
                return retval;
        } else {
                zend_error(E_ERROR, "Cannot use object of type %v as array", ce->name);