Skip to content

Commit a1738d8

Browse files
committed
Fix #81092: fflush before stream_filter_remove corrupts stream
When doing a non finishing flush, BZ2_bzCompress() returns BZ_FLUSH_OK (not BZ_FINISH_OK) what requires us to do further flushes right away. We also refactor the while-loop as do-loop. Closes GH-7113.
1 parent d8165c2 commit a1738d8

File tree

3 files changed

+28
-3
lines changed

3 files changed

+28
-3
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ PHP NEWS
1010
. Fixed bug #81070 (Integer underflow in memory limit comparison).
1111
(Peter van Dommelen)
1212

13+
- Bzip2:
14+
. Fixed bug #81092 (fflush before stream_filter_remove corrupts stream).
15+
(cmb)
16+
1317
- OpenSSL:
1418
. Fixed bug #76694 (native Windows cert verification uses CN as sever name).
1519
(cmb)

ext/bz2/bz2_filter.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -268,8 +268,7 @@ static php_stream_filter_status_t php_bz2_compress_filter(
268268

269269
if (flags & PSFS_FLAG_FLUSH_CLOSE || ((flags & PSFS_FLAG_FLUSH_INC) && !data->is_flushed)) {
270270
/* Spit it out! */
271-
status = BZ_FINISH_OK;
272-
while (status == BZ_FINISH_OK) {
271+
do {
273272
status = BZ2_bzCompress(&(data->strm), (flags & PSFS_FLAG_FLUSH_CLOSE ? BZ_FINISH : BZ_FLUSH));
274273
data->is_flushed = 1;
275274
if (data->strm.avail_out < data->outbuf_len) {
@@ -281,7 +280,7 @@ static php_stream_filter_status_t php_bz2_compress_filter(
281280
data->strm.next_out = data->outbuf;
282281
exit_status = PSFS_PASS_ON;
283282
}
284-
}
283+
} while (status == (flags & PSFS_FLAG_FLUSH_CLOSE ? BZ_FINISH_OK : BZ_FLUSH_OK));
285284
}
286285

287286
if (bytes_consumed) {

ext/bz2/tests/bug81092.phpt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
Bug #81092 (fflush before stream_filter_remove corrupts stream)
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('bz2')) die('skip bz2 extension not available');
6+
?>
7+
--FILE--
8+
<?php
9+
$stream = fopen(__DIR__ . "/81092.bz2", 'wb+');
10+
$filter = stream_filter_append($stream, 'bzip2.compress', STREAM_FILTER_WRITE, ['blocks' => 9, 'work' => 0]);
11+
fwrite($stream, random_bytes(8192));
12+
fflush($stream);
13+
stream_filter_remove($filter);
14+
15+
var_dump(strlen(bzdecompress(file_get_contents(__DIR__ . "/81092.bz2"))));
16+
?>
17+
--CLEAN--
18+
<?php
19+
@unlink(__DIR__ . "/81092.bz2");
20+
?>
21+
--EXPECT--
22+
int(8192)

0 commit comments

Comments
 (0)