]> granicus.if.org Git - php/commitdiff
Fixed bug #39346 (Unsetting a static variable inside a destructor causes segfault...
authorDmitry Stogov <dmitry@php.net>
Fri, 11 Jan 2008 08:42:06 +0000 (08:42 +0000)
committerDmitry Stogov <dmitry@php.net>
Fri, 11 Jan 2008 08:42:06 +0000 (08:42 +0000)
NEWS
Zend/tests/bug32799.phpt
Zend/tests/bug39346.phpt [new file with mode: 0644]
Zend/zend_execute.c

diff --git a/NEWS b/NEWS
index 96031f995bab0614e1463561e364c3801bd066bd..e6e4e5661c94a88f220c38500a3f23f124efff3d 100644 (file)
--- a/NEWS
+++ b/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)
index 7b09a502746768c28a33c272304e2aac387cbfc5..c76daeddef1e81286c6f7edfbecaf63a895bb837 100755 (executable)
@@ -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
diff --git a/Zend/tests/bug39346.phpt b/Zend/tests/bug39346.phpt
new file mode 100644 (file)
index 0000000..4a614c9
--- /dev/null
@@ -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
index 865a4003f37242eb2da0a779806bbc5f9f0c7e8b..1f417fab0e149da6f333050d3fe4ca95c1174564 100644 (file)
@@ -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) {