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