diff options
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | ext/zlib/tests/bug48725.phpt | 24 | ||||
-rw-r--r-- | ext/zlib/zlib_filter.c | 14 |
3 files changed, 37 insertions, 4 deletions
@@ -46,6 +46,9 @@ PHP NEWS - Tidy: . Fixed bug #77594 (ob_tidyhandler is never reset). (cmb) +- Zlib: + . Fixed #48725 (Support for flushing in zlib stream). (cmb) + 26 Nov 2020, PHP 7.4.13 - Core: diff --git a/ext/zlib/tests/bug48725.phpt b/ext/zlib/tests/bug48725.phpt new file mode 100644 index 0000000000..0d04887a2d --- /dev/null +++ b/ext/zlib/tests/bug48725.phpt @@ -0,0 +1,24 @@ +--TEST-- +Bug #48725 (Support for flushing in zlib stream) +--SKIPIF-- +<?php +if (!extension_loaded('zlib')) die('skip zip extension not available'); +?> +--FILE-- +<?php +$text = str_repeat('0123456789abcdef', 1000); + +$temp = fopen('php://temp', 'r+'); +stream_filter_append($temp, 'zlib.deflate', STREAM_FILTER_WRITE); +fwrite($temp, $text); + +rewind($temp); + +var_dump(bin2hex(stream_get_contents($temp))); +var_dump(ftell($temp)); + +fclose($temp); +?> +--EXPECT-- +string(138) "ecc7c901c0100000b09594bac641d97f840e22f9253c31bdb9d4d6c75cdf3ec1ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddaffc0f0000ffff" +int(69) diff --git a/ext/zlib/zlib_filter.c b/ext/zlib/zlib_filter.c index 3c19d38016..988ed603ca 100644 --- a/ext/zlib/zlib_filter.c +++ b/ext/zlib/zlib_filter.c @@ -29,7 +29,7 @@ typedef struct _php_zlib_filter_data { unsigned char *outbuf; size_t outbuf_len; int persistent; - zend_bool finished; + zend_bool finished; /* for zlib.deflate: signals that no flush is pending */ } php_zlib_filter_data; /* }}} */ @@ -196,6 +196,8 @@ static php_stream_filter_status_t php_zlib_deflate_filter( bucket = php_stream_bucket_make_writeable(bucket); while (bin < (unsigned int) bucket->buflen) { + int flush_mode; + desired = bucket->buflen - bin; if (desired > data->inbuf_len) { desired = data->inbuf_len; @@ -203,7 +205,9 @@ static php_stream_filter_status_t php_zlib_deflate_filter( memcpy(data->strm.next_in, bucket->buf + bin, desired); data->strm.avail_in = desired; - status = deflate(&(data->strm), flags & PSFS_FLAG_FLUSH_CLOSE ? Z_FULL_FLUSH : (flags & PSFS_FLAG_FLUSH_INC ? Z_SYNC_FLUSH : Z_NO_FLUSH)); + flush_mode = flags & PSFS_FLAG_FLUSH_CLOSE ? Z_FULL_FLUSH : (flags & PSFS_FLAG_FLUSH_INC ? Z_SYNC_FLUSH : Z_NO_FLUSH); + data->finished = flush_mode != Z_NO_FLUSH; + status = deflate(&(data->strm), flush_mode); if (status != Z_OK) { /* Something bad happened */ php_stream_bucket_delref(bucket); @@ -230,11 +234,12 @@ static php_stream_filter_status_t php_zlib_deflate_filter( php_stream_bucket_delref(bucket); } - if (flags & PSFS_FLAG_FLUSH_CLOSE) { + if (flags & PSFS_FLAG_FLUSH_CLOSE || ((flags & PSFS_FLAG_FLUSH_INC) && !data->finished)) { /* Spit it out! */ status = Z_OK; while (status == Z_OK) { - status = deflate(&(data->strm), Z_FINISH); + status = deflate(&(data->strm), (flags & PSFS_FLAG_FLUSH_CLOSE ? Z_FINISH : Z_SYNC_FLUSH)); + data->finished = 1; if (data->strm.avail_out < data->outbuf_len) { size_t bucketlen = data->outbuf_len - data->strm.avail_out; @@ -395,6 +400,7 @@ factory_setlevel: } } status = deflateInit2(&(data->strm), level, Z_DEFLATED, windowBits, memLevel, 0); + data->finished = 1; fops = &php_zlib_deflate_ops; } else { status = Z_DATA_ERROR; |