Skip to content

Commit 45d6daa

Browse files
committed
Merge branch 'PHP-8.4' into PHP-8.5
* PHP-8.4: Fix NULL deref when enabling TLS fails and the peer name needs to be reset
2 parents c633ce8 + 7782b88 commit 45d6daa

4 files changed

Lines changed: 152 additions & 3 deletions

File tree

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ PHP NEWS
2727
. Fixed bug GH-21499 (RecursiveArrayIterator getChildren UAF after parent
2828
free). (Girgias)
2929

30+
- Streams:
31+
. Fixed bug GH-21468 (Segfault in file_get_contents w/ a https URL
32+
and a proxy set). (ndossche)
33+
3034
26 Mar 2026, PHP 8.5.5
3135

3236
- Core:

ext/openssl/tests/gh21031.phpt

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
--TEST--
2+
GH-21031 (Fix NULL deref when enabling TLS fails and the peer name needs to be reset)
3+
--EXTENSIONS--
4+
openssl
5+
--SKIPIF--
6+
<?php
7+
if (!function_exists("proc_open")) die("skip no proc_open");
8+
if (substr(PHP_OS, 0, 3) == 'WIN') {
9+
die("skip not reliable on Windows due to proxy wait limitation");
10+
}
11+
?>
12+
--FILE--
13+
<?php
14+
15+
$serverCode = <<<'CODE'
16+
$serverFlags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN;
17+
$ctx = stream_context_create(['ssl' => [
18+
'SNI_server_certs' => [
19+
"cs.php.net" => __DIR__ . "/sni_server_cs_expired.pem",
20+
]
21+
]]);
22+
23+
$server = stream_socket_server('tls://127.0.0.1:0', $errno, $errstr, $serverFlags, $ctx);
24+
phpt_notify_server_start($server);
25+
26+
$conn = stream_socket_accept($server, 3);
27+
fclose($conn);
28+
29+
phpt_wait();
30+
CODE;
31+
32+
$proxyCode = <<<'CODE'
33+
$flags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN;
34+
$server = stream_socket_server("tcp://127.0.0.1:0", $errornum, $errorstr, $flags);
35+
phpt_notify_server_start($server);
36+
37+
$upstream = stream_socket_client("tcp://{{ ADDR }}", $errornum, $errorstr, 30, STREAM_CLIENT_CONNECT);
38+
stream_set_blocking($upstream, false);
39+
40+
$conn = stream_socket_accept($server);
41+
stream_set_blocking($conn, true);
42+
43+
// reading CONNECT request headers
44+
while (($line = fgets($conn)) !== false) {
45+
if (rtrim($line) === '') break; // empty line means end of headers
46+
}
47+
48+
// successful CONNECT response
49+
fwrite($conn, "HTTP/1.0 200 Connection established\r\n\r\n");
50+
51+
fclose($conn);
52+
fclose($upstream);
53+
phpt_wait();
54+
CODE;
55+
56+
$clientCode = <<<'CODE'
57+
$clientCtx = stream_context_create([
58+
'ssl' => [
59+
'cafile' => __DIR__ . '/sni_server_ca.pem',
60+
'verify_peer' => true,
61+
'verify_peer_name' => true,
62+
],
63+
"http" => [
64+
"proxy" => "tcp://{{ ADDR }}"
65+
],
66+
]);
67+
68+
var_dump(file_get_contents("https://cs.php.net/", false, $clientCtx));
69+
70+
phpt_notify('proxy');
71+
phpt_notify('server');
72+
CODE;
73+
74+
include 'ServerClientTestCase.inc';
75+
ServerClientTestCase::getInstance()->run($clientCode, [
76+
'server' => $serverCode,
77+
'proxy' => $proxyCode,
78+
]);
79+
?>
80+
--EXPECTF--
81+
Warning: file_get_contents(https://cs.php.net/): Failed to open stream: Cannot connect to HTTPS server through proxy in %s
82+
bool(false)
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
-----BEGIN RSA PRIVATE KEY-----
2+
MIIEpQIBAAKCAQEAvy5NhzktzEdsHTbGB6vqYANms5rn1zXFmTJrGlWCwoIsNmTf
3+
ahvZkrC1cCXTZ7fbPB8XQbpAtz2ZSU7OcwBW9B8okYUPo9zi/ptwcrgsQsN0hrcD
4+
8MBRUccevwime5fLvg8E9RJ/68y9y3BnRcVWYO2sAK9juTfidNjETU3Bb05oXv8D
5+
SD/6onXQu4uXDgsQ3cRXeld9UB0xazmQXyyiIqXc/cpTAnaEVYzn28aj7NlUbzNq
6+
511UXMXY44x9EcXWpPVZ7heNcJNzY5DCNzmtXKrt9yiMpWQcPXEzsESVxAMqib9u
7+
TFOlvVX17LIPxBG656PjTD9J1h6kBbMCUxzs7wIDAQABAoIBAQC85lBeY0X4ST3v
8+
I7bJz7kWQ2YP4uhfAdeLhoDDFWjNLffniwYhfwEc6xNri0R2f/jUT9gX7qORKwEx
9+
qPdeNCC2t67LElGg1FlJv2Z9Q7MgCKYzkdQH5s6y4e9kTHTLO/JpiceZKz1QTQ3f
10+
XOH9032E6nIAf0wmr6xHTgOwajrN8VI5BuPEMVmEwIw3AtYeqVuPCNKyGR4HUVkC
11+
2bAydnGngbRJRnNzmKcWJancxpHDGBSFqPyuXMFC7Jgo3ZmyCbGp99vuXVk/sW9x
12+
5aj94M9nRE0guk05ivH2/JZao2uLYkIgjFWlhNxKdWgWRk8DEuN4djC8mKS9YH1q
13+
crYRToMhAoGBAOspUTtKP54mpZmyhxuDqj02JaJRzNTskPHsiF1UhtXuw7uT+ryV
14+
ekUFLNXoFmn9mbx1WVaUvGH4qjilvQOxz7u++lz0ApqJEfyM3jc/cC40Y5zcuGSu
15+
Etbg+SyDoytlgMCIydJyrS7NNALSo5p5oG6XY2f8yd/DCAmo8LzypaHRAoGBANAf
16+
R1SlBMc/bOsi6GrJxcBVSCFMiKYiO5woL5aUKa9yM+UQuQ/6xbQ7Q+sOlt0FH3xo
17+
AJ2L60qTdjyXVtjOdtXs5ZC4l+C6AfnCx6yLr+fNc4SOYXEfqS4LZylgwKd9KyVB
18+
asspIW9Idbgebmi6vPyt9LDkIp0h1VuFGjkvQJK/AoGBAI4pbS0dprXyARyYW6sb
19+
fpgAmuG099IkrT9DUfCx/81myTclr2fAKal+BmvOIXaz0/OlMXvw8K19iVIzh7+r
20+
B70lJ+93p/dKM/BsLI5TsHqOO0YB/QsIXOVAHgJ2FfdPJnW+e9vYba+kZ/Po6PSi
21+
4ITaykJ8BIJcQgis89QWEGFxAoGBAJhQO+jzuDKF9ZWEf6ofrw0anOZZ16wWY5/e
22+
PS2rk3JmVxpuibHrKqPDt+ogTELHDAsFJmYmz3VNxHuFmrajK49Wh4/JuMVr/CQo
23+
6+8YcA1qa/94IFIlBLDBAafjujsZvOjQHnM+z8xcsGKmStF00Pjv6qNG4xoyd646
24+
FD4DmfOLAoGAWXehpopZKXE9gRAni881ucK6WqxPPBoofbozi09D0MmfarIVaSkv
25+
jNVVHBfLWd7IEXTjiipPBeUqq6Jc3pscN1Vp4rrl8jTmVTdazEv0LuzpdUFqmNo2
26+
M+xw17uz9D9Q32/aW1Lar0PdIaL/wGEDEyzEBFwrGppcENLilPz8gzU=
27+
-----END RSA PRIVATE KEY-----
28+
-----BEGIN CERTIFICATE-----
29+
MIIFIjCCAwqgAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwVTELMAkGA1UEBhMCR0Ix
30+
EDAOBgNVBAgMB0VuZ2xhbmQxEDAOBgNVBAoMB1BIUC5uZXQxEDAOBgNVBAsMB29w
31+
ZW5zc2wxEDAOBgNVBAMMB3BocC5uZXQwHhcNMTgwMTE0MTgzNjEyWhcNMjYwNDAy
32+
MTgzNjEyWjBGMQswCQYDVQQGEwJHQjEQMA4GA1UECAwHRW5nbGFuZDEQMA4GA1UE
33+
CgwHUEhQLm5ldDETMBEGA1UEAwwKY3MucGhwLm5ldDCCASIwDQYJKoZIhvcNAQEB
34+
BQADggEPADCCAQoCggEBAL8uTYc5LcxHbB02xger6mADZrOa59c1xZkyaxpVgsKC
35+
LDZk32ob2ZKwtXAl02e32zwfF0G6QLc9mUlOznMAVvQfKJGFD6Pc4v6bcHK4LELD
36+
dIa3A/DAUVHHHr8IpnuXy74PBPUSf+vMvctwZ0XFVmDtrACvY7k34nTYxE1NwW9O
37+
aF7/A0g/+qJ10LuLlw4LEN3EV3pXfVAdMWs5kF8soiKl3P3KUwJ2hFWM59vGo+zZ
38+
VG8zauddVFzF2OOMfRHF1qT1We4XjXCTc2OQwjc5rVyq7fcojKVkHD1xM7BElcQD
39+
Kom/bkxTpb1V9eyyD8QRuuej40w/SdYepAWzAlMc7O8CAwEAAaOCAQkwggEFMAkG
40+
A1UdEwQCMAAwEQYJYIZIAYb4QgEBBAQDAgZAMDMGCWCGSAGG+EIBDQQmFiRPcGVu
41+
U1NMIEdlbmVyYXRlZCBTZXJ2ZXIgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFHPfd8dK
42+
Lz1R0Ck4WV1B9AWXd5DSMGwGA1UdIwRlMGOAFOPK44Eacedv7HbR2Igcbew+4kUa
43+
oUekRTBDMQswCQYDVQQGEwJHQjEQMA4GA1UECAwHRW5nbGFuZDEQMA4GA1UECgwH
44+
UEhQLm5ldDEQMA4GA1UEAwwHcGhwLm5ldIICEAAwDgYDVR0PAQH/BAQDAgWgMBMG
45+
A1UdJQQMMAoGCCsGAQUFBwMBMA0GCSqGSIb3DQEBCwUAA4ICAQB6WSIHEyDXLZxH
46+
hZjqSNQOA7Wc9Z2FCAiD29xYkGTL8WuPVGGP1mu4B92ytj+PMWwqSReDa7eTGLE7
47+
O7ozw9l+c+gNmHFNikSsGjlV2E8CToQOFMny+jAQYMSXf8UbTp9xDfgG02t/71hv
48+
SLWqdeHMLcR0xi0nBQH0vDOkwUbuWYqFa3jejHieGhykHM6CkIk6lqnyOEO+ooIF
49+
ZsLprrg1ss/mXCPI6niP0hze55ERKdxI7Rk8sZ4pVkf2SUWqZrUS0aJ+Ymmwi6Xd
50+
2V7izq5N30PkJS8MtqII4FAjRBIkwPh0sy8PmW/DzkYU+lYQnDfYLKDFKcj8xJK/
51+
o8oZUBsQltrSj0KlM9QuqxCTCBCy1nXZ9WHOhq+jdLiTc1Oi60uEHcUMrLK8aYc4
52+
HqIvZS6C2iwMI0d1OP3VxmAbMQ9yqRi+FbLYavJ3H40jrU9SYqdxa0BrTaz8MJNE
53+
6AEwgQDPChczSghvHME+Fs4mtGCY3TesbNZKVahQRjaFIhMZIZ4RP4CRc0bJOBG+
54+
8Me4+KHNsD2ki5b03wAN6C1P2QrMzI+gH9fXLZYp761ciDAsX6YIzrhHHYLxYpJH
55+
BkQKKs8dCQWE5IzgVrdlvC3Z1/l9om66wHqqx7nKnPfYs/Sfnwe9MpCD6xJrXiTm
56+
WS7NM6fbQpO9APNr7o0ZOjbbWFzlNw==
57+
-----END CERTIFICATE-----

ext/standard/http_fopen_wrapper.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,10 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper,
547547
smart_str_appendl(&header, "\r\n", sizeof("\r\n")-1);
548548

549549
if (php_stream_write(stream, ZSTR_VAL(header.s), ZSTR_LEN(header.s)) != ZSTR_LEN(header.s)) {
550+
if (reset_ssl_peer_name) {
551+
php_stream_context_unset_option(PHP_STREAM_CONTEXT(stream), "ssl", "peer_name");
552+
}
553+
550554
php_stream_wrapper_log_error(wrapper, options, "Cannot connect to HTTPS server through proxy");
551555
php_stream_close(stream);
552556
stream = NULL;
@@ -568,16 +572,18 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper,
568572

569573
/* enable SSL transport layer */
570574
if (stream) {
575+
php_stream_context *old_context = PHP_STREAM_CONTEXT(stream);
576+
571577
if (php_stream_xport_crypto_setup(stream, STREAM_CRYPTO_METHOD_SSLv23_CLIENT, NULL) < 0 ||
572578
php_stream_xport_crypto_enable(stream, 1) < 0) {
573579
php_stream_wrapper_log_error(wrapper, options, "Cannot connect to HTTPS server through proxy");
574580
php_stream_close(stream);
575581
stream = NULL;
576582
}
577-
}
578583

579-
if (reset_ssl_peer_name) {
580-
php_stream_context_unset_option(PHP_STREAM_CONTEXT(stream), "ssl", "peer_name");
584+
if (reset_ssl_peer_name) {
585+
php_stream_context_unset_option(old_context, "ssl", "peer_name");
586+
}
581587
}
582588
}
583589

0 commit comments

Comments
 (0)