Skip to content

Commit 681e015

Browse files
committed
Handle fatal stream filter errors
1 parent dd4919e commit 681e015

File tree

2 files changed

+59
-10
lines changed

2 files changed

+59
-10
lines changed

ext/bz2/bug71263.phpt

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
--TEST--
2+
Bug #71263: fread() does not detects decoding errors from filter bzip2.decompress
3+
--FILE--
4+
<?php
5+
6+
// This bug is only partially fixed.
7+
8+
function test($case) {
9+
$plain = "The quick brown fox jumps over the lazy dog.";
10+
$fn = "bug71263.bz2";
11+
$compressed = (string) bzcompress($plain);
12+
echo "Compressed len = ", strlen($compressed), "\n";
13+
14+
if ($case == 1) {
15+
// Set a random byte in the middle of the compressed data
16+
// --> php_bz2_decompress_filter() detects fatal error
17+
// --> fread() displays empty string then garbage, no errors detected:
18+
$compressed[strlen($compressed) - 15] = 'X';
19+
} else if ($case == 2) {
20+
// Truncate the compressed data
21+
// --> php_bz2_decompress_filter() does not detect errors,
22+
// --> fread() displays the empty string:
23+
$compressed = substr($compressed, 0, strlen($compressed) - 20);
24+
} else {
25+
// Corrupted final CRC
26+
// --> php_bz2_decompress_filter() detects fatal error
27+
// --> fread() displays an empty string, then the correct plain text, no error detected:
28+
$compressed[strlen($compressed)-2] = 'X';
29+
}
30+
31+
file_put_contents($fn, $compressed);
32+
33+
$r = fopen($fn, "r");
34+
stream_filter_append($r, 'bzip2.decompress', STREAM_FILTER_READ);
35+
while (!feof($r)) {
36+
$s = fread($r, 100);
37+
echo "read: "; var_dump($s);
38+
}
39+
fclose($r);
40+
unlink($fn);
41+
}
42+
43+
test(1);
44+
test(2);
45+
test(3);
46+
?>
47+
--EXPECT--
48+
Compressed len = 81
49+
read: bool(false)
50+
read: string(43) "bthes ohe rpujumr.bthes ohe rpujumr.bthes o"
51+
Compressed len = 81
52+
read: string(0) ""
53+
Compressed len = 81
54+
read: bool(false)
55+
read: string(44) "The quick brown fox jumps over the lazy dog."

main/streams/streams.c

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,6 @@ PHPAPI int _php_stream_fill_read_buffer(php_stream *stream, size_t size)
531531

532532
if (stream->readfilters.head) {
533533
char *chunk_buf;
534-
int err_flag = 0;
535534
php_stream_bucket_brigade brig_in = { NULL, NULL }, brig_out = { NULL, NULL };
536535
php_stream_bucket_brigade *brig_inp = &brig_in, *brig_outp = &brig_out, *brig_swap;
537536

@@ -542,7 +541,7 @@ PHPAPI int _php_stream_fill_read_buffer(php_stream *stream, size_t size)
542541
/* allocate a buffer for reading chunks */
543542
chunk_buf = emalloc(stream->chunk_size);
544543

545-
while (!stream->eof && !err_flag && (stream->writepos - stream->readpos < (zend_off_t)size)) {
544+
while (!stream->eof && (stream->writepos - stream->readpos < (zend_off_t)size)) {
546545
ssize_t justread = 0;
547546
int flags;
548547
php_stream_bucket *bucket;
@@ -610,18 +609,13 @@ PHPAPI int _php_stream_fill_read_buffer(php_stream *stream, size_t size)
610609
/* when a filter needs feeding, there is no brig_out to deal with.
611610
* we simply continue the loop; if the caller needs more data,
612611
* we will read again, otherwise out job is done here */
613-
if (justread == 0) {
614-
/* there is no data */
615-
err_flag = 1;
616-
break;
617-
}
618-
continue;
612+
break;
619613

620614
case PSFS_ERR_FATAL:
621615
/* some fatal error. Theoretically, the stream is borked, so all
622616
* further reads should fail. */
623-
err_flag = 1;
624-
break;
617+
efree(chunk_buf);
618+
return FAILURE;
625619
}
626620

627621
if (justread <= 0) {

0 commit comments

Comments
 (0)