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]

Reply via email to