From 4b9e80eae9485e2eacb894566ab18dae6ce70ec5 Mon Sep 17 00:00:00 2001 From: ndossche Date: Tue, 20 Jan 2026 15:02:06 +0100 Subject: [PATCH 1/6] Fix memory leak in php_openssl_load_all_certs_from_file() when push fails --- ext/openssl/openssl.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 12383ac8c2c..62ffa7f9200 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -2291,21 +2291,13 @@ static STACK_OF(X509) *php_openssl_load_all_certs_from_file( X509_INFO *xi; char cert_path[MAXPATHLEN]; - if(!(stack = sk_X509_new_null())) { - php_openssl_store_errors(); - php_error_docref(NULL, E_ERROR, "Memory allocation failure"); - goto end; - } - if (!php_openssl_check_path(cert_file, cert_file_len, cert_path, arg_num)) { - sk_X509_free(stack); goto end; } if (!(in = BIO_new_file(cert_path, PHP_OPENSSL_BIO_MODE_R(PKCS7_BINARY)))) { php_openssl_store_errors(); php_error_docref(NULL, E_WARNING, "Error opening the file, %s", cert_path); - sk_X509_free(stack); goto end; } @@ -2313,7 +2305,11 @@ static STACK_OF(X509) *php_openssl_load_all_certs_from_file( if (!(sk = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL))) { php_openssl_store_errors(); php_error_docref(NULL, E_WARNING, "Error reading the file, %s", cert_path); - sk_X509_free(stack); + goto end; + } + + if(!(stack = sk_X509_new_reserve(NULL, sk_X509_INFO_num(sk)))) { + php_openssl_store_errors(); goto end; } From 01d598aea34825f67089801ea61234de5d499aaf Mon Sep 17 00:00:00 2001 From: ndossche Date: Tue, 20 Jan 2026 15:14:13 +0100 Subject: [PATCH 2/6] Fix memory leaks in php_array_to_X509_sk() when push fails --- ext/openssl/openssl.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 62ffa7f9200..39bfe912fc4 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -2581,7 +2581,10 @@ static STACK_OF(X509) *php_array_to_X509_sk(zval * zcerts, uint32_t arg_num, con } } - sk_X509_push(sk, cert); + if (sk_X509_push(sk, cert) <= 0) { + X509_free(cert); + goto push_fail_exit; + } } ZEND_HASH_FOREACH_END(); } else { /* a single certificate */ @@ -2599,11 +2602,20 @@ static STACK_OF(X509) *php_array_to_X509_sk(zval * zcerts, uint32_t arg_num, con goto clean_exit; } } - sk_X509_push(sk, cert); + if (sk_X509_push(sk, cert) <= 0) { + X509_free(cert); + goto push_fail_exit; + } } clean_exit: return sk; + +push_fail_exit: + php_openssl_store_errors(); + php_sk_X509_free(sk); + sk = NULL; + goto clean_exit; } /* }}} */ From ef54becb3e11a6fb05cdcd79c2a712f87f90d4dc Mon Sep 17 00:00:00 2001 From: ndossche Date: Tue, 20 Jan 2026 15:14:25 +0100 Subject: [PATCH 3/6] Fix missing error propagation when php_array_to_X509_sk() fails Execution shouldn't continue if this fails because it can give the wrong results. --- ext/openssl/openssl.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 39bfe912fc4..65e4b7b56d3 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -2684,6 +2684,9 @@ PHP_FUNCTION(openssl_pkcs12_export_to_file) if (args && (item = zend_hash_str_find(Z_ARRVAL_P(args), "extracerts", sizeof("extracerts")-1)) != NULL) { ca = php_array_to_X509_sk(item, 5, "extracerts"); + if (!ca) { + goto cleanup; + } } /* end parse extra config */ @@ -2777,6 +2780,9 @@ PHP_FUNCTION(openssl_pkcs12_export) if (args && (item = zend_hash_str_find(Z_ARRVAL_P(args), "extracerts", sizeof("extracerts")-1)) != NULL) { ca = php_array_to_X509_sk(item, 5, "extracerts"); + if (!ca) { + goto cleanup; + } } /* end parse extra config */ From 556ec779512b3851970fedf0a6769bddf719305b Mon Sep 17 00:00:00 2001 From: ndossche Date: Tue, 20 Jan 2026 15:20:11 +0100 Subject: [PATCH 4/6] Fix memory leaks in openssl_pkcs7_encrypt() when push fails --- ext/openssl/openssl.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 65e4b7b56d3..c99ce2931fd 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -5849,7 +5849,10 @@ PHP_FUNCTION(openssl_pkcs7_encrypt) goto clean_exit; } } - sk_X509_push(recipcerts, cert); + if (sk_X509_push(recipcerts, cert) <= 0) { + X509_free(cert); + goto clean_exit; + } } ZEND_HASH_FOREACH_END(); } else { /* a single certificate */ @@ -5870,7 +5873,10 @@ PHP_FUNCTION(openssl_pkcs7_encrypt) goto clean_exit; } } - sk_X509_push(recipcerts, cert); + if (sk_X509_push(recipcerts, cert) <= 0) { + X509_free(cert); + goto clean_exit; + } } /* sanity check the cipher */ From f6887f04f62301fa91b7da945491bd4c859e6802 Mon Sep 17 00:00:00 2001 From: ndossche Date: Tue, 20 Jan 2026 15:21:13 +0100 Subject: [PATCH 5/6] Fix memory leaks in openssl_cms_encrypt() when push fails --- ext/openssl/openssl.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index c99ce2931fd..2f2aae1e733 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -6464,7 +6464,10 @@ PHP_FUNCTION(openssl_cms_encrypt) goto clean_exit; } } - sk_X509_push(recipcerts, cert); + if (sk_X509_push(recipcerts, cert) <= 0) { + php_openssl_store_errors(); + goto clean_exit; + } } ZEND_HASH_FOREACH_END(); } else { /* a single certificate */ @@ -6484,7 +6487,10 @@ PHP_FUNCTION(openssl_cms_encrypt) goto clean_exit; } } - sk_X509_push(recipcerts, cert); + if (sk_X509_push(recipcerts, cert) <= 0) { + php_openssl_store_errors(); + goto clean_exit; + } } /* sanity check the cipher */ From b911748fefcb67598c4a0ccef185499bae821020 Mon Sep 17 00:00:00 2001 From: ndossche <7771979+ndossche@users.noreply.github.com> Date: Tue, 17 Feb 2026 21:40:24 +0100 Subject: [PATCH 6/6] Update NEWS for OpenSSL changes --- NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS b/NEWS index 3ddd141ab9b..3f9e5c1354d 100644 --- a/NEWS +++ b/NEWS @@ -37,6 +37,9 @@ PHP NEWS . Fixed bug GH-21227 (Borked SCCP of array containing partial object). (ilutov) +- OpenSSL: + . Fix a bunch of leaks and error propagation. (ndossche) + - PDO_PGSQL: . Fixed bug GH-21055 (connection attribute status typo for GSS negotiation). (lsaos)