Skip to content

Commit e214146

Browse files
committed
io: add stream copy tests for pipe, ssl, append and maxlen paths
1 parent 4c30e3e commit e214146

4 files changed

Lines changed: 190 additions & 0 deletions

File tree

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
--TEST--
2+
stream_copy_to_stream() from a TLS stream copies decrypted data (no fd fast-path)
3+
--EXTENSIONS--
4+
openssl
5+
--SKIPIF--
6+
<?php
7+
if (!function_exists("proc_open")) die("skip no proc_open");
8+
?>
9+
--FILE--
10+
<?php
11+
12+
$certFile = __DIR__ . DIRECTORY_SEPARATOR . 'stream_copy_ssl.pem.tmp';
13+
$cacertFile = __DIR__ . DIRECTORY_SEPARATOR . 'stream_copy_ssl-ca.pem.tmp';
14+
15+
$serverCode = <<<'CODE'
16+
$serverCtx = stream_context_create(['ssl' => [
17+
'local_cert' => '%s',
18+
]]);
19+
$flags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN;
20+
$server = stream_socket_server("ssl://127.0.0.1:0", $errno, $errstr, $flags, $serverCtx);
21+
phpt_notify_server_start($server);
22+
23+
$conn = stream_socket_accept($server, 5);
24+
fwrite($conn, str_repeat("secret-", 1000));
25+
fclose($conn);
26+
fclose($server);
27+
CODE;
28+
$serverCode = sprintf($serverCode, $certFile);
29+
30+
$peerName = 'stream_copy_ssl_peer';
31+
$clientCode = <<<'CODE'
32+
$clientCtx = stream_context_create(['ssl' => [
33+
'verify_peer' => true,
34+
'cafile' => '%s',
35+
'peer_name' => '%s',
36+
]]);
37+
$client = stream_socket_client("ssl://{{ ADDR }}", $errno, $errstr, 5, STREAM_CLIENT_CONNECT, $clientCtx);
38+
39+
$tmp = tmpfile();
40+
/* If the copy offloaded the raw socket fd it would write ciphertext; the
41+
* decrypted plaintext proves it correctly fell back to the userspace loop. */
42+
$copied = stream_copy_to_stream($client, $tmp);
43+
var_dump($copied);
44+
45+
fseek($tmp, 0, SEEK_SET);
46+
$content = stream_get_contents($tmp);
47+
var_dump(strlen($content));
48+
var_dump($content === str_repeat("secret-", 1000));
49+
50+
fclose($tmp);
51+
fclose($client);
52+
CODE;
53+
$clientCode = sprintf($clientCode, $cacertFile, $peerName);
54+
55+
include 'CertificateGenerator.inc';
56+
$certificateGenerator = new CertificateGenerator();
57+
$certificateGenerator->saveCaCert($cacertFile);
58+
$certificateGenerator->saveNewCertAsFileWithKey($peerName, $certFile);
59+
60+
include 'ServerClientTestCase.inc';
61+
ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
62+
?>
63+
--CLEAN--
64+
<?php
65+
@unlink(__DIR__ . DIRECTORY_SEPARATOR . 'stream_copy_ssl.pem.tmp');
66+
@unlink(__DIR__ . DIRECTORY_SEPARATOR . 'stream_copy_ssl-ca.pem.tmp');
67+
?>
68+
--EXPECT--
69+
int(7000)
70+
int(7000)
71+
bool(true)
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
--TEST--
2+
stream_copy_to_stream() file to file with an append-mode destination
3+
--FILE--
4+
<?php
5+
6+
$srcFile = __DIR__ . '/stream_copy_append_src.txt';
7+
$dstFile = __DIR__ . '/stream_copy_append_dst.txt';
8+
9+
file_put_contents($srcFile, str_repeat("b", 3000));
10+
file_put_contents($dstFile, "PREFIX-");
11+
12+
$src = fopen($srcFile, 'r');
13+
/* O_APPEND must disable the fd-level copy fast-path and still append correctly. */
14+
$dst = fopen($dstFile, 'a');
15+
16+
$copied = stream_copy_to_stream($src, $dst);
17+
var_dump($copied);
18+
19+
fclose($src);
20+
fclose($dst);
21+
22+
$result = file_get_contents($dstFile);
23+
var_dump(strlen($result));
24+
var_dump($result === "PREFIX-" . str_repeat("b", 3000));
25+
?>
26+
--CLEAN--
27+
<?php
28+
@unlink(__DIR__ . '/stream_copy_append_src.txt');
29+
@unlink(__DIR__ . '/stream_copy_append_dst.txt');
30+
?>
31+
--EXPECT--
32+
int(3000)
33+
int(3007)
34+
bool(true)
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
--TEST--
2+
stream_copy_to_stream() with a pipe as $source and file as $dest
3+
--SKIPIF--
4+
<?php
5+
if (!function_exists("proc_open")) die("skip no proc_open");
6+
?>
7+
--FILE--
8+
<?php
9+
10+
$descriptors = [1 => ['pipe', 'w']];
11+
$proc = proc_open(
12+
[PHP_BINARY, '-n', '-r', 'echo str_repeat("p", 5000);'],
13+
$descriptors,
14+
$pipes
15+
);
16+
var_dump(is_resource($proc));
17+
18+
$source = $pipes[1];
19+
$tmp = tmpfile();
20+
21+
$copied = stream_copy_to_stream($source, $tmp);
22+
var_dump($copied);
23+
24+
fseek($tmp, 0, SEEK_SET);
25+
$content = stream_get_contents($tmp);
26+
var_dump(strlen($content));
27+
var_dump($content === str_repeat("p", 5000));
28+
29+
fclose($tmp);
30+
fclose($source);
31+
proc_close($proc);
32+
?>
33+
--EXPECT--
34+
bool(true)
35+
int(5000)
36+
int(5000)
37+
bool(true)
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
--TEST--
2+
stream_copy_to_stream() socket to file with a maxlength shorter than the data
3+
--SKIPIF--
4+
<?php
5+
if (!function_exists("proc_open")) die("skip no proc_open");
6+
?>
7+
--FILE--
8+
<?php
9+
10+
$serverCode = <<<'CODE'
11+
$server = stream_socket_server("tcp://127.0.0.1:0", $errno, $errstr);
12+
phpt_notify_server_start($server);
13+
14+
$conn = stream_socket_accept($server);
15+
fwrite($conn, str_repeat("a", 10000));
16+
stream_socket_shutdown($conn, STREAM_SHUT_WR);
17+
18+
/* Keep alive until client is done reading. */
19+
fread($conn, 1);
20+
21+
fclose($conn);
22+
fclose($server);
23+
CODE;
24+
25+
$clientCode = <<<'CODE'
26+
$source = stream_socket_client("tcp://{{ ADDR }}", $errno, $errstr, 10);
27+
$tmp = tmpfile();
28+
29+
/* Only 4096 of the 10000 available bytes must be copied. */
30+
$copied = stream_copy_to_stream($source, $tmp, 4096);
31+
var_dump($copied);
32+
33+
fseek($tmp, 0, SEEK_SET);
34+
$content = stream_get_contents($tmp);
35+
var_dump(strlen($content));
36+
var_dump($content === str_repeat("a", 4096));
37+
38+
fclose($tmp);
39+
fclose($source);
40+
CODE;
41+
42+
include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__);
43+
ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
44+
?>
45+
--EXPECT--
46+
int(4096)
47+
int(4096)
48+
bool(true)

0 commit comments

Comments
 (0)