Re: Please do not call zval_dtor on recursive array
| From: | Dmitry Stogov | 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); }
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); }