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