From cea48b4781fc4d890e62a6ab7212c9e88d48ffcf Mon Sep 17 00:00:00 2001 From: ndossche <7771979+ndossche@users.noreply.github.com> Date: Sat, 7 Mar 2026 11:38:53 +0100 Subject: [PATCH 01/14] openssl: Propagate PHP_OPENSSL_ASN1_INTEGER_set() failure If this is not propagated, then the function will succeed even though the serial number is not set. --- ext/openssl/openssl.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 460474488224..7bd2748c0aed 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -3373,7 +3373,11 @@ PHP_FUNCTION(openssl_csr_sign) goto cleanup; } } else { - PHP_OPENSSL_ASN1_INTEGER_set(X509_get_serialNumber(new_cert), serial); + if (!PHP_OPENSSL_ASN1_INTEGER_set(X509_get_serialNumber(new_cert), serial)) { + php_openssl_store_errors(); + php_error_docref(NULL, E_WARNING, "Error setting serial number"); + goto cleanup; + } } if (!X509_set_subject_name(new_cert, X509_REQ_get_subject_name(csr))) { From 35e8cb87cb06e0a77b1751e36ba39bec15dc6471 Mon Sep 17 00:00:00 2001 From: Nora Dossche <7771979+ndossche@users.noreply.github.com> Date: Wed, 28 Jan 2026 18:58:47 +0100 Subject: [PATCH 02/14] Fix memory leaks when php_openssl_dh_pub_from_priv() fails Leak report: ``` Direct leak of 24 byte(s) in 1 object(s) allocated from: #0 0x7f97cf4cb340 in calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:77 #1 0x7f97cef66106 in BN_new bn/bn_lib.c:75 #2 0x7f97cef6006c in bn_bin2bn_cbs bn/bn_convert.c:151 #3 0x7f97cef60853 in BN_bin2bn bn/bn_convert.c:206 #4 0x56229112465b in php_openssl_pkey_init_dh_data /work/php-src/ext/openssl/openssl_backend_v1.c:208 #5 0x5622911248be in php_openssl_pkey_init_dh /work/php-src/ext/openssl/openssl_backend_v1.c:246 #6 0x5622910fe1d7 in zif_openssl_pkey_new /work/php-src/ext/openssl/openssl.c:2051 #7 0x562291eb44e5 in zend_test_execute_internal /work/php-src/ext/zend_test/observer.c:306 #8 0x5622921dc85a in ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER /work/php-src/Zend/zend_vm_execute.h:2154 #9 0x56229233cfa5 in execute_ex /work/php-src/Zend/zend_vm_execute.h:116519 #10 0x562292351ec0 in zend_execute /work/php-src/Zend/zend_vm_execute.h:121962 #11 0x5622924b60cc in zend_execute_script /work/php-src/Zend/zend.c:1980 #12 0x562291ee8ecb in php_execute_script_ex /work/php-src/main/main.c:2645 #13 0x562291ee92db in php_execute_script /work/php-src/main/main.c:2685 #14 0x5622924bbc37 in do_cli /work/php-src/sapi/cli/php_cli.c:951 #15 0x5622924be204 in main /work/php-src/sapi/cli/php_cli.c:1362 #16 0x7f97ceb301c9 (/lib/x86_64-linux-gnu/libc.so.6+0x2a1c9) (BuildId: 274eec488d230825a136fa9c4d85370fed7a0a5e) #17 0x7f97ceb3028a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2a28a) (BuildId: 274eec488d230825a136fa9c4d85370fed7a0a5e) #18 0x562291009db4 in _start (/work/php-src/build-dbg-asan/sapi/cli/php+0x609db4) (BuildId: 5cc444a6a9fc1a486ea698e72366c16bd5472605) ... etc ... ``` --- ext/openssl/openssl.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 7bd2748c0aed..b10bd561ff59 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -4275,7 +4275,12 @@ static bool php_openssl_pkey_init_legacy_dh(DH *dh, zval *data, bool *is_private OPENSSL_PKEY_SET_BN(data, p); OPENSSL_PKEY_SET_BN(data, q); OPENSSL_PKEY_SET_BN(data, g); - if (!p || !g || !DH_set0_pqg(dh, p, q, g)) { + if (!p || !q) { + BN_free(p); + return 0; + } + + if (!DH_set0_pqg(dh, p, q, g)) { return 0; } @@ -4288,6 +4293,10 @@ static bool php_openssl_pkey_init_legacy_dh(DH *dh, zval *data, bool *is_private if (priv_key) { pub_key = php_openssl_dh_pub_from_priv(priv_key, g, p); if (pub_key == NULL) { + BN_free(p); + BN_free(q); + BN_free(g); + BN_free(priv_key); return 0; } return DH_set0_key(dh, pub_key, priv_key); From f9519ccbb9975b2afae95a418fae65ad93823dc6 Mon Sep 17 00:00:00 2001 From: ndossche <7771979+ndossche@users.noreply.github.com> Date: Sat, 4 Apr 2026 12:40:44 +0200 Subject: [PATCH 03/14] [ci skip] Silence test warning --- ext/openssl/tests/gh21031.phpt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ext/openssl/tests/gh21031.phpt b/ext/openssl/tests/gh21031.phpt index a35fab927270..55694bf7676e 100644 --- a/ext/openssl/tests/gh21031.phpt +++ b/ext/openssl/tests/gh21031.phpt @@ -65,7 +65,7 @@ $clientCode = <<<'CODE' ], ]); - var_dump(file_get_contents("https://cs.php.net/", false, $clientCtx)); + var_dump(@file_get_contents("https://cs.php.net/", false, $clientCtx)); phpt_notify('proxy'); phpt_notify('server'); @@ -77,6 +77,5 @@ ServerClientTestCase::getInstance()->run($clientCode, [ 'proxy' => $proxyCode, ]); ?> ---EXPECTF-- -Warning: file_get_contents(https://cs.php.net/): Failed to open stream: Cannot connect to HTTPS server through proxy in %s +--EXPECT-- bool(false) From 4cffcbaf4a2cc7fec6838061cd3cd916f20d26c4 Mon Sep 17 00:00:00 2001 From: Nora Dossche <7771979+ndossche@users.noreply.github.com> Date: Wed, 28 Jan 2026 18:27:43 +0100 Subject: [PATCH 04/14] Add missing error check on BN_CTX_new() If this fails, then the big numbers will be allocated outside of the context, leading to leaks. Closes GH-21061. --- ext/openssl/openssl.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index b10bd561ff59..1fa4597393d5 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -4423,6 +4423,9 @@ static bool php_openssl_pkey_init_legacy_ec(EC_KEY *eckey, zval *data, bool *is_ EC_POINT *point_q = NULL; EC_GROUP *group = NULL; BN_CTX *bctx = BN_CTX_new(); + if (!bctx) { + goto clean_exit; + } *is_private = false; From 7eb38cd3f543c2fcc30f3bf4abbac341c0ec67ba Mon Sep 17 00:00:00 2001 From: Nora Dossche <7771979+ndossche@users.noreply.github.com> Date: Wed, 28 Jan 2026 18:37:47 +0100 Subject: [PATCH 05/14] Fix memory leaks when BN_bin2bn() fails This is observable in LibreSSL. The code is creating 3 big numbers, but if one of them failed to create, then DSA_set0_pqg() will have never executed and there are no references left to the created big numbers, leaking them in the process. E.g.: ``` Direct leak of 24 byte(s) in 1 object(s) allocated from: #0 0x7f4edd402340 in calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:77 #1 0x7f4edce9d106 in BN_new bn/bn_lib.c:75 #2 0x7f4edce9706c in bn_bin2bn_cbs bn/bn_convert.c:151 #3 0x7f4edce97853 in BN_bin2bn bn/bn_convert.c:206 #4 0x5556bd923e1d in php_openssl_pkey_init_dsa_data /work/php-src/ext/openssl/openssl_backend_v1.c:142 #5 0x5556bd92428f in php_openssl_pkey_init_dsa /work/php-src/ext/openssl/openssl_backend_v1.c:186 #6 0x5556bd8fe079 in zif_openssl_pkey_new /work/php-src/ext/openssl/openssl.c:2042 #7 0x5556be6b44e5 in zend_test_execute_internal /work/php-src/ext/zend_test/observer.c:306 #8 0x5556be9dc85a in ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER /work/php-src/Zend/zend_vm_execute.h:2154 #9 0x5556beb3cfa5 in execute_ex /work/php-src/Zend/zend_vm_execute.h:116519 #10 0x5556beb51ec0 in zend_execute /work/php-src/Zend/zend_vm_execute.h:121962 #11 0x5556becb60cc in zend_execute_script /work/php-src/Zend/zend.c:1980 #12 0x5556be6e8ecb in php_execute_script_ex /work/php-src/main/main.c:2645 #13 0x5556be6e92db in php_execute_script /work/php-src/main/main.c:2685 #14 0x5556becbbc37 in do_cli /work/php-src/sapi/cli/php_cli.c:951 #15 0x5556becbe204 in main /work/php-src/sapi/cli/php_cli.c:1362 #16 0x7f4edca671c9 (/lib/x86_64-linux-gnu/libc.so.6+0x2a1c9) (BuildId: 274eec488d230825a136fa9c4d85370fed7a0a5e) #17 0x7f4edca6728a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2a28a) (BuildId: 274eec488d230825a136fa9c4d85370fed7a0a5e) #18 0x5556bd809db4 in _start (/work/php-src/build-dbg-asan/sapi/cli/php+0x609db4) (BuildId: 5cc444a6a9fc1a486ea698e72366c16bd5472605) ``` Closes GH-21062. --- ext/openssl/openssl.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 1fa4597393d5..bd8e7a94210d 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -4102,7 +4102,14 @@ static bool php_openssl_pkey_init_legacy_dsa(DSA *dsa, zval *data, bool *is_priv OPENSSL_PKEY_SET_BN(data, p); OPENSSL_PKEY_SET_BN(data, q); OPENSSL_PKEY_SET_BN(data, g); - if (!p || !q || !g || !DSA_set0_pqg(dsa, p, q, g)) { + if (!p || !q || !g) { + BN_free(p); + BN_free(q); + BN_free(g); + return 0; + } + + if (!DSA_set0_pqg(dsa, p, q, g)) { return 0; } From 2467dfb18f4640d5d4f22ed1decf4fc515b93eac Mon Sep 17 00:00:00 2001 From: ndossche Date: Tue, 27 Jan 2026 11:07:42 +0100 Subject: [PATCH 06/14] Fix UB and error propagation when X509_gmtime_adj() fails This causes UB later on when the certificate is passed to another function: ``` /work/php-src/Zend/zend_string.h:191:2: runtime error: null pointer passed as argument 2, which is declared to never be null #0 0x55cfb9407d94 in zend_string_init /work/php-src/Zend/zend_string.h:191 #1 0x55cfb941ceb6 in add_assoc_stringl_ex /work/php-src/Zend/zend_API.c:1986 #2 0x55cfb7f4c16d in add_assoc_stringl /work/php-src/Zend/zend_API.h:579 #3 0x55cfb7f4cccd in php_openssl_add_assoc_asn1_string /work/php-src/ext/openssl/openssl_backend_common.c:113 #4 0x55cfb7f2eb98 in zif_openssl_x509_parse /work/php-src/ext/openssl/openssl.c:1074 #5 0x55cfb9160993 in zend_test_execute_internal /work/php-src/ext/zend_test/observer.c:306 #6 0x55cfb958ee2d in ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER /work/php-src/Zend/zend_vm_execute.h:2154 #7 0x55cfb97854bd in execute_ex /work/php-src/Zend/zend_vm_execute.h:116519 #8 0x55cfb9795c96 in zend_execute /work/php-src/Zend/zend_vm_execute.h:121962 #9 0x55cfb99666c6 in zend_execute_script /work/php-src/Zend/zend.c:1980 #10 0x55cfb919583e in php_execute_script_ex /work/php-src/main/main.c:2645 #11 0x55cfb9195b48 in php_execute_script /work/php-src/main/main.c:2685 #12 0x55cfb996bf48 in do_cli /work/php-src/sapi/cli/php_cli.c:951 #13 0x55cfb996e6a1 in main /work/php-src/sapi/cli/php_cli.c:1362 #14 0x7fb0b68301c9 (/lib/x86_64-linux-gnu/libc.so.6+0x2a1c9) (BuildId: 274eec488d230825a136fa9c4d85370fed7a0a5e) #15 0x7fb0b683028a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2a28a) (BuildId: 274eec488d230825a136fa9c4d85370fed7a0a5e) #16 0x55cfb7e097d4 in _start (/work/php-src/build-dbg-ubsan/sapi/cli/php+0x14097d4) (BuildId: b2b405964cc047ab6da19abaf92a8899a99e4a47) ``` Furthermore, it also simply does not propagate the error to userland. Closes GH-21046. --- ext/openssl/openssl.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index bd8e7a94210d..5ea8574f0235 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -3392,8 +3392,11 @@ PHP_FUNCTION(openssl_csr_sign) php_openssl_store_errors(); goto cleanup; } - X509_gmtime_adj(X509_getm_notBefore(new_cert), 0); - X509_gmtime_adj(X509_getm_notAfter(new_cert), 60*60*24*num_days); + if (!X509_gmtime_adj(X509_getm_notBefore(new_cert), 0) + || !X509_gmtime_adj(X509_getm_notAfter(new_cert), 60*60*24*num_days)) { + php_openssl_store_errors(); + goto cleanup; + } i = X509_set_pubkey(new_cert, key); if (!i) { php_openssl_store_errors(); From f81a9a2f7deb7e5047e89f523704c67d632ed141 Mon Sep 17 00:00:00 2001 From: ndossche Date: Tue, 27 Jan 2026 14:00:05 +0100 Subject: [PATCH 07/14] Add missing error check on SSL_set_ex_data() This can actually fail because internally this function does stack management in internal data structures. Can cause a crash later, e.g.: ``` ==239255==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000008 (pc 0x5652d8f2fe68 bp 0x7ffc99ee8fc0 sp 0x7ffc99ee8ec0 T0) ==239255==The signal is caused by a READ memory access. ==239255==Hint: address points to the zero page. #0 0x5652d8f2fe68 in php_openssl_limit_handshake_reneg /work/php-src/ext/openssl/xp_ssl.c:1080 #1 0x5652d8f306e2 in php_openssl_info_callback /work/php-src/ext/openssl/xp_ssl.c:1137 #2 0x7f45057b84e5 (/lib/x86_64-linux-gnu/libssl.so.3+0x694e5) (BuildId: 5f3b12d47114f9fbdc7765266cd0bb8f1b5ee8fc) #3 0x5652d8f351d9 in php_openssl_enable_crypto /work/php-src/ext/openssl/xp_ssl.c:1850 #4 0x5652d8f39c86 in php_openssl_sockop_set_option /work/php-src/ext/openssl/xp_ssl.c:2516 #5 0x5652d9d4c610 in _php_stream_set_option /work/php-src/main/streams/streams.c:1466 #6 0x5652d9d557c1 in php_stream_xport_crypto_enable /work/php-src/main/streams/transports.c:387 #7 0x5652d8f387be in php_openssl_tcp_sockop_accept /work/php-src/ext/openssl/xp_ssl.c:2279 #8 0x5652d8f39fcd in php_openssl_sockop_set_option /work/php-src/ext/openssl/xp_ssl.c:2551 #9 0x5652d9d4c610 in _php_stream_set_option /work/php-src/main/streams/streams.c:1466 #10 0x5652d9d54d3a in php_stream_xport_accept /work/php-src/main/streams/transports.c:307 #11 0x5652d9b50161 in zif_stream_socket_accept /work/php-src/ext/standard/streamsfuncs.c:298 #12 0x5652d9fdacfb in ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HANDLER /work/php-src/Zend/zend_vm_execute.h:1355 #13 0x5652da140689 in execute_ex /work/php-src/Zend/zend_vm_execute.h:116469 #14 0x5652da1558b0 in zend_execute /work/php-src/Zend/zend_vm_execute.h:121962 #15 0x5652da2ba0ab in zend_execute_script /work/php-src/Zend/zend.c:1980 #16 0x5652d9cec8bb in php_execute_script_ex /work/php-src/main/main.c:2645 #17 0x5652d9cecccb in php_execute_script /work/php-src/main/main.c:2685 #18 0x5652da2bfc16 in do_cli /work/php-src/sapi/cli/php_cli.c:951 #19 0x5652da2c21e3 in main /work/php-src/sapi/cli/php_cli.c:1362 #20 0x7f4504ebc1c9 (/lib/x86_64-linux-gnu/libc.so.6+0x2a1c9) (BuildId: 274eec488d230825a136fa9c4d85370fed7a0a5e) #21 0x7f4504ebc28a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2a28a) (BuildId: 274eec488d230825a136fa9c4d85370fed7a0a5e) #22 0x5652d8e09b34 in _start (/work/php-src/build-dbg-asan/sapi/cli/php+0x609b34) (BuildId: aa149f943514fff0c491e1f199e30fed0e977f7c) ``` Closes GH-21049. --- ext/openssl/xp_ssl.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index 88c75253abaf..64812c28042a 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -1810,7 +1810,8 @@ static zend_result php_openssl_setup_crypto(php_stream *stream, sslsock->ssl_handle = SSL_new(sslsock->ctx); - if (sslsock->ssl_handle == NULL) { + if (sslsock->ssl_handle == NULL + || !SSL_set_ex_data(sslsock->ssl_handle, php_openssl_get_ssl_stream_data_index(), stream)) { php_error_docref(NULL, E_WARNING, "SSL handle creation failure"); SSL_CTX_free(sslsock->ctx); sslsock->ctx = NULL; @@ -1821,8 +1822,6 @@ static zend_result php_openssl_setup_crypto(php_stream *stream, } #endif return FAILURE; - } else { - SSL_set_ex_data(sslsock->ssl_handle, php_openssl_get_ssl_stream_data_index(), stream); } if (!SSL_set_fd(sslsock->ssl_handle, sslsock->s.socket)) { From 4e105e0176b949aaff193959c312ad9ff7cd419a Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Sat, 4 Apr 2026 12:44:01 +0200 Subject: [PATCH 08/14] Fix openssl compile warnings on Solaris MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BIO_reset() needs a (void) cast, analogous to the other locations in this file. /usr/openssl/3/include/openssl/bio.h:555:34: error: value computed is not used [-Werror=unused-value] 555 | # define BIO_reset(b) (int)BIO_ctrl(b,BIO_CTRL_RESET,0,NULL) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /home/runner/work/php-src/php-src/ext/openssl/openssl.c:1565:33: note: in expansion of macro ‘BIO_reset’ 1565 | BIO_reset(bio_out); | ^~~~~~~~~ --- ext/openssl/openssl.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 42341a1f5b76..65da0752b557 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -1562,7 +1562,7 @@ PHP_FUNCTION(openssl_pkcs12_read) add_index_zval(&zextracerts, i, &zextracert); } - BIO_reset(bio_out); + (void)BIO_reset(bio_out); X509_free(aCA); } BIO_free(bio_out); @@ -2844,7 +2844,7 @@ PHP_FUNCTION(openssl_pkcs7_read) ZVAL_STRINGL(&zcert, bio_buf->data, bio_buf->length); add_index_zval(zout, i, &zcert); } - BIO_reset(bio_out); + (void)BIO_reset(bio_out); } BIO_free(bio_out); } @@ -2863,7 +2863,7 @@ PHP_FUNCTION(openssl_pkcs7_read) ZVAL_STRINGL(&zcert, bio_buf->data, bio_buf->length); add_index_zval(zout, i, &zcert); } - BIO_reset(bio_out); + (void)BIO_reset(bio_out); } BIO_free(bio_out); } @@ -3520,7 +3520,7 @@ PHP_FUNCTION(openssl_cms_read) ZVAL_STRINGL(&zcert, bio_buf->data, bio_buf->length); add_index_zval(zout, i, &zcert); } - BIO_reset(bio_out); + (void)BIO_reset(bio_out); } BIO_free(bio_out); } @@ -3540,7 +3540,7 @@ PHP_FUNCTION(openssl_cms_read) ZVAL_STRINGL(&zcert, bio_buf->data, bio_buf->length); add_index_zval(zout, i, &zcert); } - BIO_reset(bio_out); + (void)BIO_reset(bio_out); } BIO_free(bio_out); } From 883014debb631c6e389df0057e5dc35a8791cc78 Mon Sep 17 00:00:00 2001 From: ndossche <7771979+ndossche@users.noreply.github.com> Date: Sat, 4 Apr 2026 12:54:31 +0200 Subject: [PATCH 09/14] Fix const-generic warning in xp_ssl.c ``` ext/openssl/xp_ssl.c:423:24: warning: assignment discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers] 423 | if (!(wildcard = strchr(certname, '*')) || memchr(certname, '.', wildcard - certname)) { | ^ ``` Since these typically turn into errors with -Werror, fix the build already. --- ext/openssl/xp_ssl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index 64812c28042a..11a6b56bf449 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -413,7 +413,7 @@ static bool php_openssl_x509_fingerprint_match(X509 *peer, zval *val) static bool php_openssl_matches_wildcard_name(const char *subjectname, const char *certname) /* {{{ */ { - char *wildcard = NULL; + const char *wildcard = NULL; ptrdiff_t prefix_len; size_t suffix_len, subject_len; From 79b1ca2064c0492c4fbeeff1cd65b2c2345c32da Mon Sep 17 00:00:00 2001 From: Nora Dossche <7771979+ndossche@users.noreply.github.com> Date: Sun, 25 Jan 2026 12:36:13 +0100 Subject: [PATCH 10/14] Fix memory leaks and missing error propagation when php_openssl_csr_make() fails to set a version The leaks appears to be at least somewhat dependent on the OpenSSL version, but it is reproducible on an Ubuntu 24.04 container. Easiest way to manually trigger the bug is to make the second call fail when executing bug69215.phpt. Closes GH-21032. --- NEWS | 3 +++ ext/openssl/openssl.c | 12 ++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index 1e72166bf934..6a926e6118bb 100644 --- a/NEWS +++ b/NEWS @@ -20,6 +20,9 @@ PHP NEWS zend_jit_use_reg). (Arnaud) . Fixed bug GH-21593 (Borked function JIT JMPNZ smart branch). (ilutov) +- OpenSSL: + . Fix a bunch of memory leaks and crashes on edge cases. (ndossche) + - SPL: . Fixed bug GH-21499 (RecursiveArrayIterator getChildren UAF after parent free). (Girgias) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 5ea8574f0235..b3e1201854a5 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -2968,7 +2968,9 @@ static zend_result php_openssl_csr_make(struct php_x509_request * req, X509_REQ } } /* setup the version number: version 1 */ - if (X509_REQ_set_version(csr, 0L)) { + static int counter = 0; + counter++; + if (counter!=2&&X509_REQ_set_version(csr, 0L)) { int i, nid; char *type; CONF_VALUE *v; @@ -3090,13 +3092,15 @@ static zend_result php_openssl_csr_make(struct php_x509_request * req, X509_REQ } } } + + if (!X509_REQ_set_pubkey(csr, req->priv_key)) { + php_openssl_store_errors(); + } } else { php_openssl_store_errors(); + return FAILURE; } - if (!X509_REQ_set_pubkey(csr, req->priv_key)) { - php_openssl_store_errors(); - } return SUCCESS; } From c5fb035c6701400cc284e7b6ebf66fa678133848 Mon Sep 17 00:00:00 2001 From: ndossche <7771979+ndossche@users.noreply.github.com> Date: Sat, 4 Apr 2026 13:24:24 +0200 Subject: [PATCH 11/14] openssl: Fix merge Diffs in commit messages are applied by git, what a stupid design. So this can introduce accidental changes like here where the original reproducer got applied. --- ext/openssl/openssl.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index b3e1201854a5..8fc830b756d7 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -2968,9 +2968,7 @@ static zend_result php_openssl_csr_make(struct php_x509_request * req, X509_REQ } } /* setup the version number: version 1 */ - static int counter = 0; - counter++; - if (counter!=2&&X509_REQ_set_version(csr, 0L)) { + if (X509_REQ_set_version(csr, 0L)) { int i, nid; char *type; CONF_VALUE *v; From 7cc45e0e41c96d7966d8431a86a2220b77dba438 Mon Sep 17 00:00:00 2001 From: Peter Kokot Date: Sat, 4 Apr 2026 14:15:50 +0200 Subject: [PATCH 12/14] Windows: Allow OpenSSL Argon2 password hashing on ZTS (#21194) This is a follow-up of ce6e7a278694bb065f8adcd11beb42c353787f18 (GH-19236). --- ext/openssl/config.w32 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ext/openssl/config.w32 b/ext/openssl/config.w32 index 6fd0e928422c..4b7f4b8b8565 100644 --- a/ext/openssl/config.w32 +++ b/ext/openssl/config.w32 @@ -16,9 +16,7 @@ if (PHP_OPENSSL != "no") { AC_DEFINE("LOAD_OPENSSL_LEGACY_PROVIDER", 1, "Define to 1 to load the OpenSSL legacy algorithm provider in addition to the default provider."); } if (PHP_OPENSSL_ARGON2 != "no") { - if (PHP_ZTS != "no") { - WARNING("OpenSSL argon2 hashing not supported in ZTS mode for now"); - } else if (!GREP_HEADER("openssl/thread.h", "OSSL_set_max_threads", PHP_PHP_BUILD + "\\include")) { + if (!GREP_HEADER("openssl/thread.h", "OSSL_set_max_threads", PHP_PHP_BUILD + "\\include")) { WARNING("OpenSSL argon2 hashing requires OpenSSL >= 3.2"); } else { AC_DEFINE("HAVE_OPENSSL_ARGON2", 1, "Define to 1 to enable OpenSSL argon2 password hashing."); From f90757102cda25c1167a0df7eab8402b65b24e73 Mon Sep 17 00:00:00 2001 From: Peter Kokot Date: Sat, 4 Apr 2026 14:23:09 +0200 Subject: [PATCH 13/14] ext/intl: Add spoofchecker files unconditionally on Windows (#21621) This check was once relevant for ICU versions < 4.2 which lack the unicode/uspoof.h header file. See: 6f6d60821e25c1b978c8b3f8e3e3d8128e277f06 --- ext/intl/config.w32 | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/ext/intl/config.w32 b/ext/intl/config.w32 index da8285b50d0c..9e2f695532d3 100644 --- a/ext/intl/config.w32 +++ b/ext/intl/config.w32 @@ -92,13 +92,11 @@ if (PHP_INTL != "no") { resourcebundle_iterator.cpp", "intl"); - if (CHECK_HEADER("unicode/uspoof.h", "CFLAGS_INTL")) { - ADD_SOURCES(configure_module_dirname + "/spoofchecker", "\ - spoofchecker_class.cpp \ - spoofchecker_create.cpp \ - spoofchecker_main.cpp", - "intl"); - } + ADD_SOURCES(configure_module_dirname + "/spoofchecker", "\ + spoofchecker_class.cpp \ + spoofchecker_create.cpp \ + spoofchecker_main.cpp", + "intl"); ADD_SOURCES(configure_module_dirname + "/transliterator", "\ transliterator_class.cpp \ From 2b7489437b1b085bab57c62a64153de0a1431d6d Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Fri, 3 Apr 2026 21:54:57 +0200 Subject: [PATCH 14/14] More gcov improvements - Suppress debug assertions - Exclude ext/opcache/jit/ir Closes GH-21629 --- Zend/zend_API.h | 8 +++++++- build/Makefile.gcov | 11 ++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/Zend/zend_API.h b/Zend/zend_API.h index e56ded4e8f1b..1ec5813678a4 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -1055,7 +1055,13 @@ static zend_always_inline bool zend_char_has_nul_byte(const char *s, size_t know #define RETURN_ZVAL(zv, copy, dtor) do { RETVAL_ZVAL(zv, copy, dtor); return; } while (0) #define RETURN_FALSE do { RETVAL_FALSE; return; } while (0) #define RETURN_TRUE do { RETVAL_TRUE; return; } while (0) -#define RETURN_THROWS() do { ZEND_ASSERT(EG(exception)); (void) return_value; return; } while (0) + +#ifndef HAVE_GCOV +# define RETURN_THROWS() do { ZEND_ASSERT(EG(exception)); (void) return_value; return; } while (0) +#else +/* Drop ZEND_ASSERT() to avoid untested branch warning in gcov. */ +# define RETURN_THROWS() do { (void) return_value; return; } while (0) +#endif #define HASH_OF(p) (Z_TYPE_P(p)==IS_ARRAY ? Z_ARRVAL_P(p) : ((Z_TYPE_P(p)==IS_OBJECT ? Z_OBJ_HT_P(p)->get_properties(Z_OBJ_P(p)) : NULL))) diff --git a/build/Makefile.gcov b/build/Makefile.gcov index d389cecdd192..d0dde7c120c8 100644 --- a/build/Makefile.gcov +++ b/build/Makefile.gcov @@ -24,10 +24,15 @@ GCOVR_EXCLUDES = \ 'ext/hash/sha3/.*' \ 'ext/lexbor/lexbor/.*' \ 'ext/mbstring/libmbfl/.*' \ + 'ext/opcache/jit/ir/.*' \ 'ext/pcre/pcre2lib/.*' \ 'ext/uri/uriparser/.*' -GCOVR_EXCLUDE_LINES_BY_PATTERN = '.*\b(ZEND_PARSE_PARAMETERS_(START|END|NONE)|Z_PARAM_).*' +GCOVR_EXCLUDE_LINES_BY_PATTERNS = \ + '.*\b(ZEND_PARSE_PARAMETERS_(START|END|NONE)|Z_PARAM_).*' \ + '\s*EMPTY_SWITCH_DEFAULT_CASE\(\)(;)?\s*' \ + '\s*ZEND_ASSERT\(.*\);\s*' \ + '\s*ZEND_UNREACHABLE\(\);\s*' lcov: lcov-html @@ -53,14 +58,14 @@ gcovr-html: @rm -rf gcovr_html/ @mkdir gcovr_html gcovr -sr . -o gcovr_html/index.html --html --html-details \ - --exclude-lines-by-pattern $(GCOVR_EXCLUDE_LINES_BY_PATTERN) \ + $(foreach pattern, $(GCOVR_EXCLUDE_LINES_BY_PATTERNS), --exclude-lines-by-pattern $(pattern)) \ $(foreach lib, $(GCOVR_EXCLUDES), -e $(lib)) gcovr-xml: @echo "Generating gcovr XML" @rm -f gcovr.xml gcovr -sr . -o gcovr.xml --xml \ - --exclude-lines-by-pattern $(GCOVR_EXCLUDE_LINES_BY_PATTERN) \ + $(foreach pattern, $(GCOVR_EXCLUDE_LINES_BY_PATTERNS), --exclude-lines-by-pattern $(pattern)) \ $(foreach lib, $(GCOVR_EXCLUDES), -e $(lib)) .PHONY: gcovr-html lcov-html php_lcov.info