refcount and hence double free issue

php.internals

Kamesh Jayachandran

21 years ago
Hi All, I have come across a double free because of improper refcount manipulation. <?php class MyTextSanitizer { var $smileys=array() function MyTextSanitizer() {} function getSmileys() { return $this->smileys; } } $myts = new MyTextSanitizer(); $smiles =& $myts->getSmileys(); //calling by ref alone causes improper refcount $smiles = $myts->getSmileys(); //this does not cause improper refcount ?> What is happening is class_entry->default_properties and object->properties are sharing the same zval** as the data($smileys) against their keys with incrementing the refcount. In the execution of the script refcount of $smileys is changing from 1->2, 2->3, 3->2, 2->3, 3->2, 2->1, --->when it is 1 zend_objects_free_object_storage calls zend_hash_destroy of object->properties which calls _zval_ptr_dtor on each of its data($smiley) frees it if the refcount ==1 1->0 --destroy_zend_class also calls zend_hash_destroy(&ce->default_properties) by the time $smiley->refcount=0 and storage is already freed which is accessed by _zval_ptr_dtor to decrement the refcount which causes a segfault with a huge script. Anyway will see who and all increment/decrement the refcount and see where to increment it or not to decrement it. With regards Kamesh Jayachandran

Derick Rethans

21 years ago
On Wed, 6 Apr 2005, Kamesh Jayachandran wrote:
> Hi All, > I have come across a double free because of improper refcount > manipulation. > <?php > class MyTextSanitizer > { > var $smileys=array() > function MyTextSanitizer() {} > function getSmileys() > { > return $this->smileys; > } > } > $myts = new MyTextSanitizer(); > $smiles =& $myts->getSmileys(); //calling by ref alone causes improper > refcount > $smiles = $myts->getSmileys(); //this does not cause improper refcount > ?>
This fact is known, Marcus and I have a working patch for this - but it'll break binairy compat for PHP 4.4 - stay tuned for this. regards, Derick
-- Derick Rethans http://derickrethans.nl | http://ez.no | http://xdebug.org

Kamesh Jayachandran

21 years ago
It happens in php-5.0.4 also. With regards Kamesh Jayachandran On Wed, 6 Apr 2005 09:16:34 +0200 (CEST), "Derick Rethans" <derick@php.net> said:

Kamesh Jayachandran

21 years ago
<?php class MyTextSanitizer { var $smileys=array() function MyTextSanitizer() {} function getSmileys() { return $this->smileys; } } $myts = new MyTextSanitizer(); $smiles =& $myts->getSmileys(); //calling by ref alone causes improper ?> The opcodes for the above script ZEND_FETCH_CLASS ZEND_NEW (Increases the refcount of smileys array from 1 to 2. zend_declare class made it 1 from 0) ZEND_JMP_NO_CTOR (Not executed) ZEND_INIT_CTOR_CALL (No change in smileys refcount) ZEND_DO_FCALL_BY_NAME(No change in smileys refcount) ZEND_FETCH_W(No change in smileys refcount) ZEND_ASSIGN(No change in smileys refcount) ZEND_FETCH_R(No change in smileys refcount) ZEND_INIT_METHOD_CALL(No change in smileys refcount) ZEND_DO_FCALL_BY_NAME(Increases the refcount of smileys array from 2 to 3) ZEND_FETCH_W(No change in smileys refcount) ZEND_ASSIGN_REF(Increases the refcount of smileys array from 3 to 1. _get_zval_ptr_ptr on &opline->op2 makes it 3 to 2. zend_assign_to_variable_reference(&opline->result, get_zval_ptr_ptr(&opline->op1, EX(Ts), BP_VAR_W), value_ptr_ptr, EX(Ts) TSRMLS_CC); decreases it from 2 to 1) ZEND_RETURN ZEND_HANDLE_EXCEPTION object destructor reduces the refcount from 1 to 0 and destroys the $smileys. zend_destroy_class now attempts to destroy it again. This causes a segfault. With regards Kamesh Jayachandran On Wed, 06 Apr 2005 00:18:35 -0700, "Kamesh Jayachandran" <kameshj@fastmail.fm> said: