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);
}