From 77acc692fd9b590245937bfe65ba60f9bacd4350 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Tue, 28 Mar 2006 16:01:04 +0000 Subject: [PATCH] Fixed bug #36886 (User filters can leak buckets in some situations). --- NEWS | 1 + ext/standard/user_filters.c | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 7c577505cb..cf4235dc3c 100644 --- 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). diff --git a/ext/standard/user_filters.c b/ext/standard/user_filters.c index 971a5b91ab..24d9e0ab16 100644 --- a/ext/standard/user_filters.c +++ b/ext/standard/user_filters.c @@ -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++; + } } /* }}} */ -- 2.40.0