From: Dmitry Stogov Date: Tue, 8 Jul 2008 08:16:09 +0000 (+0000) Subject: Fixed bug #45434 (circular reference causes segfault in gc_collect_cycles()) X-Git-Tag: php-5.3.0alpha1~448 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f7f74367df809e39591a52c6c6b2a6c405cda4bd;p=php Fixed bug #45434 (circular reference causes segfault in gc_collect_cycles()) --- diff --git a/NEWS b/NEWS index c806f4e5c0..937497777f 100644 --- 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) diff --git a/Zend/tests/gc_029.phpt b/Zend/tests/gc_029.phpt index 12f40c18c9..ea0660eca4 100644 --- a/Zend/tests/gc_029.phpt +++ b/Zend/tests/gc_029.phpt @@ -1,5 +1,5 @@ --TEST-- -GC 028: GC and destructors +GC 029: GC and destructors --FILE-- 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 diff --git a/Zend/zend_gc.c b/Zend/zend_gc.c index 67ea744bf8..55bd207ce1 100644 --- a/Zend/zend_gc.c +++ b/Zend/zend_gc.c @@ -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);