Commit 880a6fcf8e7 for php.net

commit 880a6fcf8e7ea37b5fd852110ed63c1c128e4bc8
Author: Niels Dossche <7771979+ndossche@users.noreply.github.com>
Date:   Sun Jan 25 23:24:47 2026 +0100

    Fix memory leak regression in openssl_pbkdf2()

    We're fetching the digest using the new method, but if an alias is used,
    the method is fetched via EVP_MD_fetch() which requires lifetime
    management. This is observable when using "sha-256" instead of "sha256"
    as an algorithm name. This is a regression in comparison to PHP 8.4.

    Closes GH-21039.

diff --git a/NEWS b/NEWS
index eb098f11c04..09e58c4d9dc 100644
--- a/NEWS
+++ b/NEWS
@@ -19,6 +19,9 @@ PHP                                                                        NEWS
     zend_jit_use_reg). (Arnaud)
   . Fixed bug GH-21593 (Borked function JIT JMPNZ smart branch). (ilutov)

+- OpenSSL:
+  . Fix memory leak regression in openssl_pbkdf2(). (ndossche)
+
 - DOM:
   . Fixed bug GH-21566 (Dom\XMLDocument::C14N() emits duplicate xmlns
     declarations after setAttributeNS()). (David Carlier)
diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c
index a3968296317..9986fd60204 100644
--- a/ext/openssl/openssl.c
+++ b/ext/openssl/openssl.c
@@ -2450,12 +2450,14 @@ PHP_FUNCTION(openssl_pbkdf2)

 	if (PKCS5_PBKDF2_HMAC(password, (int)password_len, (unsigned char *)salt, (int)salt_len, (int)iterations, digest, (int)key_length, (unsigned char*)ZSTR_VAL(out_buffer)) == 1) {
 		ZSTR_VAL(out_buffer)[key_length] = 0;
-		RETURN_NEW_STR(out_buffer);
+		RETVAL_NEW_STR(out_buffer);
 	} else {
 		php_openssl_store_errors();
 		zend_string_release_ex(out_buffer, 0);
-		RETURN_FALSE;
+		RETVAL_FALSE;
 	}
+
+	php_openssl_release_evp_md(digest);
 }
 /* }}} */

diff --git a/ext/openssl/tests/openssl_pbkdf2_basic.phpt b/ext/openssl/tests/openssl_pbkdf2_basic.phpt
index fd253ac78bb..ba79f9415ba 100644
--- a/ext/openssl/tests/openssl_pbkdf2_basic.phpt
+++ b/ext/openssl/tests/openssl_pbkdf2_basic.phpt
@@ -19,6 +19,8 @@
 var_dump(bin2hex(openssl_pbkdf2('passwordPASSWORDpassword', 'saltSALTsaltSALTsaltSALTsaltSALTsalt', 25, 4096)));
 var_dump(bin2hex(openssl_pbkdf2("pass\0word", "sa\0lt", 16, 4096)));

+var_dump(bin2hex(openssl_pbkdf2("password", "salt", 16, 4096, "sha-256")));
+
 ?>
 --EXPECT--
 string(40) "0c60c80f961f0e71f3a9b524af6012062fe037a6"
@@ -26,3 +28,4 @@
 string(40) "4b007901b765489abead49d926f721d065a429c1"
 string(50) "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038"
 string(32) "56fa6aa75548099dcc37d7f03425e0c3"
+string(32) "c5e478d59288c841aa530db6845c4c8d"