xref: /PHP-7.4/ext/openssl/tests/bug77390.phpt (revision 043ce4c8)
1--TEST--
2Bug #76705: feof might hang on TLS streams in case of fragmented TLS records
3--SKIPIF--
4<?php
5if (!extension_loaded("openssl")) die("skip openssl not loaded");
6if (!function_exists("proc_open")) die("skip no proc_open");
7?>
8--FILE--
9<?php
10$certFile = __DIR__ . DIRECTORY_SEPARATOR . 'bug77390.pem.tmp';
11$cacertFile = __DIR__ . DIRECTORY_SEPARATOR . 'bug77390-ca.pem.tmp';
12
13$peerName = 'bug77390';
14$clientCode = <<<'CODE'
15    $context = stream_context_create(['ssl' => ['verify_peer' => false, 'peer_name' => '%s']]);
16
17    phpt_wait('server');
18    phpt_notify('proxy');
19
20    phpt_wait('proxy');
21    $fp = stream_socket_client("ssl://127.0.0.1:10012", $errornum, $errorstr, 3000, STREAM_CLIENT_CONNECT, $context);
22    stream_set_blocking($fp, false);
23
24    $read = [$fp];
25    $buf = '';
26    $emptyChunkPrinted = false;
27    $warmedUp = false;
28    while (stream_select($read, $write, $except, 1000)) {
29        $chunk = stream_get_contents($fp, 4096);
30        $buf .= $chunk;
31        phpt_notify('proxy');
32        if (!$warmedUp) {
33            if ($buf !== 'warmup') {
34                continue;
35            }
36            $warmedUp = true;
37            $buf = '';
38            phpt_notify('server');
39            continue;
40        }
41        if ($chunk !== '' || !$emptyChunkPrinted) {
42            $emptyChunkPrinted = true;
43            var_dump($chunk);
44        }
45        if ($buf === 'hello, world') {
46            break;
47        }
48    }
49
50    phpt_notify('server');
51    phpt_notify('proxy');
52CODE;
53$clientCode = sprintf($clientCode, $peerName);
54
55$serverCode = <<<'CODE'
56    $context = stream_context_create(['ssl' => ['local_cert' => '%s']]);
57
58    $flags = STREAM_SERVER_BIND|STREAM_SERVER_LISTEN;
59    $fp = stream_socket_server("ssl://127.0.0.1:10011", $errornum, $errorstr, $flags, $context);
60    phpt_notify();
61
62    $conn = stream_socket_accept($fp);
63    fwrite($conn, 'warmup');
64    phpt_wait();
65    fwrite($conn, 'hello, world');
66
67    phpt_wait();
68    fclose($conn);
69CODE;
70$serverCode = sprintf($serverCode, $certFile);
71
72$proxyCode = <<<'CODE'
73    phpt_wait();
74
75    $upstream = stream_socket_client("tcp://127.0.0.1:10011", $errornum, $errorstr, 3000, STREAM_CLIENT_CONNECT);
76    stream_set_blocking($upstream, false);
77
78    $flags = STREAM_SERVER_BIND|STREAM_SERVER_LISTEN;
79    $server = stream_socket_server("tcp://127.0.0.1:10012", $errornum, $errorstr, $flags);
80    phpt_notify();
81
82    $conn = stream_socket_accept($server);
83    stream_set_blocking($conn, false);
84
85    $read = [$upstream, $conn];
86    while (stream_select($read, $write, $except, 1)) {
87        foreach ($read as $fp) {
88            $data = stream_get_contents($fp);
89            if ($fp === $conn) {
90                fwrite($upstream, $data);
91            } else {
92                if ($data !== '' && $data[0] === chr(23)) {
93                    $parts = str_split($data, (int) ceil(strlen($data) / 3));
94                    foreach ($parts as $part) {
95                        fwrite($conn, $part);
96                        phpt_wait(null, 1);
97                    }
98                } else {
99                    fwrite($conn, $data);
100                }
101            }
102        }
103        if (feof($upstream)) {
104            break;
105        }
106        $read = [$upstream, $conn];
107    }
108
109    phpt_wait();
110CODE;
111
112include 'CertificateGenerator.inc';
113$certificateGenerator = new CertificateGenerator();
114$certificateGenerator->saveCaCert($cacertFile);
115$certificateGenerator->saveNewCertAsFileWithKey($peerName, $certFile);
116
117include 'ServerClientTestCase.inc';
118ServerClientTestCase::getInstance()->run($clientCode, [
119    'server' => $serverCode,
120    'proxy' => $proxyCode,
121]);
122?>
123--CLEAN--
124<?php
125@unlink(__DIR__ . DIRECTORY_SEPARATOR . 'bug77390.pem.tmp');
126@unlink(__DIR__ . DIRECTORY_SEPARATOR . 'bug77390-ca.pem.tmp');
127?>
128--EXPECT--
129string(0) ""
130string(12) "hello, world"
131