diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index 51eca3d7cc4de..ae65f0258c24b 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -2544,8 +2544,11 @@ PHP_FUNCTION(ldap_modify_batch) /* for the modification hashtable... */ zend_hash_internal_pointer_reset(Z_ARRVAL_P(mod)); num_modprops = zend_hash_num_elements(Z_ARRVAL_P(mod)); + bool has_attrib_key = false; + bool has_modtype_key = false; for (j = 0; j < num_modprops; j++) { + /* are the keys strings? */ if (zend_hash_get_current_key(Z_ARRVAL_P(mod), &modkey, &tmpUlong) != HASH_KEY_IS_STRING) { zend_argument_type_error(3, "must only contain string-indexed arrays"); @@ -2567,6 +2570,7 @@ PHP_FUNCTION(ldap_modify_batch) /* does the value type match the key? */ if (_ldap_str_equal_to_const(ZSTR_VAL(modkey), ZSTR_LEN(modkey), LDAP_MODIFY_BATCH_ATTRIB)) { + has_attrib_key = true; if (Z_TYPE_P(modinfo) != IS_STRING) { zend_type_error("%s(): Option \"" LDAP_MODIFY_BATCH_ATTRIB "\" must be of type string, %s given", get_active_function_name(), zend_zval_type_name(modinfo)); RETURN_THROWS(); @@ -2578,6 +2582,7 @@ PHP_FUNCTION(ldap_modify_batch) } } else if (_ldap_str_equal_to_const(ZSTR_VAL(modkey), ZSTR_LEN(modkey), LDAP_MODIFY_BATCH_MODTYPE)) { + has_modtype_key = true; if (Z_TYPE_P(modinfo) != IS_LONG) { zend_type_error("%s(): Option \"" LDAP_MODIFY_BATCH_MODTYPE "\" must be of type int, %s given", get_active_function_name(), zend_zval_type_name(modinfo)); RETURN_THROWS(); @@ -2641,6 +2646,15 @@ PHP_FUNCTION(ldap_modify_batch) zend_hash_move_forward(Z_ARRVAL_P(mod)); } + + if (!has_attrib_key) { + zend_value_error("%s(): Required option \"" LDAP_MODIFY_BATCH_ATTRIB "\" is missing", get_active_function_name()); + RETURN_THROWS(); + } + if (!has_modtype_key) { + zend_value_error("%s(): Required option \"" LDAP_MODIFY_BATCH_MODTYPE "\" is missing", get_active_function_name()); + RETURN_THROWS(); + } } } /* validation was successful */ diff --git a/ext/ldap/tests/gh16032-1.phpt b/ext/ldap/tests/gh16032-1.phpt new file mode 100644 index 0000000000000..dbaf8213933d7 --- /dev/null +++ b/ext/ldap/tests/gh16032-1.phpt @@ -0,0 +1,26 @@ +--TEST-- +Bug GH-16032: Various NULL pointer dereferencements in ldap_modify_batch() +--EXTENSIONS-- +ldap +--FILE-- + LDAP_MODIFY_BATCH_ADD, + "values" => ["value1"], + ], +]; +try { + var_dump(ldap_modify_batch($ldap, $valid_dn, $modification_missing_attrib_key)); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +ValueError: ldap_modify_batch(): Required option "attrib" is missing diff --git a/ext/ldap/tests/gh16032-2.phpt b/ext/ldap/tests/gh16032-2.phpt new file mode 100644 index 0000000000000..531415807f674 --- /dev/null +++ b/ext/ldap/tests/gh16032-2.phpt @@ -0,0 +1,26 @@ +--TEST-- +Bug GH-16032: Various NULL pointer dereferencements in ldap_modify_batch() +--EXTENSIONS-- +ldap +--FILE-- + "attrib1", + "values" => ["value1"], + ], +]; +try { + var_dump(ldap_modify_batch($ldap, $valid_dn, $modification_missing_modtype_key)); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +ValueError: ldap_modify_batch(): Required option "modtype" is missing