Skip to content

Commit 18a0c03

Browse files
committed
streams: allow filtered streams to be casted as fd for select
1 parent d9d55f0 commit 18a0c03

File tree

3 files changed

+91
-1
lines changed

3 files changed

+91
-1
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
--TEST--
2+
stream_select() base64-decode filter basic usage
3+
--FILE--
4+
<?php
5+
$file = fopen('php://temp', 'r+');
6+
7+
// Write complete base64 "Hello World"
8+
fwrite($file, 'SGVsbG8gV29ybGQ=');
9+
10+
stream_filter_append($file, 'convert.base64-decode');
11+
rewind($file);
12+
13+
$read = [$file];
14+
$write = null;
15+
$except = null;
16+
17+
$result = stream_select($read, $write, $except, 0);
18+
19+
if ($result !== false) {
20+
echo "stream_select succeeded\n";
21+
if (count($read) > 0) {
22+
echo fread($file, 1024) . "\n";
23+
}
24+
} else {
25+
echo "stream_select failed\n";
26+
}
27+
28+
fclose($file);
29+
?>
30+
--EXPECT--
31+
stream_select succeeded
32+
Hello World
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
--TEST--
2+
stream_select() base64-decode filter buffered data usage
3+
--FILE--
4+
<?php
5+
$pipes = stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP);
6+
if ($pipes === false) {
7+
die("Failed to create socket pair");
8+
}
9+
10+
list($read_pipe, $write_pipe) = $pipes;
11+
12+
stream_set_blocking($read_pipe, false);
13+
stream_filter_append($read_pipe, 'convert.base64-decode');
14+
15+
// Write incomplete base64 data: "SGVs" decodes to "Hel" but "SGVs" is incomplete
16+
fwrite($write_pipe, 'SGVs');
17+
fflush($write_pipe);
18+
19+
$read = [$read_pipe];
20+
$write = null;
21+
$except = null;
22+
23+
$result = fread($read_pipe, 1024);
24+
echo "Decoded content (before select): " . $result . "\n";
25+
26+
// Should succeed but stream should NOT be readable yet (data buffered in filter)
27+
$result = stream_select($read, $write, $except, 0, 1000);
28+
echo "After incomplete data - select result: " . $result . "\n";
29+
echo "After incomplete data - readable streams: " . count($read) . "\n";
30+
31+
// Now complete the base64 sequence: "SGVsbG8=" decodes to "Hello"
32+
fwrite($write_pipe, 'bG8=');
33+
fflush($write_pipe);
34+
35+
$read = [$read_pipe];
36+
$write = null;
37+
$except = null;
38+
39+
// Now stream should be readable
40+
$result = stream_select($read, $write, $except, 0, 1000);
41+
echo "After complete data - select result: " . $result . "\n";
42+
echo "After complete data - readable streams: " . count($read) . "\n";
43+
44+
if (count($read) > 0) {
45+
$content = fread($read_pipe, 1024);
46+
echo "Decoded content: " . $content . "\n";
47+
}
48+
49+
fclose($read_pipe);
50+
fclose($write_pipe);
51+
?>
52+
--EXPECT--
53+
Decoded content (before select): Hel
54+
After incomplete data - select result: 0
55+
After incomplete data - readable streams: 0
56+
After complete data - select result: 1
57+
After complete data - readable streams: 1
58+
Decoded content: lo

main/streams/cast.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ PHPAPI zend_result _php_stream_cast(php_stream *stream, int castas, void **ret,
297297
}
298298
}
299299

300-
if (php_stream_is_filtered(stream)) {
300+
if (php_stream_is_filtered(stream) && castas != PHP_STREAM_AS_FD_FOR_SELECT) {
301301
if (show_err) {
302302
php_error_docref(NULL, E_WARNING, "Cannot cast a filtered stream on this system");
303303
}

0 commit comments

Comments
 (0)