From: Dmitry Stogov Date: Wed, 16 Nov 2005 11:52:27 +0000 (+0000) Subject: Fixed bug #35239 (Objects can lose references) X-Git-Tag: php-5.1.0RC5~5 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6b8bf3833334fd2b5b2dfa6e9437add717cfb132;p=php Fixed bug #35239 (Objects can lose references) --- diff --git a/NEWS b/NEWS index cd79b02912..0c423798fb 100644 --- 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 index 0000000000..7fc7b7d3b6 --- /dev/null +++ b/Zend/tests/bug35239.phpt @@ -0,0 +1,41 @@ +--TEST-- +Bug #35239 (Objects can lose references) +--FILE-- +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 diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index bbe056457a..d44a6ccca9 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -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) { diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index d1d413b211..a4b80db38b 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -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; } }