Commit b2956e0bb32 for php.net
commit b2956e0bb326913d91bfa22e1059896c6bd7c6b9
Author: Ilia Alshanetsky <ilia@ilia.ws>
Date: Mon Aug 17 20:40:15 2026 -0400
Close the keyword UEnumeration on Locale::getKeywords failure
uloc_getKeywordValue failure destroyed the result array and returned
without uenum_close(). Close the enumeration on that path. The success
path already closes it.
Audited the other uenum_close site in this file (acceptLanguage).
Closes GH-23351
diff --git a/NEWS b/NEWS
index 5607f31081b..e56e562a4c9 100644
--- a/NEWS
+++ b/NEWS
@@ -32,6 +32,8 @@ PHP NEWS
. Fixed Locale::parseLocale() reading past a trailing '-' or '_'.
(iliaal, Xuyang Zhang)
. Fixed grapheme_str_split() treating UBRK_DONE as a byte index. (iliaal)
+ . Fixed a leak in Locale::getKeywords() when a keyword value cannot be
+ read. (iliaal)
- Opcache:
. Fixed opcache.protect_memory race under ZTS. (realFlowControl)
diff --git a/ext/intl/locale/locale_methods.c b/ext/intl/locale/locale_methods.c
index e3894b6f28f..2643f492087 100644
--- a/ext/intl/locale/locale_methods.c
+++ b/ext/intl/locale/locale_methods.c
@@ -776,6 +776,7 @@ PHP_FUNCTION( locale_get_keywords )
zend_string_efree( kw_value_str );
}
zend_array_destroy(Z_ARR_P(return_value));
+ uenum_close( e );
RETURN_FALSE;
}
diff --git a/ext/intl/tests/locale_get_keywords_failure.phpt b/ext/intl/tests/locale_get_keywords_failure.phpt
new file mode 100644
index 00000000000..823da63ca54
--- /dev/null
+++ b/ext/intl/tests/locale_get_keywords_failure.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Locale::getKeywords() closes the keyword enumeration on failure
+--EXTENSIONS--
+intl
+--SKIPIF--
+<?php
+if (version_compare(INTL_ICU_VERSION, '59.1', '<')) {
+ die('skip for ICU >= 59.1');
+}
+?>
+--FILE--
+<?php
+var_dump(Locale::getKeywords('en@foo=bar!'));
+var_dump(intl_get_error_code() === U_ILLEGAL_ARGUMENT_ERROR);
+?>
+--EXPECT--
+bool(false)
+bool(true)