Commit d2780bcbaea for php.net
commit d2780bcbaea2c9e90dbff482eced68ad3a98b499
Author: Ilija Tovilo <ilija.tovilo@me.com>
Date: Wed Aug 5 16:28:48 2026 +0200
Fix use-after-free in OpenSSL empty cafile warning (GH-22880)
diff --git a/ext/openssl/tests/stream_cafile_no_valid_certs.phpt b/ext/openssl/tests/stream_cafile_no_valid_certs.phpt
new file mode 100644
index 00000000000..4622dfbf576
--- /dev/null
+++ b/ext/openssl/tests/stream_cafile_no_valid_certs.phpt
@@ -0,0 +1,42 @@
+--TEST--
+SSL cafile stream containing no valid certificates
+--EXTENSIONS--
+openssl
+--SKIPIF--
+<?php
+if (!function_exists('proc_open')) die('skip no proc_open');
+?>
+--FILE--
+<?php
+$serverCode = <<<'CODE'
+ $server = stream_socket_server('tcp://127.0.0.1:0', $errno, $errstr);
+ phpt_notify_server_start($server);
+
+ $client = stream_socket_accept($server, 2);
+ if ($client) {
+ fclose($client);
+ }
+CODE;
+
+$clientCode = <<<'CODE'
+ $context = stream_context_create(['ssl' => [
+ 'cafile' => 'file://%s',
+ ]]);
+ var_dump(stream_socket_client(
+ 'ssl://{{ ADDR }}',
+ timeout: 2,
+ context: $context,
+ ));
+CODE;
+$clientCode = sprintf($clientCode, __DIR__ . '/plain.txt');
+
+include 'ServerClientTestCase.inc';
+ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
+?>
+--EXPECTF--
+Warning: stream_socket_client(): no valid certs found cafile stream: '%s' in %sServerClientTestCase.inc(%d) : eval()'d code on line 4
+
+Warning: stream_socket_client(): Failed to enable crypto in %sServerClientTestCase.inc(%d) : eval()'d code on line 4
+
+Warning: stream_socket_client(): Unable to connect to ssl://127.0.0.1:%d (Unknown error) in %sServerClientTestCase.inc(%d) : eval()'d code on line 4
+bool(false)
diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c
index 130d3717ccc..269de954538 100644
--- a/ext/openssl/xp_ssl.c
+++ b/ext/openssl/xp_ssl.c
@@ -947,15 +947,14 @@ static long php_openssl_load_stream_cafile(X509_STORE *cert_store, const char *c
goto cert_start;
}
- stream_complete: {
- php_stream_close(stream);
- if (buffer_active == 1) {
- BIO_free(buffer);
- }
+stream_complete:
+ if (certs_added == 0) {
+ php_stream_warn(stream, DecodingFailed, "no valid certs found cafile stream: '%s'", cafile);
}
- if (certs_added == 0) {
- php_stream_warn(stream, DecodingFailed, "no valid certs found cafile stream: `%s'", cafile);
+ php_stream_close(stream);
+ if (buffer_active == 1) {
+ BIO_free(buffer);
}
return certs_added;