Skip to content

Commit 8e67823

Browse files
ext/standard: document stream filter state reset on seek in UPGRADING
#19981 (bug #49874) made stateful filters reset their state when the stream is sought to 0 (with rewind(), fseek(), or stream_get_contents($h, -1, 0)). It is not currently mentioned in UPGRADING.
1 parent 4592d1c commit 8e67823

2 files changed

Lines changed: 56 additions & 0 deletions

File tree

UPGRADING

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ PHP 8.6 UPGRADE NOTES
8282
values.
8383

8484
- Standard:
85+
. Stateful stream filters (e.g. "dechunk", "consumed", "convert.*") now
86+
reset their internal state when the stream is sought to position 0.
87+
See bug #49874.
8588
. Form feed (\f) is now added in the default trimmed characters of trim(),
8689
rtrim() and ltrim(). RFC: https://wiki.php.net/rfc/trim_form_feed
8790
. array_filter() now raises a ValueError when an invalid $mode
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
--TEST--
2+
dechunk filter: seeking to position 0 resets the filter's internal state
3+
--SKIPIF--
4+
<?php
5+
if (!in_array('dechunk', stream_get_filters(), true)) die('skip dechunk filter not available');
6+
?>
7+
--FILE--
8+
<?php
9+
10+
$body = "8\r\nSymfony \r\n5\r\nis aw\r\n6\r\nesome!\r\n0\r\n\r\n";
11+
12+
// no seek, post-terminator writes are discarded
13+
$h = fopen('php://temp', 'w+');
14+
stream_filter_append($h, 'dechunk', STREAM_FILTER_WRITE);
15+
fwrite($h, $body);
16+
$before = ftell($h);
17+
fwrite($h, '-');
18+
var_dump(ftell($h) === $before);
19+
20+
// rewind() resets the filter: subsequent writes are processed as a
21+
// new chunked stream, so invalid input like "-" leaks through
22+
$h = fopen('php://temp', 'w+');
23+
stream_filter_append($h, 'dechunk', STREAM_FILTER_WRITE);
24+
fwrite($h, $body);
25+
rewind($h);
26+
$before = ftell($h);
27+
fwrite($h, '-');
28+
var_dump(ftell($h) > $before);
29+
30+
// stream_get_contents($h, -1, 0) performs an implicit seek to 0
31+
$h = fopen('php://temp', 'w+');
32+
stream_filter_append($h, 'dechunk', STREAM_FILTER_WRITE);
33+
fwrite($h, $body);
34+
stream_get_contents($h, -1, 0);
35+
$before = ftell($h);
36+
fwrite($h, '-');
37+
var_dump(ftell($h) > $before);
38+
39+
// after reset, the filter correctly decodes a fresh chunked body
40+
$h = fopen('php://temp', 'w+');
41+
stream_filter_append($h, 'dechunk', STREAM_FILTER_WRITE);
42+
fwrite($h, $body);
43+
rewind($h);
44+
ftruncate($h, 0);
45+
fwrite($h, "1\r\nX\r\n0\r\n\r\n");
46+
var_dump(stream_get_contents($h, -1, 0));
47+
48+
?>
49+
--EXPECT--
50+
bool(true)
51+
bool(true)
52+
bool(true)
53+
string(1) "X"

0 commit comments

Comments
 (0)