Commit 48e53b09213 for php.net
commit 48e53b092135b44cbc919e694e0f174bdc452ae1
Merge: fdc4aa92f4e 2ef7525be76
Author: Jakub Zelenka <bukka@php.net>
Date: Tue Sep 22 11:15:26 2026 +0200
Merge branch 'PHP-8.5'
* PHP-8.5:
Skip bz2 GH-20807 test when less than 13 GiB of memory is available
ext/soap: make GHSA-cj93-vc83-wgqv test lean and reliable
Add NEWS entries
ext/standard: Fix 1-char relative Location redirects after GH-23467
[http] Fix out-of-bounds read on empty Location header
Fix GHSA-ch8v-r6jh-4vvr: encode 0xFF in FILTER_SANITIZE_ENCODED
Fix GHSA-9f67-6fw4-hpfp
Fix GHSA-j3wh-g957-2m85: phar tar entry injection
Fix GHSA-cj93-vc83-wgqv
Fix GHSA-rgrp-mwpx-f6rm: unbounded recursion in ext/soap XML parsing and decoding
Fix GHSA-fpwc-w8rq-cr92: strip credentials from user headers on cross-origin redirects
Fix GHSA-r6x9-5r99-36j7: Various packet overreads in mysqlnd wireprotocol
Fix GHSA-xr7j-rvgx-xq5p: OOB read in php_openssl_matches_wildcard_name()
Fix GHSA-vvx9-73fr-5jjx: do not fall back to CN if the cert has a service ID
Fix GHSA-62xp-839h-2637: FastCGI allowed_clients compared only 96 bits of IPv6 addresses
Fix heap-buffer-overflow in convert stream filters with NUL in line-break-chars
# Conflicts:
# NEWS
# ext/openssl/xp_ssl.c
# ext/phar/tar.c
# ext/soap/php_http.c
# ext/standard/http_fopen_wrapper.c
diff --cc ext/openssl/xp_ssl.c
index 269de954538,10e10691bda..24895a96004
--- a/ext/openssl/xp_ssl.c
+++ b/ext/openssl/xp_ssl.c
@@@ -475,11 -412,10 +475,10 @@@ static bool php_openssl_x509_fingerprin
static bool php_openssl_matches_wildcard_name(const char *subjectname, const char *certname) /* {{{ */
{
const char *wildcard = NULL;
- ptrdiff_t prefix_len;
- size_t suffix_len, subject_len;
+ size_t prefix_len, suffix_len, subject_len;
if (strcasecmp(subjectname, certname) == 0) {
- return 1;
+ return true;
}
/* wildcard, if present, must only be present in the left-most component */
@@@ -586,56 -537,31 +600,55 @@@ static bool php_openssl_matches_san_lis
sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
- return 0;
+ return false;
}
- /* }}} */
-static bool php_openssl_matches_common_name(X509 *peer, const char *subject_name) /* {{{ */
+static bool php_openssl_matches_common_name(php_stream *stream, const X509 *peer, const char *subject_name) /* {{{ */
{
- char buf[1024];
- X509_NAME *cert_name;
- bool is_match = 0;
+ unsigned char *cert_name = NULL;
+#if PHP_OPENSSL_API_VERSION < 0x30000
+ X509_NAME *name;
+#else
+ const X509_NAME *name;
+#endif
+ const X509_NAME_ENTRY *name_entry;
+ const ASN1_STRING *name_asn1;
+ bool is_match = false;
+ int name_index;
int cert_name_len;
- cert_name = X509_get_subject_name(peer);
- cert_name_len = X509_NAME_get_text_by_NID(cert_name, NID_commonName, buf, sizeof(buf));
+ name = X509_get_subject_name(peer);
+ name_index = X509_NAME_get_index_by_NID(name, NID_commonName, -1);
+ if (name_index == -1) {
+ php_stream_warn(stream, NetworkRecvFailed, "Unable to locate peer certificate CN");
+ return false;
+ }
+
+ name_entry = X509_NAME_get_entry(name, name_index);
+ if (name_entry == NULL) {
+ php_stream_warn(stream, NetworkRecvFailed, "Unable to locate peer certificate CN");
+ return false;
+ }
+ name_asn1 = X509_NAME_ENTRY_get_data(name_entry);
+ cert_name_len = ASN1_STRING_length(name_asn1);
+ cert_name = (unsigned char *) OPENSSL_strndup((const char *) ASN1_STRING_get0_data(name_asn1), cert_name_len);
+ if (cert_name == NULL) {
+ php_stream_warn(stream, NetworkRecvFailed, "Unable to locate peer certificate CN");
+ return false;
+ }
- if (cert_name_len == -1) {
- php_error_docref(NULL, E_WARNING, "Unable to locate peer certificate CN");
- } else if ((size_t)cert_name_len != strlen(buf)) {
- php_error_docref(NULL, E_WARNING, "Peer certificate CN=`%.*s' is malformed", cert_name_len, buf);
- } else if (php_openssl_matches_wildcard_name(subject_name, buf)) {
- is_match = 1;
+ if ((size_t)cert_name_len != strlen((const char *)cert_name)) {
+ php_stream_warn(stream, AuthFailed, "Peer certificate CN=`%.*s' is malformed", cert_name_len, (const char *)cert_name);
+ } else if (php_openssl_matches_wildcard_name(subject_name, (const char *)cert_name)) {
+ is_match = true;
} else {
- php_error_docref(NULL, E_WARNING,
+ php_stream_warn(stream, AuthFailed,
"Peer certificate CN=`%.*s' did not match expected CN=`%s'",
- cert_name_len, buf, subject_name);
+ cert_name_len, (const char *)cert_name, subject_name);
}
+ OPENSSL_free(cert_name);
+
return is_match;
}
/* }}} */
@@@ -715,9 -645,17 +728,17 @@@ static zend_result php_openssl_apply_pe
}
if (peer_name) {
- if (php_openssl_matches_san_list(peer, peer_name)) {
+ bool has_service_id = false;
+
+ if (php_openssl_matches_san_list(peer, peer_name, &has_service_id)) {
return SUCCESS;
+ } else if (has_service_id) {
+ /* CN must be ignored if the certificate presents a service identity. */
- php_error_docref(NULL, E_WARNING,
++ php_stream_warn(stream, AuthFailed,
+ "Peer certificate subjectAltName did not match expected name `%s'",
+ peer_name);
+ return FAILURE;
- } else if (php_openssl_matches_common_name(peer, peer_name)) {
+ } else if (php_openssl_matches_common_name(stream, peer, peer_name)) {
return SUCCESS;
} else {
return FAILURE;
diff --cc ext/phar/tar.c
index bc78472afce,ea9b72b5998..d1858511ee6
--- a/ext/phar/tar.c
+++ b/ext/phar/tar.c
@@@ -367,8 -430,8 +437,8 @@@ bail
goto bail;
}
- if (!last_was_longlink && hdr->typeflag == 'L') {
+ if (!last_was_longlink && hdr->typeflag == TAR_LONGNAME) {
- last_was_longlink = 1;
+ last_was_longlink = true;
/* support the ././@LongLink system for storing long filenames */
/* Check for overflow - bug 61065 */
diff --cc ext/soap/php_http.c
index 5df9506102a,a627d1adead..e7325ec65b5
--- a/ext/soap/php_http.c
+++ b/ext/soap/php_http.c
@@@ -1460,8 -1458,8 +1460,9 @@@ static zend_string* get_http_body(php_s
{
zend_string *http_buf = NULL;
char *header;
- int header_close = close, header_chunked = 0, header_length = 0;
+ bool header_close = close, header_chunked = false;
- int header_length = 0, http_buf_size = 0;
++ int header_length = 0;
+ size_t http_buf_size = 0;
if (!close) {
header = get_http_header_value(headers, "Connection:");
@@@ -1490,18 -1484,19 +1491,18 @@@
}
if (header_chunked) {
- char ch, done, headerbuf[8192];
-
- done = FALSE;
+ char ch, headerbuf[8192];
+ bool done = false;
while (!done) {
- int buf_size = 0;
+ unsigned int buf_size = 0;
php_stream_gets(stream, headerbuf, sizeof(headerbuf));
if (sscanf(headerbuf, "%x", &buf_size) > 0 ) {
if (buf_size > 0) {
size_t len_size = 0;
- if (UNEXPECTED(http_buf_size + buf_size + 1 < 0)) {
- if (buf_size >= ZSTR_MAX_LEN - http_buf_size) {
++ if (UNEXPECTED(buf_size >= ZSTR_MAX_LEN - http_buf_size)) {
if (http_buf) {
zend_string_release_ex(http_buf, 0);
}
@@@ -1568,7 -1563,7 +1569,7 @@@
}
} else if (header_length) {
- if (UNEXPECTED(header_length < 0 || header_length >= INT_MAX)) {
- if (header_length < 0 || header_length >= ZSTR_MAX_LEN) {
++ if (UNEXPECTED(header_length < 0 || header_length >= ZSTR_MAX_LEN)) {
return NULL;
}
http_buf = zend_string_alloc(header_length, 0);
diff --cc ext/standard/http_fopen_wrapper.c
index 4a0f95062bc,b7a05e2942d..4157601f222
--- a/ext/standard/http_fopen_wrapper.c
+++ b/ext/standard/http_fopen_wrapper.c
@@@ -1099,11 -1125,9 +1123,11 @@@ finish
header_info.location = NULL;
}
- php_uri_struct_free(resource);
+ /* check for invalid redirection URLs */
- if ((resource = php_uri_parse_to_struct(uri_parser, new_path, strlen(new_path), PHP_URI_COMPONENT_READ_MODE_RAW, true)) == NULL) {
+ php_uri *new_resource = php_uri_parse_to_struct(uri_parser, new_path, strlen(new_path), PHP_URI_COMPONENT_READ_MODE_RAW, true);
+ if (new_resource == NULL) {
- php_stream_wrapper_log_error(wrapper, options, "Invalid redirect URL! %s", new_path);
+ php_stream_wrapper_log_warn(wrapper, context, options, InvalidUrl,
+ "Invalid redirect URL! %s", new_path);
efree(new_path);
goto out;
}