Commit 19255f4b784 for php.net

commit 19255f4b784cedf6dd4bb21e97def348d335dd69
Author: Ilija Tovilo <ilija.tovilo@me.com>
Date:   Sat May 2 01:49:34 2026 +0200

    Backport compatibility changes for OpenSSL 4.0

    This backports:

    - 266f85f4e89957a02142f5fc9baea723d57bd90b
    - ff1bb13315740a80c8072acb91d82ee3aed86c9d

diff --git a/NEWS b/NEWS
index aa91603d872..c9b334b1645 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,9 @@ PHP                                                                        NEWS
 - Curl:
   . Add support for brotli and zstd on Windows. (Shivam Mathur)

+- OpenSSL:
+  . Fix compatibility issues with OpenSSL 4.0. (jordikroon, Remi)
+
 18 Dec 2025, PHP 8.2.30

 - Curl:
diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c
index 9e703f75863..1d467f5b50a 100644
--- a/ext/openssl/openssl.c
+++ b/ext/openssl/openssl.c
@@ -469,9 +469,9 @@ void php_openssl_store_errors()
 	errors = OPENSSL_G(errors);

 	do {
-		errors->top = (errors->top + 1) % ERR_NUM_ERRORS;
+		errors->top = (errors->top + 1) % PHP_OPENSSL_ERR_BUFFER_SIZE;
 		if (errors->top == errors->bottom) {
-			errors->bottom = (errors->bottom + 1) % ERR_NUM_ERRORS;
+			errors->bottom = (errors->bottom + 1) % PHP_OPENSSL_ERR_BUFFER_SIZE;
 		}
 		errors->buffer[errors->top] = error_code;
 	} while ((error_code = ERR_get_error()));
@@ -685,7 +685,7 @@ static void php_openssl_add_assoc_name_entry(zval * val, char * key, X509_NAME *

 static void php_openssl_add_assoc_asn1_string(zval * val, char * key, ASN1_STRING * str) /* {{{ */
 {
-	add_assoc_stringl(val, key, (char *)str->data, str->length);
+	add_assoc_stringl(val, key, (const char *)ASN1_STRING_get0_data(str), ASN1_STRING_length(str));
 }
 /* }}} */

@@ -718,12 +718,12 @@ static time_t php_openssl_asn1_time_to_time_t(ASN1_UTCTIME * timestr) /* {{{ */
 	}

 	if (timestr_len < 13 && timestr_len != 11) {
-		php_error_docref(NULL, E_WARNING, "Unable to parse time string %s correctly", timestr->data);
+		php_error_docref(NULL, E_WARNING, "Unable to parse time string %s correctly", ASN1_STRING_get0_data(timestr));
 		return (time_t)-1;
 	}

 	if (ASN1_STRING_type(timestr) == V_ASN1_GENERALIZEDTIME && timestr_len < 15) {
-		php_error_docref(NULL, E_WARNING, "Unable to parse time string %s correctly", timestr->data);
+		php_error_docref(NULL, E_WARNING, "Unable to parse time string %s correctly", ASN1_STRING_get0_data(timestr));
 		return (time_t)-1;
 	}

@@ -1982,8 +1982,8 @@ static int openssl_x509v3_subjectAltName(BIO *bio, X509_EXTENSION *extension)
 	}

 	extension_data = X509_EXTENSION_get_data(extension);
-	p = extension_data->data;
-	length = extension_data->length;
+	p = ASN1_STRING_get0_data(extension_data);
+	length = ASN1_STRING_length(extension_data);
 	if (method->it) {
 		names = (GENERAL_NAMES*) (ASN1_item_d2i(NULL, &p, length,
 			ASN1_ITEM_ptr(method->it)));
@@ -6709,7 +6709,7 @@ PHP_FUNCTION(openssl_error_string)
 		RETURN_FALSE;
 	}

-	OPENSSL_G(errors)->bottom = (OPENSSL_G(errors)->bottom + 1) % ERR_NUM_ERRORS;
+	OPENSSL_G(errors)->bottom = (OPENSSL_G(errors)->bottom + 1) % PHP_OPENSSL_ERR_BUFFER_SIZE;
 	val = OPENSSL_G(errors)->buffer[OPENSSL_G(errors)->bottom];

 	if (val) {
diff --git a/ext/openssl/php_openssl.h b/ext/openssl/php_openssl.h
index 5cfadbedc98..fd7f818d30b 100644
--- a/ext/openssl/php_openssl.h
+++ b/ext/openssl/php_openssl.h
@@ -44,6 +44,8 @@ extern zend_module_entry openssl_module_entry;
 #endif
 #endif

+#define PHP_OPENSSL_ERR_BUFFER_SIZE 16
+
 #define OPENSSL_RAW_DATA 1
 #define OPENSSL_ZERO_PADDING 2
 #define OPENSSL_DONT_ZERO_PAD_KEY 4
@@ -73,7 +75,7 @@ extern zend_module_entry openssl_module_entry;
 #endif

 struct php_openssl_errors {
-	int buffer[ERR_NUM_ERRORS];
+	int buffer[PHP_OPENSSL_ERR_BUFFER_SIZE];
 	int top;
 	int bottom;
 };
diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c
index a0db38c20bc..46b4de67ee7 100644
--- a/ext/openssl/xp_ssl.c
+++ b/ext/openssl/xp_ssl.c
@@ -497,12 +497,12 @@ static bool php_openssl_matches_san_list(X509 *peer, const char *subject_name) /
 			}
 			OPENSSL_free(cert_name);
 		} else if (san->type == GEN_IPADD) {
-			if (san->d.iPAddress->length == 4) {
+			if (ASN1_STRING_length(san->d.iPAddress) == 4) {
 				sprintf(ipbuffer, "%d.%d.%d.%d",
-					san->d.iPAddress->data[0],
-					san->d.iPAddress->data[1],
-					san->d.iPAddress->data[2],
-					san->d.iPAddress->data[3]
+					ASN1_STRING_get0_data(san->d.iPAddress)[0],
+					ASN1_STRING_get0_data(san->d.iPAddress)[1],
+					ASN1_STRING_get0_data(san->d.iPAddress)[2],
+					ASN1_STRING_get0_data(san->d.iPAddress)[3]
 				);
 				if (strcasecmp(subject_name, (const char*)ipbuffer) == 0) {
 					sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
@@ -511,9 +511,9 @@ static bool php_openssl_matches_san_list(X509 *peer, const char *subject_name) /
 				}
 			}
 #ifdef HAVE_IPV6_SAN
-			else if (san->d.ip->length == 16 && subject_name_is_ipv6) {
+			else if (ASN1_STRING_length(san->d.ip) == 16 && subject_name_is_ipv6) {
 				ipbuffer[0] = 0;
-				EXPAND_IPV6_ADDRESS(ipbuffer, san->d.iPAddress->data);
+				EXPAND_IPV6_ADDRESS(ipbuffer, ASN1_STRING_get0_data(san->d.iPAddress));
 				if (strcasecmp((const char*)subject_name_ipv6_expanded, (const char*)ipbuffer) == 0) {
 					sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);