Skip to content

Commit 8869479

Browse files
committed
Check whether stream correctly ends in dechunk
At the end of the stream, we expect to have read the trailer. Check whether the chunked encoding is at the end of the encoded data when the stream ends. This makes it more difficult to abuse the dechunk filter for abuse. Related to php#21983
1 parent 7c9fcfd commit 8869479

3 files changed

Lines changed: 59 additions & 1 deletion

File tree

ext/standard/filters.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1949,6 +1949,11 @@ static php_stream_filter_status_t php_chunked_filter(
19491949
*bytes_consumed = consumed;
19501950
}
19511951

1952+
if ((flags & PSFS_FLAG_FLUSH_CLOSE) && data->state != CHUNK_TRAILER) {
1953+
php_error_docref(NULL, E_WARNING, "Stream filter (dechunk): unexpected end of stream");
1954+
return PSFS_ERR_FATAL;
1955+
}
1956+
19521957
return PSFS_PASS_ON;
19531958
}
19541959

ext/standard/tests/filters/chunked_002.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ fclose($buffer);
3939
$buffer = fopen('php://temp', 'w+');
4040
stream_filter_append($buffer, 'dechunk', STREAM_FILTER_WRITE);
4141

42-
fwrite($buffer, "5\r\nHello\r\n");
42+
fwrite($buffer, "5\r\nHello\r\n0\r\n");
4343
$data = stream_get_contents($buffer, -1, 0);
4444
var_dump($data);
4545

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
--TEST--
2+
Chunked encoding with invalid values
3+
--SKIPIF--
4+
<?php
5+
$filters = stream_get_filters();
6+
if(! in_array( "dechunk", $filters )) die( "skip Chunked filter not available." );
7+
?>
8+
--INI--
9+
allow_url_fopen=1
10+
--FILE--
11+
<?php
12+
$streams = array(
13+
"data://text/plain,1\r\n",
14+
"data://text/plain,1\r\n0\r\n",
15+
"data://text/plain,1\r\nab\r\n0\r\n",
16+
"data://text/plain,a\r\n",
17+
"data://text/plain,z\r\n",
18+
"data://text/plain,z\r\n0\r\n",
19+
"data://text/plain,a string that starts with a valid hex character\r\n0\r\n",
20+
"data://text/plain,some string that does not start with a hex character\r\n0\r\n",
21+
);
22+
foreach ($streams as $name) {
23+
$fp = fopen($name, "r");
24+
stream_filter_append($fp, "dechunk", STREAM_FILTER_READ);
25+
var_dump(stream_get_contents($fp));
26+
fclose($fp);
27+
}
28+
?>
29+
--EXPECTF--
30+
31+
Warning: stream_get_contents(): Stream filter (dechunk): unexpected end of stream in %s on line %d
32+
string(0) ""
33+
34+
Warning: stream_get_contents(): Stream filter (dechunk): unexpected end of stream in %s on line %d
35+
string(0) ""
36+
37+
Warning: stream_get_contents(): Stream filter (dechunk): unexpected end of stream in %s on line %d
38+
string(0) ""
39+
40+
Warning: stream_get_contents(): Stream filter (dechunk): unexpected end of stream in %s on line %d
41+
string(0) ""
42+
43+
Warning: stream_get_contents(): Stream filter (dechunk): unexpected end of stream in %s on line %d
44+
string(0) ""
45+
46+
Warning: stream_get_contents(): Stream filter (dechunk): unexpected end of stream in %s on line %d
47+
string(0) ""
48+
49+
Warning: stream_get_contents(): Stream filter (dechunk): unexpected end of stream in %s on line %d
50+
string(0) ""
51+
52+
Warning: stream_get_contents(): Stream filter (dechunk): unexpected end of stream in %s on line %d
53+
string(0) ""

0 commit comments

Comments
 (0)