mirror of
https://github.com/php/php-src.git
synced 2024-11-24 10:24:11 +08:00
Fixed bug #39346 (Unsetting a static variable inside a destructor causes segfault later on)
This commit is contained in:
parent
fa1e1d249b
commit
ab5bddd976
2
NEWS
2
NEWS
@ -91,6 +91,8 @@ PHP NEWS
|
||||
- Fixed bug #39700 (NUMERIC error when result precision are 7,8 or 12-14 ).
|
||||
(Lars W)
|
||||
- Fixed bug #39397 (invalid statement handle in Unknown on line 0). (Lars W)
|
||||
- Fixed bug #39346 (Unsetting a static variable inside a destructor causes
|
||||
segfault later on). (Dmitry)
|
||||
- Fixed bug #39056 (Interbase NUMERIC data type error). (Lars W)
|
||||
- Fixed bug #38468 (Unexpected creation of cycle). (Dmitry)
|
||||
- Fixed bug #37911 (preg_replace_callback() ignores named groups). (Nuno)
|
||||
|
@ -5,17 +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)
|
||||
}
|
||||
NULL
|
||||
|
26
Zend/tests/bug39346.phpt
Normal file
26
Zend/tests/bug39346.phpt
Normal file
@ -0,0 +1,26 @@
|
||||
--TEST--
|
||||
Bug #39346 (Unsetting a static variable inside a destructor causes segfault later on)
|
||||
--FILE--
|
||||
<?php
|
||||
class test
|
||||
{
|
||||
protected $_id;
|
||||
static $instances;
|
||||
|
||||
public function __construct($id) {
|
||||
$this->_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
|
@ -691,6 +691,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) {
|
||||
@ -716,7 +717,6 @@ static inline zval* zend_assign_to_variable(zval **variable_ptr_ptr, zval *value
|
||||
} else 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);
|
||||
@ -756,7 +756,6 @@ static inline zval* zend_assign_to_variable(zval **variable_ptr_ptr, zval *value
|
||||
} else 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);
|
||||
@ -778,23 +777,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) {
|
||||
|
Loading…
Reference in New Issue
Block a user