]> granicus.if.org Git - php/commitdiff
Fixed bug #36886 (User filters can leak buckets in some situations).
authorIlia Alshanetsky <iliaa@php.net>
Tue, 28 Mar 2006 16:01:04 +0000 (16:01 +0000)
committerIlia Alshanetsky <iliaa@php.net>
Tue, 28 Mar 2006 16:01:04 +0000 (16:01 +0000)
NEWS
ext/standard/user_filters.c

diff --git a/NEWS b/NEWS
index 7c577505cb5d2ab40fe5b3c82e026277a5685a15..cf4235dc3c3f64b92d757c9abbadac31a158d9d6 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -12,6 +12,7 @@ PHP                                                                        NEWS
 - Removed the E_STRICT deprecation notice from "var". (Ilia)
 - Fixed debug_zval_dump() to support private and protected members. (Dmitry)
 - Fixed SoapFault::getMessage(). (Dmitry)
+- Fixed bug #36886 (User filters can leak buckets in some situations). (Ilia)
 - Fixed bug #36878 (error messages are printed even though an exception has 
   been thrown). (Tony)
 - Fixed bug #36869 (memory leak in output buffering when using chunked output).
index 971a5b91abd6aa9e3f6cd57c7099190b10ca068f..24d9e0ab16d30ac3daaac3ab819e1f1923f537d0 100644 (file)
@@ -64,6 +64,15 @@ static zend_function_entry user_filter_class_funcs[] = {
 
 static zend_class_entry user_filter_class_entry;
 
+static ZEND_RSRC_DTOR_FUNC(php_bucket_dtor)
+{
+       php_stream_bucket *bucket = (struct php_stream_bucket *)rsrc->ptr;
+       if (bucket) {
+               php_stream_bucket_delref(bucket TSRMLS_CC);
+               bucket = NULL;
+       }
+}
+
 PHP_MINIT_FUNCTION(user_filters)
 {
        /* init the filter class ancestor */
@@ -83,7 +92,7 @@ PHP_MINIT_FUNCTION(user_filters)
        /* Filters will dispose of their brigades */
        le_bucket_brigade = zend_register_list_destructors_ex(NULL, NULL, PHP_STREAM_BRIGADE_RES_NAME, module_number);
        /* Brigades will dispose of their buckets */
-       le_bucket = zend_register_list_destructors_ex(NULL, NULL, PHP_STREAM_BUCKET_RES_NAME, module_number);
+       le_bucket = zend_register_list_destructors_ex(php_bucket_dtor, NULL, PHP_STREAM_BUCKET_RES_NAME, module_number);
        
        if (le_bucket_brigade == FAILURE) {
                return FAILURE;
@@ -418,6 +427,12 @@ static void php_stream_bucket_attach(int append, INTERNAL_FUNCTION_PARAMETERS)
        } else {
                php_stream_bucket_prepend(brigade, bucket TSRMLS_CC);
        }
+       /* This is a hack necessary to accomodate situations where bucket is appended to the stream
+        * multiple times. See bug35916.phpt for reference.
+        */
+       if (bucket->refcount == 1) {
+               bucket->refcount++;
+       }
 }
 /* }}} */