This is an automated email from the ASF dual-hosted git repository.

markt-asf pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/main by this push:
     new 37ac5d7821 Improve case-insenstive comparisons.
37ac5d7821 is described below

commit 37ac5d78214f229a6257dc4b4cfc2e15d9f7f080
Author: Mark Thomas <[email protected]>
AuthorDate: Fri May 22 18:38:50 2026 +0100

    Improve case-insenstive comparisons.
    
    Update documentation to expand supported range from 0x00-0x7F to
    0x00-0xFF where appropriate.
    Based on PR #1010 by Chenjp
---
 java/org/apache/catalina/mapper/Mapper.java           | 16 ++++++++++++++--
 java/org/apache/tomcat/util/buf/ByteChunk.java        | 10 ++++++----
 java/org/apache/tomcat/util/buf/CharChunk.java        | 18 ++++++++++++++++--
 java/org/apache/tomcat/util/buf/MessageBytes.java     | 10 +++++++++-
 test/org/apache/tomcat/util/buf/TestByteChunk.java    | 10 ++++++++++
 test/org/apache/tomcat/util/http/TestMimeHeaders.java | 13 ++++++++++++-
 6 files changed, 67 insertions(+), 10 deletions(-)

diff --git a/java/org/apache/catalina/mapper/Mapper.java 
b/java/org/apache/catalina/mapper/Mapper.java
index 897c6a1237..bfbc6e88b7 100644
--- a/java/org/apache/catalina/mapper/Mapper.java
+++ b/java/org/apache/catalina/mapper/Mapper.java
@@ -1391,8 +1391,20 @@ public final class Mapper {
             len = end - start;
         }
         for (int i = 0; (i < len) && (result == 0); i++) {
-            int nameLower = Ascii.toLower(c[i + start]);
-            int compareLower = Ascii.toLower(compareTo.charAt(i));
+            char cName = c[i + start];
+            char cCompare = compareTo.charAt(i);
+            int nameLower;
+            int compareLower;
+            if (cName > 0xFF) {
+                nameLower = Character.toLowerCase(cName);
+            } else {
+                nameLower = Ascii.toLower(cName);
+            }
+            if (cCompare > 0xFF) {
+                compareLower = Character.toLowerCase(cCompare);
+            } else {
+                compareLower = Ascii.toLower(compareTo.charAt(i));
+            }
             if (nameLower > compareLower) {
                 result = 1;
             } else if (nameLower < compareLower) {
diff --git a/java/org/apache/tomcat/util/buf/ByteChunk.java 
b/java/org/apache/tomcat/util/buf/ByteChunk.java
index e9011d5b30..0a6fb23ef1 100644
--- a/java/org/apache/tomcat/util/buf/ByteChunk.java
+++ b/java/org/apache/tomcat/util/buf/ByteChunk.java
@@ -691,7 +691,7 @@ public final class ByteChunk extends AbstractChunk {
     /**
      * Compares the message bytes to the specified String object.
      * <p>
-     * NOTE: This only works for characters in the range 0-127.
+     * NOTE: This only works for characters in the range 0-255.
      *
      * @param s the String to compare
      *
@@ -705,7 +705,8 @@ public final class ByteChunk extends AbstractChunk {
         }
         int off = start;
         for (int i = 0; i < len; i++) {
-            if (Ascii.toLower(b[off++]) != Ascii.toLower(s.charAt(i))) {
+            char c = s.charAt(i);
+            if (c > 0xFF || Ascii.toLower(b[off++]) != Ascii.toLower(c)) {
                 return false;
             }
         }
@@ -860,7 +861,7 @@ public final class ByteChunk extends AbstractChunk {
     /**
      * Returns true if the buffer starts with the specified string when tested 
in a case-insensitive manner.
      * <p>
-     * NOTE: This only works for characters in the range 0-127.
+     * NOTE: This only works for characters in the range 0-255.
      *
      * @param s   the string
      * @param pos The position
@@ -875,7 +876,8 @@ public final class ByteChunk extends AbstractChunk {
         }
         int off = start + pos;
         for (int i = 0; i < len; i++) {
-            if (Ascii.toLower(b[off++]) != Ascii.toLower(s.charAt(i))) {
+            char c = s.charAt(i);
+            if (c > 0xFF || Ascii.toLower(b[off++]) != Ascii.toLower(c)) {
                 return false;
             }
         }
diff --git a/java/org/apache/tomcat/util/buf/CharChunk.java 
b/java/org/apache/tomcat/util/buf/CharChunk.java
index b169f72d12..b7084a2fad 100644
--- a/java/org/apache/tomcat/util/buf/CharChunk.java
+++ b/java/org/apache/tomcat/util/buf/CharChunk.java
@@ -502,7 +502,14 @@ public final class CharChunk extends AbstractChunk 
implements CharSequence {
         }
         int off = start;
         for (int i = 0; i < len; i++) {
-            if (Ascii.toLower(c[off++]) != Ascii.toLower(s.charAt(i))) {
+            char c1 = c[off++];
+            char c2 = s.charAt(i);
+            // Use ASCII short-cut if possible
+            if (c1 > 0xFF || c2 > 0xFF) {
+                if (Character.toLowerCase(c1) != Character.toLowerCase(c2)) {
+                    return false;
+                }
+            } else if (Ascii.toLower(c1) != Ascii.toLower(c2)) {
                 return false;
             }
         }
@@ -592,7 +599,14 @@ public final class CharChunk extends AbstractChunk 
implements CharSequence {
         }
         int off = start + pos;
         for (int i = 0; i < len; i++) {
-            if (Ascii.toLower(c[off++]) != Ascii.toLower(s.charAt(i))) {
+            char c1 = c[off++];
+            char c2 = s.charAt(i);
+            // Use ASCII short-cut if possible
+            if (c1 > 0xFF || c2 > 0xFF) {
+                if (Character.toLowerCase(c1) != Character.toLowerCase(c2)) {
+                    return false;
+                }
+            } else if (Ascii.toLower(c1) != Ascii.toLower(c2)) {
                 return false;
             }
         }
diff --git a/java/org/apache/tomcat/util/buf/MessageBytes.java 
b/java/org/apache/tomcat/util/buf/MessageBytes.java
index 205879f2e4..499e46390f 100644
--- a/java/org/apache/tomcat/util/buf/MessageBytes.java
+++ b/java/org/apache/tomcat/util/buf/MessageBytes.java
@@ -487,9 +487,17 @@ public final class MessageBytes implements Cloneable, 
Serializable {
                 }
 
                 for (int i = 0; i < s.length(); i++) {
-                    if (Ascii.toLower(s.charAt(i)) != 
Ascii.toLower(strValue.charAt(pos + i))) {
+                    char c1 = s.charAt(i);
+                    char c2 = strValue.charAt(pos + i);
+                    // Use ASCII short-cut if possible
+                    if (c1 > 0xFF || c2 > 0xFF) {
+                        if (Character.toLowerCase(c1) != 
Character.toLowerCase(c2)) {
+                            return false;
+                        }
+                    } else if (Ascii.toLower(c1) != Ascii.toLower(c2)) {
                         return false;
                     }
+
                 }
                 return true;
             case T_CHARS:
diff --git a/test/org/apache/tomcat/util/buf/TestByteChunk.java 
b/test/org/apache/tomcat/util/buf/TestByteChunk.java
index ce8234230e..23f5e7e0ef 100644
--- a/test/org/apache/tomcat/util/buf/TestByteChunk.java
+++ b/test/org/apache/tomcat/util/buf/TestByteChunk.java
@@ -179,4 +179,14 @@ public class TestByteChunk {
         // immediately after a call to recycle().
         Assert.assertNull(bc.toString());
     }
+
+
+    @Test
+    public void testEqualsIgnoreCase() {
+        byte[] bytes = "Hello".getBytes();
+        ByteChunk bc = new ByteChunk();
+        bc.setBytes(bytes, 0, bytes.length);
+        Assert.assertTrue(bc.equalsIgnoreCase("heLLo"));
+        
Assert.assertFalse(bc.equalsIgnoreCase("\u8a48\u8a65\u8a6c\u8a6c\u8a6f"));
+    }
 }
diff --git a/test/org/apache/tomcat/util/http/TestMimeHeaders.java 
b/test/org/apache/tomcat/util/http/TestMimeHeaders.java
index efc7832bf7..7136ab1ce0 100644
--- a/test/org/apache/tomcat/util/http/TestMimeHeaders.java
+++ b/test/org/apache/tomcat/util/http/TestMimeHeaders.java
@@ -16,6 +16,7 @@
  */
 package org.apache.tomcat.util.http;
 
+import java.io.UnsupportedEncodingException;
 import java.util.Enumeration;
 import java.util.HashSet;
 import java.util.Set;
@@ -107,4 +108,14 @@ public class TestMimeHeaders {
         }
         Assert.assertFalse(names.hasMoreElements());
     }
-}
+
+
+    @Test
+    public void testSetValueBytesIgnoresCase01() throws 
UnsupportedEncodingException {
+        MimeHeaders mh = new MimeHeaders();
+
+        byte[] bytes = HEADER_NAME_UC_STRING.getBytes("utf-8");
+        mh.setValue(HEADER_NAME_UC_STRING).setBytes(bytes, 0, bytes.length);
+        
Assert.assertTrue(mh.getValue(HEADER_NAME_UC_STRING).equalsIgnoreCase(HEADER_NAME_MIXED_STRING));
+        
Assert.assertFalse(mh.getValue(HEADER_NAME_UC_STRING).equalsIgnoreCase("\u8a54\u8a45\u8a53\u8a54"));
+    }}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to