]> granicus.if.org Git - php/commitdiff
fix Bug #46026: bz2.decompress/zlib.inflate filter tries to decompress after end...
authorGreg Beaver <cellog@php.net>
Sat, 11 Oct 2008 19:12:11 +0000 (19:12 +0000)
committerGreg Beaver <cellog@php.net>
Sat, 11 Oct 2008 19:12:11 +0000 (19:12 +0000)
NEWS
ext/bz2/bz2_filter.c
ext/zlib/zlib_filter.c

diff --git a/NEWS b/NEWS
index d9351dea0b3495b029d3a20491dd1ac4b84289c1..2c574a1f4cbdeeb849cbf0ba2b501c4502ffe7dc 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,8 @@ PHP                                                                        NEWS
   and $this->$method()). (Dmitry)
 - Fixed bug #46139 (PDOStatement->setFetchMode() forgets FETCH_PROPS_LATE).
   (chsc at peytz dot dk, Felipe)
+- Fixed bug #46026 (bzip2.decompress/zlib.inflate filter tries to decompress
+  after end of stream). (Keisial at gmail dot com, Greg)
 - Fixed bug #44251, #41125 (PDO + quote() + prepare() can result in seg fault).
   (tsteiner at nerdclub dot net)
 
index 5c986fc5a83722c5fe5aa8c0968965cfe237bbd9..07597e5b18dac3dda8b397333d83c2a74e38203c 100644 (file)
@@ -34,6 +34,7 @@ typedef struct _php_bz2_filter_data {
        size_t inbuf_len;
        char *outbuf;
        size_t outbuf_len;
+       zend_bool finished;
 } php_bz2_filter_data;
 
 /* }}} */
@@ -82,6 +83,11 @@ static php_stream_filter_status_t php_bz2_decompress_filter(
 
                bucket = php_stream_bucket_make_writeable(buckets_in->head TSRMLS_CC);
                while (bin < bucket->buflen) {
+                       if (data->finished) {
+                               consumed += bucket->buflen;
+                               break;
+                       }
+
                        desired = bucket->buflen - bin;
                        if (desired > data->inbuf_len) {
                                desired = data->inbuf_len;
@@ -90,7 +96,11 @@ static php_stream_filter_status_t php_bz2_decompress_filter(
                        data->strm.avail_in = desired;
 
                        status = BZ2_bzDecompress(&(data->strm));
-                       if (status != BZ_OK && status != BZ_STREAM_END) {
+
+                       if (status == BZ_STREAM_END) {
+                               BZ2_bzDecompressEnd(&(data->strm));
+                               data->finished = '\1';
+                       } else if (status != BZ_OK) {
                                /* Something bad happened */
                                php_stream_bucket_delref(bucket TSRMLS_CC);
                                return PSFS_ERR_FATAL;
@@ -115,10 +125,11 @@ static php_stream_filter_status_t php_bz2_decompress_filter(
                                return PSFS_PASS_ON;
                        }
                }
+
                php_stream_bucket_delref(bucket TSRMLS_CC);
        }
 
-       if (flags & PSFS_FLAG_FLUSH_CLOSE) {
+       if (!data->finished && (flags & PSFS_FLAG_FLUSH_CLOSE)) {
                /* Spit it out! */
                status = BZ_OK;
                while (status == BZ_OK) {
@@ -148,7 +159,9 @@ static void php_bz2_decompress_dtor(php_stream_filter *thisfilter TSRMLS_DC)
 {
        if (thisfilter && thisfilter->abstract) {
                php_bz2_filter_data *data = thisfilter->abstract;
-               BZ2_bzDecompressEnd(&(data->strm));
+               if (!data->finished) {
+                       BZ2_bzDecompressEnd(&(data->strm));
+               }
                pefree(data->inbuf, data->persistent);
                pefree(data->outbuf, data->persistent);
                pefree(data, data->persistent);
@@ -327,6 +340,7 @@ static php_stream_filter *php_bz2_filter_create(const char *filtername, zval *fi
                }
 
                status = BZ2_bzDecompressInit(&(data->strm), 0, smallFootprint);
+               data->finished = '\0';
                fops = &php_bz2_decompress_ops;
        } else if (strcasecmp(filtername, "bzip2.compress") == 0) {
                int blockSize100k = PHP_BZ2_FILTER_DEFAULT_BLOCKSIZE;
index ac1c029a405b6c0c433baac669215f1188714317..8d804989c5795083ee542960bdfe161bfce72bbf 100644 (file)
@@ -31,6 +31,7 @@ typedef struct _php_zlib_filter_data {
        size_t inbuf_len;
        char *outbuf;
        size_t outbuf_len;
+       zend_bool finished;
 } php_zlib_filter_data;
 
 /* }}} */
@@ -81,6 +82,12 @@ static php_stream_filter_status_t php_zlib_inflate_filter(
 
                bucket = php_stream_bucket_make_writeable(buckets_in->head TSRMLS_CC);
                while (bin < bucket->buflen) {
+
+                       if (data->finished) {
+                               consumed += bucket->buflen;
+                               break;
+                       }
+
                        desired = bucket->buflen - bin;
                        if (desired > data->inbuf_len) {
                                desired = data->inbuf_len;
@@ -89,7 +96,10 @@ static php_stream_filter_status_t php_zlib_inflate_filter(
                        data->strm.avail_in = desired;
 
                        status = inflate(&(data->strm), flags & PSFS_FLAG_FLUSH_CLOSE ? Z_FINISH : Z_SYNC_FLUSH);
-                       if (status != Z_OK && status != Z_STREAM_END) {
+                       if (status == Z_STREAM_END) {
+                               inflateEnd(&(data->strm));
+                               data->finished = '\1';
+                       } else if (status != Z_OK) {
                                /* Something bad happened */
                                php_stream_bucket_delref(bucket TSRMLS_CC);
                                return PSFS_ERR_FATAL;
@@ -118,7 +128,7 @@ static php_stream_filter_status_t php_zlib_inflate_filter(
                php_stream_bucket_delref(bucket TSRMLS_CC);
        }
 
-       if (flags & PSFS_FLAG_FLUSH_CLOSE) {
+       if (!data->finished && flags & PSFS_FLAG_FLUSH_CLOSE) {
                /* Spit it out! */
                status = Z_OK;
                while (status == Z_OK) {
@@ -146,7 +156,9 @@ static void php_zlib_inflate_dtor(php_stream_filter *thisfilter TSRMLS_DC)
 {
        if (thisfilter && thisfilter->abstract) {
                php_zlib_filter_data *data = thisfilter->abstract;
-               inflateEnd(&(data->strm));
+               if (!data->finished) {
+                       inflateEnd(&(data->strm));
+               }
                pefree(data->inbuf, data->persistent);
                pefree(data->outbuf, data->persistent);
                pefree(data, data->persistent);
@@ -330,6 +342,7 @@ static php_stream_filter *php_zlib_filter_create(const char *filtername, zval *f
                }
 
                /* RFC 1951 Inflate */
+               data->finished = '\0';
                status = inflateInit2(&(data->strm), windowBits);
                fops = &php_zlib_inflate_ops;
        } else if (strcasecmp(filtername, "zlib.deflate") == 0) {