Re: Please do not call zval_dtor on recursive array

From: Date: Thu, 18 Oct 2012 11:19:58 +0000
Subject: Re: Please do not call zval_dtor on recursive array
References: 1 2 3  Groups: php.internals php.pecl.dev 
Request: Send a blank email to pecl-dev+get-9909@lists.php.net to get a copy of this message
I think, I've found a more simple fix (attached) that don't require extension patching and even allow to optimize ZE a bit. Laruence, can you please verify it. Sorry, I'm quite busy with other tasks. Thanks. Dmitry. On 10/18/2012 02:56 PM, Laruence wrote: > On Thu, Oct 18, 2012 at 6:45 PM, Pierre Joye <pierre.php@gmail.com> wrote: >> hi Dmitry, Laruence! >> >> On Thu, Oct 18, 2012 at 11:46 AM, Laruence <laruence@php.net> wrote: >>> Hey: >>> >>> recently we found a problem, that is "usage zval_dtor on a recursive >>> array while gc enabled" has chance to result a segfault. >>> >>> a reproduce script could be found here: >>> >>> https://github.com/php/php-src/blob/8bd5e15ff7a57791956c4017ee8fb4a8ac0d8d2e/ext/pcre/tests/bug63055.phpt >>> >>> the preg_match used to call zval_dtor on the third argument. which >>> result a segfault, reported at #63055 >>> >>> the segfault backtrace will looks like: ²UC¹¡ >>> ÎuˆÅOXæ]ohttp://pastebin.com/uPWBgrTZ >>> >>> thanks to dmitry, we got a simple solution, that is: instead of >>> directly call to zval_dtor, please use following codes instead: >>> " >>> zval garbage = *subpats; >>> array_init(subpats); >>> zval_dtor(&garbage); >>> " >> Nice catch! >> >> We could add a macro? As it looks like many will forget to do that :) > maybe a seris macro: > > ZVAL_REPLACE_LONG() > ZVAL_REPLACE_STRING{L}() > ZVAL_REPLACE_ZVAL() > > etc; > > thanks , will do it later, only for trunk I think > > thanks >> >> Cheers, >> -- >> Pierre >> >> @pierrejoye | http://blog.thepimp.net | >> http://www.libgd.org > > >

diff --git a/Zend/zend_variables.c b/Zend/zend_variables.c index c790108..f2a85c3 100644 --- a/Zend/zend_variables.c +++ b/Zend/zend_variables.c @@ -40,6 +40,9 @@ ZEND_API void _zval_dtor_func(zval *zvalue ZEND_FILE_LINE_DC) TSRMLS_FETCH(); if (zvalue->value.ht && (zvalue->value.ht != &EG(symbol_table))) { + /* break possible cycles */ + Z_TYPE_P(zvalue) = IS_NULL; + zend_hash_destroy(zvalue->value.ht); FREE_HASHTABLE(zvalue->value.ht); }
« previous php.pecl.dev (#9909) next »