From e5de41cb04d053325a4a01bdfb7a1cbadcff138e Mon Sep 17 00:00:00 2001 From: ndossche Date: Tue, 20 Jan 2026 15:02:06 +0100 Subject: [PATCH 1/5] 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 e514ebeeaba59..d4e1d5f7304cd 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -2280,21 +2280,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; } @@ -2302,7 +2294,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 994078f79e6eb543402db57311835d6b727b8646 Mon Sep 17 00:00:00 2001 From: ndossche Date: Tue, 20 Jan 2026 15:14:13 +0100 Subject: [PATCH 2/5] 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 d4e1d5f7304cd..295b6e9fe8dde 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -2567,7 +2567,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 */ @@ -2585,11 +2588,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 94bd7cfd26f17f10ab42337dae19fce78d526c91 Mon Sep 17 00:00:00 2001 From: ndossche Date: Tue, 20 Jan 2026 15:14:25 +0100 Subject: [PATCH 3/5] 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 295b6e9fe8dde..3dcc897be689d 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -2670,6 +2670,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 */ @@ -2763,6 +2766,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 2ea9de7735865ac80077cb5051227cdb0e111858 Mon Sep 17 00:00:00 2001 From: ndossche Date: Tue, 20 Jan 2026 15:20:11 +0100 Subject: [PATCH 4/5] 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 3dcc897be689d..a6a1b5bc60a31 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -5832,7 +5832,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 */ @@ -5853,7 +5856,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 e75669e4b695e8af33d7fa0d5fb7c915e0481e08 Mon Sep 17 00:00:00 2001 From: ndossche Date: Tue, 20 Jan 2026 15:21:13 +0100 Subject: [PATCH 5/5] 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 a6a1b5bc60a31..913360177139e 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -6444,7 +6444,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 */ @@ -6464,7 +6467,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 */