]> granicus.if.org Git - php/commitdiff
Fixed bug #35239 (Objects can lose references)
authorDmitry Stogov <dmitry@php.net>
Wed, 16 Nov 2005 11:52:27 +0000 (11:52 +0000)
committerDmitry Stogov <dmitry@php.net>
Wed, 16 Nov 2005 11:52:27 +0000 (11:52 +0000)
NEWS
Zend/tests/bug35239.phpt [new file with mode: 0755]
Zend/zend_execute.c
Zend/zend_object_handlers.c

diff --git a/NEWS b/NEWS
index cd79b02912df3b67fd1d9c62366c4ecc2fc929cf..0c423798fb93f107e8138453812134f7fc89aa66 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,7 @@ PHP                                                                        NEWS
 - Fixed bug in mysqli extension with unsigned int(11) being represented as 
   signed integer in PHP instead of string in 32bit systems. (Andrey)
 - Fixed initializing and argument checking for posix_mknod(). (Derick)
+- Fixed bug #35239 (Objects can lose references). (Dmitry)
 - Fixed bug #35229 (call_user_func() crashes when arguement_stack is nearly
   full). (Dmitry)
 - Fixed bug #35197 (Destructor is not called). (Tony)
diff --git a/Zend/tests/bug35239.phpt b/Zend/tests/bug35239.phpt
new file mode 100755 (executable)
index 0000000..7fc7b7d
--- /dev/null
@@ -0,0 +1,41 @@
+--TEST--
+Bug #35239 (Objects can lose references)
+--FILE--
+<?php
+$a = new stdClass; 
+$a->x0 = new stdClass;
+$a->x0->y0 = 'a';
+$a->x0->y1 =& $a->x0;
+$a->x0->y2 =& $a->x0;
+$a->x0->y0 = 'b';
+var_dump($a);
+$a->x0->y1 = "ok\n";
+echo $a->x0;
+?>
+--EXPECT--
+object(stdClass)#1 (1) {
+  ["x0"]=>
+  &object(stdClass)#2 (3) {
+    ["y0"]=>
+    string(1) "b"
+    ["y1"]=>
+    &object(stdClass)#2 (3) {
+      ["y0"]=>
+      string(1) "b"
+      ["y1"]=>
+      *RECURSION*
+      ["y2"]=>
+      *RECURSION*
+    }
+    ["y2"]=>
+    &object(stdClass)#2 (3) {
+      ["y0"]=>
+      string(1) "b"
+      ["y1"]=>
+      *RECURSION*
+      ["y2"]=>
+      *RECURSION*
+    }
+  }
+}
+ok
index bbe056457aa120c6d63de8dfe7b5e5e9628d3fd0..d44a6ccca946e46a5f36696f1db848903e5aba75 100644 (file)
@@ -1250,11 +1250,6 @@ static void zend_fetch_property_address(temp_variable *result, zval **container_
                return;
        }
                
-       if ((type==BP_VAR_W || type==BP_VAR_RW) && container->refcount>1 && !PZVAL_IS_REF(container)) {
-               SEPARATE_ZVAL(container_ptr);
-               container = *container_ptr;
-       }
-
        if (Z_OBJ_HT_P(container)->get_property_ptr_ptr) {
                zval **ptr_ptr = Z_OBJ_HT_P(container)->get_property_ptr_ptr(container, prop_ptr TSRMLS_CC);
                if(NULL == ptr_ptr) {
index d1d413b211da0d58ae961ffe75d2cc1a06f09ec5..a4b80db38b9e535cc1376afcbe5c8dd63348a5b2 100644 (file)
@@ -381,13 +381,15 @@ static void zend_std_write_property(zval *object, zval *member, zval *value TSRM
                        /* if we are assigning reference, we shouldn't move it, but instead assign variable
                           to the same pointer */
                        if (PZVAL_IS_REF(*variable_ptr)) {
-                               zval_dtor(*variable_ptr); /* old value should be destroyed */
+                               zval garbage = **variable_ptr; /* old value should be destroyed */
+
                                /* To check: can't *variable_ptr be some system variable like error_zval here? */
                                (*variable_ptr)->type = value->type;
                                (*variable_ptr)->value = value->value;
                                if (value->refcount>0) {
                                        zval_copy_ctor(*variable_ptr);
                                }
+                               zval_dtor(&garbage);
                                setter_done = 1;
                        }
                }