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;
  			}