Hello. There is a bug in PHP5 code which shows when an object destructor tries to access the zval for the object being destroyed. Here is a sample code: <? class A { public function __construct () { }
public function __destruct () { global $gA; } } $gA = new A (); ?> What happens is that upon program shutdown the symtable is cleared the refcount for gA zval goes to zero and the zval destructor is called. It calls the zend_objects_destroy_object() function which has following code: ... ZEND_INIT_SYMTABLE(&symbol_table); /* FIXME: Optimize this so that we use the old_object->ce->destructor function pointer instead of the name */ MAKE_STD_ZVAL(destructor_func_name); destructor_func_name->type = IS_STRING; destructor_func_name->value.str.val = estrndup("__destruct", sizeof("__destruct")-1); destructor_func_name->value.str.len = sizeof("__destruct")-1; call_user_function_ex(NULL, &obj, destructor_func_name, &retval_ptr, 0, NULL, 0, &symbol_table TSRMLS_CC); zend_hash_destroy(&symbol_table); ... this code sets a temporary symtable and calls the A::__destruct. When the __destruct functions accesses the gA object via "global $gA" its refcount goes from 0 to 1 and after return from "__destruct" the "zend_hash_destroy(&symbol_table);" line kills the symtable, and the zval refcount goes to zero again, this causes the zval structure to be freed, and then it is freed once again on return from zend_objects_destroy_object(), thus causing memory corruption. Here is a patch that fixes the problem: diff -ruN php5-200310182330.orig/Zend/zend_variables.c php5-200310182330/Zend/zend_variables.c --- php5-200310182330.orig/Zend/zend_variables.c 2003-08-24 18:06:54.000000000 +0000 +++ php5-200310182330/Zend/zend_variables.c 2003-10-23 19:09:11.000000000 +0000 @@ -58,7 +58,14 @@ { TSRMLS_FETCH(); + /* Increase temporarily the object zvalue refcount in order to protect + the object zvalue from being destroyed one more time if it is accessed + from the object destructor call chain. This could happen if the + object destructor accesses the object as a global variable by name. */ + + zvalue->refcount++; Z_OBJ_HT_P(zvalue)->del_ref(zvalue TSRMLS_CC); + zvalue->refcount--; } break; case IS_RESOURCE: -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php