From 6499b56aa6267473ab49ae2fa05bf065525b9e94 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 20 Feb 2026 13:05:39 +0000 Subject: [PATCH 1/3] Fix GH-21262: ldap_modify() too strict controls argument validation. make it impossible to unset an attribute. --- ext/ldap/ldap.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index 86ac58c5273c0..805c1059f9d49 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -2339,9 +2339,14 @@ static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper, bool ext) SEPARATE_ARRAY(attribute_values); uint32_t num_values = zend_hash_num_elements(Z_ARRVAL_P(attribute_values)); if (num_values == 0) { - zend_argument_value_error(3, "attribute \"%s\" must be a non-empty list of attribute values", ZSTR_VAL(attribute)); - RETVAL_FALSE; - goto cleanup; + if (UNEXPECTED(is_full_add)) { + zend_argument_value_error(3, "attribute \"%s\" must be a non-empty list of attribute values", ZSTR_VAL(attribute)); + RETVAL_FALSE; + goto cleanup; + } + /* When we modify, we means we delete the attribute */ + attribute_index ++; + continue; } if (!php_ldap_is_numerically_indexed_array(Z_ARRVAL_P(attribute_values))) { zend_argument_value_error(3, "attribute \"%s\" must be an array of attribute values with numeric keys", ZSTR_VAL(attribute)); From 0d915c5df2293f46f503a00b96ce2765d8934950 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 20 Feb 2026 13:14:38 +0000 Subject: [PATCH 2/3] fix need to apply to LDAP_MOD_ADD only --- ext/ldap/ldap.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index 805c1059f9d49..40d936bc4222f 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -2339,13 +2339,13 @@ static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper, bool ext) SEPARATE_ARRAY(attribute_values); uint32_t num_values = zend_hash_num_elements(Z_ARRVAL_P(attribute_values)); if (num_values == 0) { - if (UNEXPECTED(is_full_add)) { + if (UNEXPECTED(oper == LDAP_MOD_ADD)) { zend_argument_value_error(3, "attribute \"%s\" must be a non-empty list of attribute values", ZSTR_VAL(attribute)); RETVAL_FALSE; goto cleanup; } - /* When we modify, we means we delete the attribute */ - attribute_index ++; + /* When we modify, we mean we delete the attribute */ + attribute_index++; continue; } if (!php_ldap_is_numerically_indexed_array(Z_ARRVAL_P(attribute_values))) { From d0f0e0f65ceaaf37a840049392dc462f5e608ac7 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 20 Feb 2026 13:16:19 +0000 Subject: [PATCH 3/3] add test --- ext/ldap/tests/gh21262.phpt | 50 +++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 ext/ldap/tests/gh21262.phpt diff --git a/ext/ldap/tests/gh21262.phpt b/ext/ldap/tests/gh21262.phpt new file mode 100644 index 0000000000000..3e414a9cbb129 --- /dev/null +++ b/ext/ldap/tests/gh21262.phpt @@ -0,0 +1,50 @@ +--TEST-- +GH-21262 (ldap_modify() too strict controls argument validation) +--EXTENSIONS-- +ldap +--FILE-- + 'value', + 'attribute2' => [], +]; + +// ldap_add() should still reject empty arrays +try { + ldap_add($ldap, $valid_dn, $entry_with_empty_array); +} catch (ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} + +// ldap_mod_add() should still reject empty arrays +try { + ldap_mod_add($ldap, $valid_dn, $entry_with_empty_array); +} catch (ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} + +// ldap_modify() should accept empty arrays (delete attribute) +try { + @ldap_modify($ldap, $valid_dn, $entry_with_empty_array); + echo "ldap_modify: no ValueError thrown", PHP_EOL; +} catch (ValueError $e) { + echo "ldap_modify: UNEXPECTED ValueError: ", $e->getMessage(), PHP_EOL; +} + +// ldap_mod_del() should accept empty arrays (delete attribute) +try { + @ldap_mod_del($ldap, $valid_dn, $entry_with_empty_array); + echo "ldap_mod_del: no ValueError thrown", PHP_EOL; +} catch (ValueError $e) { + echo "ldap_mod_del: UNEXPECTED ValueError: ", $e->getMessage(), PHP_EOL; +} +?> +--EXPECT-- +ldap_add(): Argument #3 ($entry) attribute "attribute2" must be a non-empty list of attribute values +ldap_mod_add(): Argument #3 ($entry) attribute "attribute2" must be a non-empty list of attribute values +ldap_modify: no ValueError thrown +ldap_mod_del: no ValueError thrown