]> granicus.if.org Git - php/commitdiff
Fixed bug #45434 (circular reference causes segfault in gc_collect_cycles())
authorDmitry Stogov <dmitry@php.net>
Tue, 8 Jul 2008 08:16:09 +0000 (08:16 +0000)
committerDmitry Stogov <dmitry@php.net>
Tue, 8 Jul 2008 08:16:09 +0000 (08:16 +0000)
NEWS
Zend/tests/gc_029.phpt
Zend/tests/gc_030.phpt [new file with mode: 0644]
Zend/zend_gc.c

diff --git a/NEWS b/NEWS
index c806f4e5c0a0da0f05a7c13214a1381890beb14d..937497777fa93a88255dcb4fa9e354878909b3f5 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -183,6 +183,8 @@ PHP                                                                        NEWS
 - Fixed an issue in date() where a : was printed for the O modifier after a P
   modifier was used. (Derick)
 
+- Fixed bug #45434 (circular reference causes segfault in gc_collect_cycles()).
+  (Dmitry)
 - Fixed bug #44769 (declaring private magic methods should throw error). (Felipe)
 - Fixed bug #44913 (Segfault when using return in combination with nested loops
   and continue 2). (Dmitry)
index 12f40c18c997670199656f57f161bbaadc7bf746..ea0660eca4fba855ba549334166f5e3c88c4fcbc 100644 (file)
@@ -1,5 +1,5 @@
 --TEST--
-GC 028: GC and destructors
+GC 029: GC and destructors
 --FILE--
 <?php
 class Foo {
diff --git a/Zend/tests/gc_030.phpt b/Zend/tests/gc_030.phpt
new file mode 100644 (file)
index 0000000..2c5e197
--- /dev/null
@@ -0,0 +1,21 @@
+--TEST--
+GC 030: GC and exceptions in destructors
+--FILE--
+<?php
+class foo {
+    public $foo;
+
+    public function __destruct() {
+        throw new Exception("foobar");
+    }
+}
+
+$f1 = new foo;
+$f2 = new foo;
+$f1->foo = $f2;
+$f2->foo = $f1;
+unset($f1, $f2);
+gc_collect_cycles();
+?>
+--EXPECTF--
+Fatal error: Ignoring exception from foo::__destruct() while an exception is already active (Uncaught Exception in %sgc_030.php on line %d) in %sgc_030.php on line %d
index 67ea744bf8b4ecd82f828a25152027e7c929935d..55bd207ce154cb39b4a62a2170a879f39ba9bad6 100644 (file)
@@ -557,9 +557,9 @@ ZEND_API int gc_collect_cycles(TSRMLS_D)
                                        !EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].destructor_called) {
 
                                        EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].destructor_called = 1;
-                                       zend_try {
-                                               EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.dtor(EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.object, Z_OBJ_HANDLE(p->z) TSRMLS_CC);
-                                       } zend_end_try();
+                                       EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.refcount++;
+                                       EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.dtor(EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.object, Z_OBJ_HANDLE(p->z) TSRMLS_CC);
+                                       EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.refcount--;
                                }
                        }
                        count++;
@@ -575,19 +575,15 @@ ZEND_API int gc_collect_cycles(TSRMLS_D)
                                        EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].valid &&
                                        EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.refcount <= 0) {
                                        EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.refcount = 1;
-                                       zend_try {
-                                               Z_TYPE(p->z) = IS_NULL;
-                                               zend_objects_store_del_ref_by_handle(Z_OBJ_HANDLE(p->z) TSRMLS_CC);
-                                       } zend_end_try();
+                                       Z_TYPE(p->z) = IS_NULL;
+                                       zend_objects_store_del_ref_by_handle(Z_OBJ_HANDLE(p->z) TSRMLS_CC);
                                }
                        } else if (Z_TYPE(p->z) == IS_ARRAY) {
                                Z_TYPE(p->z) = IS_NULL;
                                zend_hash_destroy(Z_ARRVAL(p->z));
                                FREE_HASHTABLE(Z_ARRVAL(p->z));
                        } else {
-                               zend_try {
-                                       zval_dtor(&p->z);
-                               } zend_end_try();
+                               zval_dtor(&p->z);
                                Z_TYPE(p->z) = IS_NULL;
                        }
                        p = GC_G(next_to_free);