summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph M. Becker <cmbecker69@gmx.de>2020-12-08 12:24:09 +0100
committerChristoph M. Becker <cmbecker69@gmx.de>2020-12-08 12:24:49 +0100
commitfb4bc0f9e589a862d0fb1c05467bf589f86cee96 (patch)
tree3ccaa65dba865320dbe5a993301c5d19366185b3
parentd6ae0f010ec6bc4713dc9fe79e79947c2404a8dd (diff)
parent20e75329f2adb11dd231852c061926d0e4080929 (diff)
downloadphp-git-fb4bc0f9e589a862d0fb1c05467bf589f86cee96.tar.gz
Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4: Fix #48725: Support for flushing in zlib stream
-rw-r--r--NEWS3
-rw-r--r--ext/zlib/tests/bug48725.phpt24
-rw-r--r--ext/zlib/zlib_filter.c14
3 files changed, 37 insertions, 4 deletions
diff --git a/NEWS b/NEWS
index a776b3faf4..3d9fcb4a5b 100644
--- a/NEWS
+++ b/NEWS
@@ -65,6 +65,9 @@ PHP NEWS
- XML:
. XmlParser opaque object renamed to XMLParser for consistency with other XML objects. (girgias)
+- Zlib:
+ . Fixed #48725 (Support for flushing in zlib stream). (cmb)
+
26 Nov 2020, PHP 8.0.0
- BZ2:
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 0ed0c2713a..cdd981afde 100644
--- a/ext/zlib/zlib_filter.c
+++ b/ext/zlib/zlib_filter.c
@@ -27,7 +27,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;
/* }}} */
@@ -195,6 +195,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;
@@ -202,7 +204,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);
@@ -229,11 +233,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;
@@ -394,6 +399,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;