Commit 02a7c49564b for php.net

commit 02a7c49564bebb0af476db7a37ad14b658119691
Author: Niels Dossche <7771979+ndossche@users.noreply.github.com>
Date:   Sat Dec 6 14:09:01 2025 +0100

    ldap: Fix memory leak in ldap_set_options()

    Closes GH-20659.

diff --git a/NEWS b/NEWS
index b4a15b3ddd8..be1c55a7c8e 100644
--- a/NEWS
+++ b/NEWS
@@ -13,6 +13,8 @@ PHP                                                                        NEWS
 - GD:
   . Fixed bug GH-20622 (imagestring/imagestringup overflow). (David Carlier)

+- LDAP:
+  . Fix memory leak in ldap_set_options(). (ndossche)

 18 Dec 2025, PHP 8.3.29

diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c
index 0b0a0c21df4..303ba055458 100644
--- a/ext/ldap/ldap.c
+++ b/ext/ldap/ldap.c
@@ -664,14 +664,15 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
 				goto failure;
 			}

+			zend_string *context_str = NULL;
 			if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "context", sizeof("context") - 1)) != NULL) {
-				tmpstring = zval_get_string(tmp);
+				context_str = zval_get_string(tmp);
 				if (EG(exception)) {
 					rc = -1;
 					goto failure;
 				}
-				context.bv_val = ZSTR_VAL(tmpstring);
-				context.bv_len = ZSTR_LEN(tmpstring);
+				context.bv_val = ZSTR_VAL(context_str);
+				context.bv_len = ZSTR_LEN(context_str);
 				vlvInfo.ldvlv_context = &context;
 			} else {
 				vlvInfo.ldvlv_context = NULL;
@@ -683,6 +684,9 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
 			if (rc != LDAP_SUCCESS) {
 				php_error_docref(NULL, E_WARNING, "Failed to create VLV control value: %s (%d)", ldap_err2string(rc), rc);
 			}
+			if (context_str) {
+				zend_string_release_ex(context_str, false);
+			}
 		} else {
 			zend_type_error("%s(): Control OID %s cannot be of type array", get_active_function_name(), ZSTR_VAL(control_oid));
 			rc = -1;
diff --git a/ext/ldap/tests/ldap_set_option_leak_attrvalue_context.phpt b/ext/ldap/tests/ldap_set_option_leak_attrvalue_context.phpt
new file mode 100644
index 00000000000..5829ad24faf
--- /dev/null
+++ b/ext/ldap/tests/ldap_set_option_leak_attrvalue_context.phpt
@@ -0,0 +1,34 @@
+--TEST--
+ldap_set_option() - Leaks attrvalue and context
+--EXTENSIONS--
+ldap
+--FILE--
+<?php
+require "connect.inc";
+
+$link = ldap_connect($uri);
+
+$attrvalue = str_repeat("attrvalue", random_int(1, 1));
+$context = str_repeat("context", random_int(1, 1));
+
+$controls = [
+    ["oid" => "2.16.840.1.113730.3.4.9", "value" => ["attrvalue" => $attrvalue, "context" => $context, "before" => 0, "after" => 0]],
+];
+
+ldap_set_option($link, LDAP_OPT_CLIENT_CONTROLS, $controls);
+ldap_get_option($link, LDAP_OPT_CLIENT_CONTROLS, $controls_out);
+
+var_dump($controls_out);
+?>
+--EXPECTF--
+array(1) {
+  ["2.16.840.1.113730.3.4.9"]=>
+  array(3) {
+    ["oid"]=>
+    string(23) "2.16.840.1.113730.3.4.9"
+    ["iscritical"]=>
+    bool(false)
+    ["value"]=>

+  }
+}