Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:4947 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 45852 invoked by uid 1010); 23 Oct 2003 17:19:08 -0000 Delivered-To: ezmlm-scan-internals@lists.php.net Delivered-To: ezmlm-internals@lists.php.net Received: (qmail 45759 invoked from network); 23 Oct 2003 17:19:07 -0000 Received: from unknown (HELO sofia.digsys.bg) (193.68.3.250) by pb1.pair.com with SMTP; 23 Oct 2003 17:19:07 -0000 Received: from damagegqsaogpp (bourgas33.pip.digsys.bg [193.68.8.33]) by sofia.digsys.bg (8.11.6/8.10.1) with SMTP id h9NHJ3p17013 for ; Thu, 23 Oct 2003 20:19:04 +0300 (EEST) To: "PHP-DEV" Date: Thu, 23 Oct 2003 20:20:13 +0300 Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit X-Priority: 3 (Normal) X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook IMO, Build 9.0.2416 (9.0.2910.0) Importance: Normal X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2600.0000 Subject: [PATCH] Memory corruption when freeing an object zval twice From: vma1@abv.bg ("Vesselin Atanasov") 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: 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: