Commit 2a712fb5577 for php.net
commit 2a712fb55775da4cdee2334c15ad391ff8852b20
Author: Jakub Zelenka <bukka@php.net>
Date: Sun Jul 12 21:02:45 2026 +0200
Fix flaky stream_socket_get_crypto_status handshake test (#22707)
The test could intermittently fail because a non-blocking TLS handshake
can complete in a single stream_socket_enable_crypto() call, so
WANT_READ/WANT_WRITE was never observed and $sawWant stayed false.
Route the connection through a plain TCP proxy that forwards the server
handshake flight in fragments, forcing the client to see a partial TLS
record and report WANT_READ at least once.
diff --git a/ext/openssl/tests/stream_socket_get_crypto_status_handshake.phpt b/ext/openssl/tests/stream_socket_get_crypto_status_handshake.phpt
index 2a1c554a79d..7e0f660c980 100644
--- a/ext/openssl/tests/stream_socket_get_crypto_status_handshake.phpt
+++ b/ext/openssl/tests/stream_socket_get_crypto_status_handshake.phpt
@@ -27,6 +27,46 @@
CODE;
$serverCode = sprintf($serverCode, $certFile);
+/* Plain TCP proxy that forwards the server handshake flight in fragments, so the client's
+ * non-blocking handshake sees a partial TLS record and reports WANT_READ instead of completing
+ * in a single call (which can otherwise happen depending on timing). */
+$proxyCode = <<<'CODE'
+ $upstream = stream_socket_client("tcp://{{ ADDR }}", $errno, $errstr, 30, STREAM_CLIENT_CONNECT);
+ stream_set_blocking($upstream, false);
+
+ $flags = STREAM_SERVER_BIND|STREAM_SERVER_LISTEN;
+ $server = stream_socket_server("tcp://127.0.0.1:0", $errno, $errstr, $flags);
+ phpt_notify_server_start($server);
+
+ $conn = stream_socket_accept($server);
+ stream_set_blocking($conn, false);
+
+ $read = [$upstream, $conn];
+ while (stream_select($read, $write, $except, 1)) {
+ foreach ($read as $fp) {
+ $data = stream_get_contents($fp);
+ if ($data === '') {
+ continue;
+ }
+ if ($fp === $conn) {
+ fwrite($upstream, $data);
+ } else {
+ /* Fragment server -> client to force a partial TLS record. */
+ foreach (str_split($data, (int) ceil(strlen($data) / 3)) as $part) {
+ fwrite($conn, $part);
+ usleep(50000);
+ }
+ }
+ }
+ if (feof($upstream) || feof($conn)) {
+ break;
+ }
+ $read = [$upstream, $conn];
+ }
+
+ phpt_wait();
+CODE;
+
/* Client connects over plain TCP, then completes the TLS handshake in non-blocking mode, using
* the reported crypto status to select the right direction to wait on. */
$clientCode = <<<'CODE'
@@ -73,7 +113,8 @@
stream_set_blocking($client, true);
echo trim(fgets($client)), "\n";
- phpt_notify();
+ phpt_notify('server');
+ phpt_notify('proxy');
fclose($client);
CODE;
$clientCode = sprintf($clientCode, $peerName);
@@ -83,7 +124,10 @@
$certificateGenerator->saveNewCertAsFileWithKey($peerName, $certFile);
include 'ServerClientTestCase.inc';
-ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
+ServerClientTestCase::getInstance()->run($clientCode, [
+ 'server' => $serverCode,
+ 'proxy' => $proxyCode,
+]);
?>
--CLEAN--
<?php