This is an automated email from the ASF dual-hosted git repository.
rmaucher pushed a commit to branch 10.1.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/10.1.x by this push:
new 4b70c7e9b7 Allow maxLocaleCount to soft fail
4b70c7e9b7 is described below
commit 4b70c7e9b73ebab6d45c4755ba1828b7a80a9a3b
Author: remm <[email protected]>
AuthorDate: Fri Oct 23 11:38:00 2026 +0200
Allow maxLocaleCount to soft fail
Exceeding the locale count leaves the request functionally correct,
unlike what happens for request parameters.
As a result, simply ignore extra locales, and log an info message about
it.
---
java/org/apache/catalina/connector/Request.java | 18 ++----
.../org/apache/catalina/connector/TestRequest.java | 65 +---------------------
webapps/docs/changelog.xml | 5 ++
webapps/docs/config/http.xml | 6 +-
4 files changed, 17 insertions(+), 77 deletions(-)
diff --git a/java/org/apache/catalina/connector/Request.java
b/java/org/apache/catalina/connector/Request.java
index a4750befbb..4f8c81d023 100644
--- a/java/org/apache/catalina/connector/Request.java
+++ b/java/org/apache/catalina/connector/Request.java
@@ -131,12 +131,6 @@ public class Request implements HttpServletRequest {
private static final String HTTP_UPGRADE_HEADER_NAME = "upgrade";
- /**
- * The default value of the maximum number of locales to parse from the
Accept-Language header(s). Must match the
- * default of the maxLocaleCount attribute of the Connector with which a
Request is associated.
- */
- private static final int DEFAULT_MAX_LOCALE_COUNT = 10;
-
/*
* Use AcceptLanguage2 parser rather than the StandardAcceptLanguageParser.
*/
@@ -447,10 +441,9 @@ public class Request implements HttpServletRequest {
* The maximum number of locales permitted for a request. The
Accept-Language header value is untrusted input
* bounded only by the maximum header size so the number of locales is
bounded by default to limit the
* per-request processing and the number of distinct locales exposed to
web applications and internal components.
- * Requests that exceed this limit are rejected when the locales are
parsed. A value of less than zero means no
- * limit.
+ * A value of less than zero means no limit.
*/
- private int maxLocaleCount = DEFAULT_MAX_LOCALE_COUNT;
+ private int maxLocaleCount = -1;
// --------------------------------------------------------- Public Methods
@@ -507,7 +500,7 @@ public class Request implements HttpServletRequest {
maxParameterCount = -1;
maxPartCount = -1;
maxPartHeaderSize = -1;
- maxLocaleCount = DEFAULT_MAX_LOCALE_COUNT;
+ maxLocaleCount = -1;
}
if (parts != null) {
for (Part part : parts) {
@@ -3355,8 +3348,9 @@ public class Request implements HttpServletRequest {
for (ArrayList<Locale> list : locales.values()) {
for (Locale locale : list) {
if (maxLocaleCount > -1 && this.locales.size() >=
maxLocaleCount) {
- throw new IllegalArgumentException(
- sm.getString("coyoteRequest.tooManyLocales",
Integer.valueOf(maxLocaleCount)));
+ // Remove the last element
+ this.locales.remove(this.locales.size() - 1);
+ log.info(sm.getString("coyoteRequest.tooManyLocales",
Integer.valueOf(maxLocaleCount)));
}
addLocale(locale);
}
diff --git a/test/org/apache/catalina/connector/TestRequest.java
b/test/org/apache/catalina/connector/TestRequest.java
index e06926b1f9..98fea5a8fa 100644
--- a/test/org/apache/catalina/connector/TestRequest.java
+++ b/test/org/apache/catalina/connector/TestRequest.java
@@ -825,33 +825,6 @@ public class TestRequest extends TomcatBaseTest {
}
}
- /*
- * The number of locales in the Accept-Language header(s) is
- * limited because the header value is untrusted input. Requests
- * that exceed the limit are rejected (when the locales are
- * accessed) in the same way as requests that exceed
- * maxCookieCount.
- */
- @Test
- public void testAcceptLanguageLocaleLimit() throws Exception {
- TesterRequest req = new TesterRequest();
-
- req.addHeader("accept-language", buildAcceptLanguage(20));
-
- try {
- req.getLocales();
- Assert.fail("Accessing the locales when the limit is exceeded
should throw an IllegalArgumentException");
- } catch (IllegalArgumentException iae) {
- // Expected
- }
-
- // Requests within the limit are processed and the highest
- // quality locale (at the start of the list) is retained
- req = new TesterRequest();
- req.addHeader("accept-language", "aa-000,aa-001,aa-002");
- Assert.assertEquals(Locale.forLanguageTag("aa-000"), req.getLocale());
- }
-
/*
* The locale limit is configurable via the maxLocaleCount attribute
* of the Connector associated with the request.
@@ -866,12 +839,7 @@ public class TestRequest extends TomcatBaseTest {
connector.setMaxLocaleCount(5);
Assert.assertEquals(5, localeCount(connector, buildAcceptLanguage(5)));
- try {
- localeCount(connector, buildAcceptLanguage(6));
- Assert.fail("Exceeding maxLocaleCount should throw an
IllegalArgumentException");
- } catch (IllegalArgumentException iae) {
- // Expected
- }
+ Assert.assertEquals(5, localeCount(connector, buildAcceptLanguage(6)));
// No limit
connector = new Connector();
@@ -905,28 +873,6 @@ public class TestRequest extends TomcatBaseTest {
return count;
}
- /*
- * The limit on untrusted locale tags is enforced while the
- * header is parsed so that Locale objects are not created for
- * entries that can never be used.
- */
- @Test
- public void testAcceptLanguageLocaleLimitHeaderFlood() throws Exception {
- Connector connector = new Connector();
-
- // Default limit of 10. A header with far more tags than the
- // limit is rejected.
- try {
- localeCount(connector, buildAcceptLanguage(5000));
- Assert.fail("A header with 5000 locales should be rejected");
- } catch (IllegalArgumentException iae) {
- // Expected
- }
-
- // Exactly the limit is accepted.
- Assert.assertEquals(10, localeCount(connector,
buildAcceptLanguage(10)));
- }
-
/*
* When multiple Accept-Language headers are present the limit
* applies to the combined set of locales and parsing stops
@@ -939,13 +885,8 @@ public class TestRequest extends TomcatBaseTest {
"aa-005,aa-006,aa-007,aa-008,aa-009"));
// 5 + 6 = 11, exceeds the default limit
- try {
- localeCount(new Connector(), "aa-000,aa-001,aa-002,aa-003,aa-004",
- "aa-005,aa-006,aa-007,aa-008,aa-009,aa-010");
- Assert.fail("11 locales across two headers should be rejected");
- } catch (IllegalArgumentException iae) {
- // Expected
- }
+ Assert.assertEquals(10, localeCount(new Connector(),
"aa-000,aa-001,aa-002,aa-003,aa-004",
+ "aa-005,aa-006,aa-007,aa-008,aa-009,aa-010"));
}
private static int localeCount(Connector connector, String...
acceptLanguages) {
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index c8dfc6e84d..f8afa8b677 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -261,6 +261,11 @@
Mark JAASRealm as a deprecated component. JAASRealm will be removed in
Tomcat 12. (schultz)
</update>
+ <fix>
+ Rework <code>maxLocaleCount</code> behavior to ignore extra locales
+ when parsed instead of throwing an ISE, since a request remains
+ functionally coherent. (remm)
+ </fix>
</changelog>
</subsection>
<subsection name="Coyote">
diff --git a/webapps/docs/config/http.xml b/webapps/docs/config/http.xml
index 24d5a1dd23..a5d9e673bf 100644
--- a/webapps/docs/config/http.xml
+++ b/webapps/docs/config/http.xml
@@ -173,9 +173,9 @@
<attribute name="maxLocaleCount" required="false">
<p>The maximum number of locales (obtained from the
<code>Accept-Language</code> header(s)) that are permitted for a request.
- Requests that exceed this limit will be rejected when the locales are
- parsed. A value of less than 0 means no limit. If not specified, a
- default of 10 is used.</p>
+ Locales above this limit will be ignored when the locales are
+ parsed and an info will be logged. A value of less than 0 means no
+ limit. If not specified, a default of 10 is used.</p>
</attribute>
<attribute name="maxParameterCount" required="false">
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]