[PATCH] Two bugs in variable destruction

php.internals

Vesselin Atanasov

22 years ago
Hello. There are two bugs that show when code is executed from an object destructor and PHP is compiled in debug mode. Both bugs cause the zend_hash_find() to fail in the IS_CONSISTENT() macro. The first bug shows when the global symtable is destroyed and the destruction of a symbol causes an object destruction. If the object destructor tries to access a global symbol the zend_hash_find, IS_CONSISTENT() check will fail and error message will be logged. Here is code that shows the bug: <? class lala { public function __destruct () { global $abc; printf ("%s\n", $abc); } } $obj = new lala (); $abc = "123"; ?> The second bug shows when the object properties hash is destroyed. If the destruction of some property causes a destructor of a second object to be called and that destructor tries to access aproperty of the first object being destroyed zend_hash_find() will fail for the same reason as in first bug. Here is sample code: <? class A { private $objref; public $val; public function __construct () { $this->obref = new B (); $this->val = "msg"; } } class B { public function __destruct () { global $gA; printf ("%s\n", $gA->val); } } $gA = new A (); ?> And here is a patch that fixes these two bugs: diff -ruN php5-200310182330.orig/Zend/zend_execute_API.c php5-200310182330/Zend/zend_execute_API.c --- php5-200310182330.orig/Zend/zend_execute_API.c 2003-10-14 15:07:10.000000000 +0000 +++ php5-200310182330/Zend/zend_execute_API.c 2003-10-22 09:10:20.000000000 +0000 @@ -207,7 +207,13 @@ */ zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_deactivator TSRMLS_CC); - zend_hash_destroy(&EG(symbol_table)); +/* We need to use graceful destroy here because of the following problem when + Zend engine iscompiled in debug mode. Suppose the destruction of the + symtable causes the destruction of some object. If the destructor of that + object tries to access some global variable, it will fail because the + symtable hash is in inconsistent state and Zend engine will bail out in + IS_CONSISTENT() */ + zend_hash_graceful_destroy(&EG(symbol_table)); } zend_end_try(); zend_try { diff -ruN php5-200310182330.orig/Zend/zend_objects.c php5-200310182330/Zend/zend_objects.c --- php5-200310182330.orig/Zend/zend_objects.c 2003-09-02 15:06:33.000000000 +0000 +++ php5-200310182330/Zend/zend_objects.c 2003-10-22 09:13:02.000000000 +0000 @@ -26,7 +26,13 @@ static inline void zend_nuke_object(zend_object *object TSRMLS_DC) { - zend_hash_destroy(object->properties); +/* We need to use graceful destroy here because of the following problem when + Zend engine is compiled in debug mode. Suppose the destruction of some + property invokes a destructor which possibly calls other functions and + that call chain at some place tries to access a property of the nuked + object. The access will fail because the properties hash is in + inconsistent state and Zend engine will bail out in IS_CONSISTENT () */ + zend_hash_graceful_destroy(object->properties); FREE_HASHTABLE(object->properties); efree(object); }

Marcus Börger

22 years ago
Hello Vesselin, Wednesday, October 22, 2003, 8:43:39 AM, you wrote:
> Hello. > There are two bugs that show when code is executed from an object destructor and > PHP is compiled in debug mode. Both bugs cause the zend_hash_find() to fail in the > IS_CONSISTENT() macro.
[...]
> And here is a patch that fixes these two bugs:
[...] Besides your quick and dirty patch here's a patch that allows the destructors to do their job correctly: http://marcus-boerger.de/php/ext/ze2/ze2-shutdown-20031002.diff.txt
-- Best regards, Marcus mailto:helly@php.net