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 534afe9694 Strip script tags which cannot be represented
534afe9694 is described below
commit 534afe9694d17eced600aef60b956c3c160a288f
Author: remm <[email protected]>
AuthorDate: Mon Oct 26 12:24:48 2026 +0100
Strip script tags which cannot be represented
BZ70286.
---
.../tomcat/util/http/parser/AcceptLanguage2.java | 25 ++++++++++++----------
.../org/apache/catalina/connector/TestRequest.java | 25 ++++++++++++++++++++++
webapps/docs/changelog.xml | 7 ++++++
3 files changed, 46 insertions(+), 11 deletions(-)
diff --git a/java/org/apache/tomcat/util/http/parser/AcceptLanguage2.java
b/java/org/apache/tomcat/util/http/parser/AcceptLanguage2.java
index ccdd554cc6..4f3362209d 100644
--- a/java/org/apache/tomcat/util/http/parser/AcceptLanguage2.java
+++ b/java/org/apache/tomcat/util/http/parser/AcceptLanguage2.java
@@ -34,9 +34,12 @@ import java.util.Locale;
* <ul>
* <li>Unicode, other and private use extensions (e.g. {@code
-u-ca-buddhist},
* {@code -x-priv}) are discarded rather than recorded on the
Locale.</li>
- * <li>Script subtags (e.g. {@code -Hant-}) cannot be represented by the
- * deprecated constructor and are mapped to the Locale variant, in upper
- * case, instead of to the Locale script.</li>
+ * <li>Script subtags (e.g. {@code -Hant-}) are discarded. The deprecated
+ * constructor has no script component and {@code zh-Hans-CN} therefore
+ * yields the Locale for {@code zh-CN}. Mapping the script to the variant
+ * instead kept the information but produced a Locale whose language tag
+ * is not the one the client sent, {@code zh-CN-x-lvariant-HANS} rather
+ * than {@code zh-Hans-CN}.</li>
* <li>Tags that are syntactically invalid after the language subtag retain
* the components parsed up to that point rather than being replaced with
* {@link Locale#ROOT}.</li>
@@ -113,10 +116,9 @@ public final class AcceptLanguage2 {
* <p>
* Component mapping: the primary subtag becomes the language, the region
* subtag (2 alpha or 3 digits) becomes the country, the script subtag (4
- * alpha) is upper-cased and mapped to the variant, any other variant
- * subtags are appended to the variant unchanged (variant values are case
- * sensitive in Locale) with '_' as separator, and extension/private use
- * subtags are dropped.
+ * alpha) is discarded, any variant subtags are appended to the variant
+ * unchanged (variant values are case sensitive in Locale) with '_' as
+ * separator, and extension/private use subtags are dropped.
*
* @param tag The language tag
*
@@ -171,10 +173,11 @@ public final class AcceptLanguage2 {
countrySeen = true;
} else if (subLen == 4 && !scriptSeen && !countrySeen &&
allAsciiAlpha(tag, pos, end)) {
// Script subtag. The deprecated constructor has no script
- // component so it is mapped to the variant instead. The
- // subtag is upper-cased to clearly distinguish it from
- // regular variant subtags which are kept unchanged.
- appendVariant(variant, upper(tag, pos, end));
+ // component, and the variant cannot hold a four letter subtag
+ // without producing a language tag that differs from the one
+ // that was received, so the script is discarded. Parsing
+ // continues so that a region subtag following the script is
+ // still used.
scriptSeen = true;
} else if (isVariantSubtag(tag, pos, end, subLen)) {
// Variant subtag. Locale variants are case sensitive and
diff --git a/test/org/apache/catalina/connector/TestRequest.java
b/test/org/apache/catalina/connector/TestRequest.java
index 98fea5a8fa..5901b39a66 100644
--- a/test/org/apache/catalina/connector/TestRequest.java
+++ b/test/org/apache/catalina/connector/TestRequest.java
@@ -935,6 +935,31 @@ public class TestRequest extends TomcatBaseTest {
Assert.assertEquals(expected, actual);
}
+ /*
+ * A script subtag in the Accept-Language header must not end up in the
+ * Locale variant, which made the Locale report the language tag
+ * zh-CN-x-lvariant-HANS for the tag the client sent as zh-Hans-CN. The
+ * default parser cannot represent the script at all and drops it, the
+ * standard parser keeps it.
+ */
+ @Test
+ public void getLocaleScript() throws Exception {
+ TesterRequest req = new TesterRequest();
+
+ req.addHeader("accept-language", "zh-Hans-CN;q=1.0");
+
+ Locale actual = req.getLocale();
+
+ boolean standardParser = Boolean
+
.getBoolean("org.apache.tomcat.util.http.parser.StandardAcceptLanguageParser");
+ Locale expected = Locale.forLanguageTag(standardParser ? "zh-Hans-CN"
: "zh-CN");
+
+ Assert.assertEquals(expected, actual);
+ Assert.assertEquals("CN", actual.getCountry());
+ Assert.assertEquals("", actual.getVariant());
+ Assert.assertEquals(expected.toLanguageTag(), actual.toLanguageTag());
+ }
+
@Test
public void testGetReaderValidEncoding() throws Exception {
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 9f0105f358..7e6f00d545 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -432,6 +432,13 @@
Add TLS pre-shared key support to the OpenSSL FFM implementation.
(markt)
</add>
+ <fix>
+ <bug>70286</bug>: Strip the scipt tag in the
+ <code>AcceptLanguage2</code> parser, If the script subtag needs to be
+ preserved, use the standard parser by setting the system property
+
<code>org.apache.tomcat.util.http.parser.StandardAcceptLanguageParser</code>
+ to <code>true</code>. (remm)
+ </fix>
</changelog>
</subsection>
<subsection name="Jasper">
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]