xref: /PHP-8.4/ext/openssl/tests/bug74159.phpt (revision 74859783)
1--TEST--
2Bug #74159: Writing a large buffer to non-blocking encrypted streams fails
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 . 'bug74159.pem.tmp';
12$cacertFile = __DIR__ . DIRECTORY_SEPARATOR . 'bug74159-ca.pem.tmp';
13
14// the server code is doing many readings in a short interval which is
15// not really reliable on more powerful machine but cover different
16// scenarios which might be useful. More reliable test is bug72333.phpt
17$serverCode = <<<'CODE'
18    $serverUri = "ssl://127.0.0.1:10012";
19    $serverFlags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN;
20    $serverCtx = stream_context_create(['ssl' => [
21        'local_cert' => '%s',
22        'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_2_SERVER,
23    ]]);
24
25    $server = stream_socket_server($serverUri, $errno, $errstr, $serverFlags, $serverCtx);
26    phpt_notify();
27
28    $client = stream_socket_accept($server, 1);
29
30    if (!$client) {
31        exit();
32    }
33
34    $data = '';
35    while (strlen($data) < 0xfffff) {
36        $buffer = fread($client, 8192);
37        if (empty($buffer)) {
38            exit();
39        }
40        $data .= $buffer;
41        usleep(100);
42    }
43
44    fclose($client);
45CODE;
46$serverCode = sprintf($serverCode, $certFile);
47
48$peerName = 'bug74159';
49$clientCode = <<<'CODE'
50    function streamRead($stream) : int {
51        return strlen(fread($stream, 8192));
52    }
53
54    function streamWrite($stream, $data) : int {
55        return fwrite($stream, $data);
56    }
57
58    function waitForWrite(...$streams) : bool {
59        $read = null;
60        $except = null;
61        while($streams && !($n = stream_select($read, $streams, $except, 1)));
62        return $n > 0;
63    }
64
65    function waitForRead(...$streams) : bool {
66        $write = null;
67        $except = null;
68        while ($streams && !($n = stream_select($streams, $write, $except, 1)));
69        return $n > 0;
70    }
71
72    set_error_handler(function ($errno, $errstr) {
73        exit("$errstr\n");
74    });
75
76    $serverUri = "tcp://127.0.0.1:10012";
77    $clientFlags = STREAM_CLIENT_CONNECT;
78    $clientCtx = stream_context_create(['ssl' => [
79        'verify_peer' => true,
80        'cafile' => '%s',
81        'peer_name' => '%s',
82    ]]);
83
84    phpt_wait();
85
86    $fp = stream_socket_client($serverUri, $errno, $errstr, 1, $clientFlags, $clientCtx);
87
88    stream_set_blocking($fp, false);
89    while (0 === ($n = stream_socket_enable_crypto($fp, true, STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT)));
90
91    $data = str_repeat("a", 0xfffff);
92    $written = 0;
93    $total = $written;
94    while(!empty($data)) {
95        $written = streamWrite($fp, $data);
96        $total += $written;
97        $data = substr($data, $written);
98        waitForWrite($fp);
99    }
100    printf("Written %%d bytes\n", $total);
101
102    while(waitForRead($fp)) {
103        streamRead($fp);
104        if (feof($fp)) {
105            break;
106        }
107    }
108
109    exit("DONE\n");
110CODE;
111$clientCode = sprintf($clientCode, $cacertFile, $peerName);
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, $serverCode);
120?>
121--CLEAN--
122<?php
123@unlink(__DIR__ . DIRECTORY_SEPARATOR . 'bug74159.pem.tmp');
124@unlink(__DIR__ . DIRECTORY_SEPARATOR . 'bug74159-ca.pem.tmp');
125?>
126--EXPECT--
127Written 1048575 bytes
128DONE
129