From: Dmitry Stogov Date: Fri, 11 Jan 2008 08:42:19 +0000 (+0000) Subject: Fixed bug #39346 (Unsetting a static variable inside a destructor causes segfault... X-Git-Tag: RELEASE_2_0_0a1~947 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=350a3daee422424e821904c3766f686b6303b0b3;p=php Fixed bug #39346 (Unsetting a static variable inside a destructor causes segfault later on) --- diff --git a/Zend/tests/bug32799.phpt b/Zend/tests/bug32799.phpt index 18b5a1e8c6..c76daeddef 100755 --- a/Zend/tests/bug32799.phpt +++ b/Zend/tests/bug32799.phpt @@ -5,23 +5,17 @@ Bug #32799 (crash: calling the corresponding global var during the destruct) class test{ public $c=1; function __destruct (){ - $GLOBALS['p']->c++; // no warning - print $GLOBALS['p']->c."\n"; // segfault - var_dump($GLOBALS['p']); + if (!isset($GLOBALS['p'])) { + echo "NULL\n"; + } else { + $GLOBALS['p']->c++; // no warning + print $GLOBALS['p']->c."\n"; // segfault + var_dump($GLOBALS['p']); + } } } $p=new test; $p=null; //destroy the object by a new assignment (segfault) ?> --EXPECT-- -2 -object(test)#1 (1) { - ["c"]=> - int(2) -} ---UEXPECT-- -2 -object(test)#1 (1) { - [u"c"]=> - int(2) -} +NULL diff --git a/Zend/tests/bug39346.phpt b/Zend/tests/bug39346.phpt new file mode 100644 index 0000000000..4a614c9e9a --- /dev/null +++ b/Zend/tests/bug39346.phpt @@ -0,0 +1,26 @@ +--TEST-- +Bug #39346 (Unsetting a static variable inside a destructor causes segfault later on) +--FILE-- +_id = $id; + self::$instances[$this->_id] = $this; + } + + function __destruct() { + unset(self::$instances[$this->_id]); + } +} +$test = new test(2); +$test = new test(1); +$test = new test(2); +$test = new test(3); +echo "ok\n"; +?> +--EXPECT-- +ok diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index a37ed49c90..156c31f534 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -765,6 +765,7 @@ static inline void zend_assign_to_string_offset(temp_variable *T, zval *value, i static inline zval* zend_assign_to_variable(zval **variable_ptr_ptr, zval *value, int is_tmp_var TSRMLS_DC) /* {{{ */ { zval *variable_ptr = *variable_ptr_ptr; + zval garbage; if (variable_ptr == EG(error_zval_ptr)) { if (is_tmp_var) { @@ -781,7 +782,6 @@ static inline zval* zend_assign_to_variable(zval **variable_ptr_ptr, zval *value if (PZVAL_IS_REF(variable_ptr)) { if (variable_ptr!=value) { zend_uint refcount = Z_REFCOUNT_P(variable_ptr); - zval garbage; if (!is_tmp_var) { Z_ADDREF_P(value); @@ -803,23 +803,25 @@ static inline zval* zend_assign_to_variable(zval **variable_ptr_ptr, zval *value if (variable_ptr==value) { Z_ADDREF_P(variable_ptr); } else if (PZVAL_IS_REF(value)) { - zval tmp; - - tmp = *value; - zval_copy_ctor(&tmp); - Z_SET_REFCOUNT(tmp, 1); - zendi_zval_dtor(*variable_ptr); - *variable_ptr = tmp; + garbage = *variable_ptr; + *variable_ptr = *value; + INIT_PZVAL(variable_ptr); + zval_copy_ctor(variable_ptr); + zendi_zval_dtor(garbage); + return variable_ptr; } else { Z_ADDREF_P(value); + *variable_ptr_ptr = value; zendi_zval_dtor(*variable_ptr); safe_free_zval_ptr(variable_ptr); - *variable_ptr_ptr = value; + return value; } } else { - zendi_zval_dtor(*variable_ptr); - Z_SET_REFCOUNT_P(value, 1); + garbage = *variable_ptr; *variable_ptr = *value; + INIT_PZVAL(variable_ptr); + zendi_zval_dtor(garbage); + return variable_ptr; } } else { /* we need to split */ if (!is_tmp_var) {