This is an automated email from the ASF dual-hosted git repository.
garydgregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-lang.git
The following commit(s) were added to refs/heads/master by this push:
new 57bd7dd09 Keep LocaleUtils.toLocale to ASCII language and country
codes (#1838)
57bd7dd09 is described below
commit 57bd7dd094fd855f2ab3c969170933bbd7bafa2d
Author: alhuda <[email protected]>
AuthorDate: Sun Oct 25 19:10:47 2026 +0530
Keep LocaleUtils.toLocale to ASCII language and country codes (#1838)
* keep LocaleUtils.toLocale to ASCII language and country codes
toLocale(String) documents strict validation, but its language, country
and area-code checks used StringUtils.isAllLowerCase, isAllUpperCase,
isNumeric and Character.isUpperCase, which accept any Unicode letter or
decimal digit. java.util.Locale defines these codes as [a-zA-Z]{2,8},
[a-zA-Z]{2} and [0-9]{3}, so fullwidth letters, Latin-1 letters and
Arabic-Indic digits were turned into an ill-formed Locale instead of
an IllegalArgumentException.
Check those characters against the ASCII ranges. Variants are unchanged.
* Use a parameterized test for LocaleUtils non-ASCII codes
---
src/main/java/org/apache/commons/lang3/LocaleUtils.java | 8 ++++----
.../java/org/apache/commons/lang3/LocaleUtilsTest.java | 15 +++++++++++++++
2 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/src/main/java/org/apache/commons/lang3/LocaleUtils.java
b/src/main/java/org/apache/commons/lang3/LocaleUtils.java
index fd8854b71..cbc721c09 100644
--- a/src/main/java/org/apache/commons/lang3/LocaleUtils.java
+++ b/src/main/java/org/apache/commons/lang3/LocaleUtils.java
@@ -214,7 +214,7 @@ public static boolean isAvailableLocale(final Locale
locale) {
* @return true if the given String is a <a
href="https://www.iso.org/iso-3166-country-codes.html">ISO 3166</a> compliant
country code.
*/
private static boolean isISO3166CountryCode(final String str) {
- return StringUtils.isAllUpperCase(str) && isAlpha2Len(str);
+ return isAlpha2Len(str) && str.chars().allMatch(ch ->
CharUtils.isAsciiAlphaUpper((char) ch));
}
/**
@@ -224,7 +224,7 @@ private static boolean isISO3166CountryCode(final String
str) {
* @return true, if the given String is a <a
href="https://www.iso.org/iso-639-language-code">ISO 639</a> compliant language
code.
*/
private static boolean isISO639LanguageCode(final String str) {
- return StringUtils.isAllLowerCase(str) && (isAlpha2Len(str) ||
isAlpha3Len(str));
+ return (isAlpha2Len(str) || isAlpha3Len(str)) &&
str.chars().allMatch(ch -> CharUtils.isAsciiAlphaLower((char) ch));
}
/**
@@ -250,7 +250,7 @@ public static boolean isLanguageUndetermined(final Locale
locale) {
* @return true if the given String is a UN M.49 numeric area code.
*/
private static boolean isNumericAreaCode(final String str) {
- return StringUtils.isNumeric(str) && isAlpha3Len(str);
+ return isAlpha3Len(str) && str.chars().allMatch(ch ->
CharUtils.isAsciiNumeric((char) ch));
}
/**
@@ -446,7 +446,7 @@ public static Locale toLocale(final String str) {
}
final char ch1 = str.charAt(1);
final char ch2 = str.charAt(2);
- if (!Character.isUpperCase(ch1) || !Character.isUpperCase(ch2)) {
+ if (!CharUtils.isAsciiAlphaUpper(ch1) ||
!CharUtils.isAsciiAlphaUpper(ch2)) {
throw new IllegalArgumentException("Invalid locale format: " +
str);
}
if (len == 3) {
diff --git a/src/test/java/org/apache/commons/lang3/LocaleUtilsTest.java
b/src/test/java/org/apache/commons/lang3/LocaleUtilsTest.java
index 38ea40ab7..cb665f882 100644
--- a/src/test/java/org/apache/commons/lang3/LocaleUtilsTest.java
+++ b/src/test/java/org/apache/commons/lang3/LocaleUtilsTest.java
@@ -540,6 +540,21 @@ void testToLocale_2Part() {
assertIllegalArgumentException(() -> LocaleUtils.toLocale("us_E3"),
"Should fail second part not uppercase");
}
+ /**
+ * Tests that language, country and area codes are restricted to ASCII, as
{@link Locale} defines them.
+ */
+ @ParameterizedTest
+ @ValueSource(strings = {
+ // FULLWIDTH LATIN SMALL LETTER E and N
+ "en", "éé", "éé_GB",
+ // FULLWIDTH LATIN CAPITAL LETTER G and B
+ "en_GB", "en_ÉÉ", "en_ÉÉ_POSIX", "_ÉÉ", "_ÉÉ_POSIX",
+ // ARABIC-INDIC DIGIT ONE, TWO and THREE
+ "en_١٢٣" })
+ void testToLocaleNonAsciiCodes(final String localeString) {
+ assertIllegalArgumentException(() ->
LocaleUtils.toLocale(localeString), "Should fail code not ASCII: " +
localeString);
+ }
+
/**
* Test toLocale() method.
*/