From f666ce6b62adddc9ecbafb817f7d20bb65ee1f50 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Mon, 1 Sep 2025 15:14:38 +0200 Subject: [PATCH 1/2] Fix GH-18988: Check unchecked error-prone calls in ext/ssl --- ext/openssl/openssl.c | 48 ++++++++++++++++++++++++++++++++----------- ext/openssl/xp_ssl.c | 9 +++++--- 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 8fc830b756d7..ba839a34bd15 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -971,7 +971,9 @@ static int php_openssl_parse_config(struct php_x509_request * req, zval * option if (str != NULL && php_openssl_check_path_ex(str, strlen(str), path, 0, false, false, "oid_file")) { BIO *oid_bio = BIO_new_file(path, PHP_OPENSSL_BIO_MODE_R(PKCS7_BINARY)); if (oid_bio) { - OBJ_create_objects(oid_bio); + if (OBJ_create_objects(oid_bio) == 0) { + php_openssl_store_errors(); + } BIO_free(oid_bio); php_openssl_store_errors(); } @@ -1299,7 +1301,10 @@ PHP_MINIT_FUNCTION(openssl) OSSL_PROVIDER_load(NULL, "legacy"); OSSL_PROVIDER_load(NULL, "default"); #endif - OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL); + if (OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL) != 1) { + php_error_docref(NULL, E_WARNING, "Failed to initialize OpenSSL"); + return FAILURE; + } #endif /* register a resource id number with OpenSSL so that we can map SSL -> stream structures in @@ -2060,22 +2065,34 @@ static int openssl_x509v3_subjectAltName(BIO *bio, X509_EXTENSION *extension) name = sk_GENERAL_NAME_value(names, i); switch (name->type) { case GEN_EMAIL: - BIO_puts(bio, "email:"); + if (BIO_puts(bio, "email:") < 0) { + php_openssl_store_errors(); + } as = name->d.rfc822Name; - BIO_write(bio, ASN1_STRING_get0_data(as), - ASN1_STRING_length(as)); + if (BIO_write(bio, ASN1_STRING_get0_data(as), + ASN1_STRING_length(as)) < 0) { + php_openssl_store_errors(); + } break; case GEN_DNS: - BIO_puts(bio, "DNS:"); + if (BIO_puts(bio, "DNS:") < 0) { + php_openssl_store_errors(); + } as = name->d.dNSName; - BIO_write(bio, ASN1_STRING_get0_data(as), - ASN1_STRING_length(as)); + if (BIO_write(bio, ASN1_STRING_get0_data(as), + ASN1_STRING_length(as)) < 0) { + php_openssl_store_errors(); + } break; case GEN_URI: - BIO_puts(bio, "URI:"); + if (BIO_puts(bio, "URI:") < 0) { + php_openssl_store_errors(); + } as = name->d.uniformResourceIdentifier; - BIO_write(bio, ASN1_STRING_get0_data(as), - ASN1_STRING_length(as)); + if (BIO_write(bio, ASN1_STRING_get0_data(as), + ASN1_STRING_length(as)) < 0) { + php_openssl_store_errors(); + } break; default: /* use builtin print for GEN_OTHERNAME, GEN_X400, @@ -2313,7 +2330,10 @@ static STACK_OF(X509) *php_openssl_load_all_certs_from_file( while (sk_X509_INFO_num(sk)) { xi=sk_X509_INFO_shift(sk); if (xi->x509 != NULL) { - sk_X509_push(stack,xi->x509); + if (sk_X509_push(stack,xi->x509) == 0) { + php_openssl_store_errors(); + X509_free(xi->x509); + } xi->x509=NULL; } X509_INFO_free(xi); @@ -2579,6 +2599,7 @@ static STACK_OF(X509) *php_array_to_X509_sk(zval * zcerts, uint32_t arg_num, con } if (sk_X509_push(sk, cert) <= 0) { + php_openssl_store_errors(); X509_free(cert); goto push_fail_exit; } @@ -2600,6 +2621,7 @@ static STACK_OF(X509) *php_array_to_X509_sk(zval * zcerts, uint32_t arg_num, con } } if (sk_X509_push(sk, cert) <= 0) { + php_openssl_store_errors(); X509_free(cert); goto push_fail_exit; } @@ -5887,6 +5909,7 @@ PHP_FUNCTION(openssl_pkcs7_encrypt) } } if (sk_X509_push(recipcerts, cert) <= 0) { + php_openssl_store_errors(); X509_free(cert); goto clean_exit; } @@ -5911,6 +5934,7 @@ PHP_FUNCTION(openssl_pkcs7_encrypt) } } if (sk_X509_push(recipcerts, cert) <= 0) { + php_openssl_store_errors(); X509_free(cert); goto clean_exit; } diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index 11a6b56bf449..e8eb645317b9 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -1775,7 +1775,9 @@ static zend_result php_openssl_setup_crypto(php_stream *stream, return FAILURE; } if (sslsock->is_client) { - SSL_CTX_set_alpn_protos(sslsock->ctx, alpn, alpn_len); + if (SSL_CTX_set_alpn_protos(sslsock->ctx, alpn, alpn_len) != 0) { + php_openssl_store_errors(); + } } else { sslsock->alpn_ctx.data = (unsigned char *) pestrndup((const char*)alpn, alpn_len, php_stream_is_persistent(stream)); sslsock->alpn_ctx.len = alpn_len; @@ -1849,8 +1851,9 @@ static zend_result php_openssl_setup_crypto(php_stream *stream, php_error_docref(NULL, E_WARNING, "Supplied session stream must be an SSL enabled stream"); } else if (((php_openssl_netstream_data_t*)cparam->inputs.session->abstract)->ssl_handle == NULL) { php_error_docref(NULL, E_WARNING, "Supplied SSL session stream is not initialized"); - } else { - SSL_copy_session_id(sslsock->ssl_handle, ((php_openssl_netstream_data_t*)cparam->inputs.session->abstract)->ssl_handle); + } else if (SSL_copy_session_id(sslsock->ssl_handle, ((php_openssl_netstream_data_t*)cparam->inputs.session->abstract)->ssl_handle) != 1) { + php_openssl_store_errors(); + php_error_docref(NULL, E_WARNING, "Failed to copy SSL session"); } } From 096d7b8563c19d33ec7b54e1f1c3c27f3f76af2b Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Wed, 8 Apr 2026 14:03:16 +0200 Subject: [PATCH 2/2] Address latest comment --- NEWS | 2 ++ ext/openssl/openssl.c | 6 +----- ext/openssl/xp_ssl.c | 5 ++--- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/NEWS b/NEWS index fcdfd3973d83..3401ff0b755e 100644 --- a/NEWS +++ b/NEWS @@ -28,6 +28,8 @@ PHP NEWS - OpenSSL: . Fix a bunch of memory leaks and crashes on edge cases. (ndossche) + . Fixed bug GH-18988 (Check various unchecked error-prone OpenSSL function + return values). (alexandre-daubois) - SPL: . Fixed bug GH-21499 (RecursiveArrayIterator getChildren UAF after parent diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index ba839a34bd15..2c0fc972857a 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -1303,7 +1303,6 @@ PHP_MINIT_FUNCTION(openssl) #endif if (OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL) != 1) { php_error_docref(NULL, E_WARNING, "Failed to initialize OpenSSL"); - return FAILURE; } #endif @@ -2330,10 +2329,7 @@ static STACK_OF(X509) *php_openssl_load_all_certs_from_file( while (sk_X509_INFO_num(sk)) { xi=sk_X509_INFO_shift(sk); if (xi->x509 != NULL) { - if (sk_X509_push(stack,xi->x509) == 0) { - php_openssl_store_errors(); - X509_free(xi->x509); - } + sk_X509_push(stack,xi->x509); xi->x509=NULL; } X509_INFO_free(xi); diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index e8eb645317b9..f5fe1351f91c 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -1851,9 +1851,8 @@ static zend_result php_openssl_setup_crypto(php_stream *stream, php_error_docref(NULL, E_WARNING, "Supplied session stream must be an SSL enabled stream"); } else if (((php_openssl_netstream_data_t*)cparam->inputs.session->abstract)->ssl_handle == NULL) { php_error_docref(NULL, E_WARNING, "Supplied SSL session stream is not initialized"); - } else if (SSL_copy_session_id(sslsock->ssl_handle, ((php_openssl_netstream_data_t*)cparam->inputs.session->abstract)->ssl_handle) != 1) { - php_openssl_store_errors(); - php_error_docref(NULL, E_WARNING, "Failed to copy SSL session"); + } else { + SSL_copy_session_id(sslsock->ssl_handle, ((php_openssl_netstream_data_t*)cparam->inputs.session->abstract)->ssl_handle); } }