Author: markt
Date: Thu Dec  8 22:19:41 2016
New Revision: 1773306

URL: http://svn.apache.org/viewvc?rev=1773306&view=rev
Log:
Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=60451
Correctly handle HTTP/2 header values that contain characters with unicode code 
points in the range 128 to 255. Reject with a clear error message HTTP/2 header 
values that contain characters with unicode code points above 255.

Modified:
    tomcat/trunk/java/org/apache/coyote/http2/HPackHuffman.java
    tomcat/trunk/java/org/apache/coyote/http2/Hpack.java
    tomcat/trunk/java/org/apache/coyote/http2/HpackEncoder.java
    tomcat/trunk/java/org/apache/coyote/http2/LocalStrings.properties
    tomcat/trunk/test/org/apache/coyote/http2/TestHpack.java
    tomcat/trunk/webapps/docs/changelog.xml

Modified: tomcat/trunk/java/org/apache/coyote/http2/HPackHuffman.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/HPackHuffman.java?rev=1773306&r1=1773305&r2=1773306&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/HPackHuffman.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http2/HPackHuffman.java Thu Dec  8 
22:19:41 2016
@@ -434,7 +434,11 @@ public class HPackHuffman {
         //so we end up iterating twice
         int length = 0;
         for (int i = 0; i < toEncode.length(); ++i) {
-            byte c = (byte) toEncode.charAt(i);
+            char c = toEncode.charAt(i);
+            if (c > 255) {
+                throw new 
IllegalArgumentException(sm.getString("hpack.invalidCharacter",
+                        Character.toString(c), Integer.valueOf(c)));
+            }
             if(forceLowercase) {
                 c = Hpack.toLower(c);
             }
@@ -450,7 +454,7 @@ public class HPackHuffman {
         int bytePos = 0;
         byte currentBufferByte = 0;
         for (int i = 0; i < toEncode.length(); ++i) {
-            byte c = (byte) toEncode.charAt(i);
+            char c = toEncode.charAt(i);
             if(forceLowercase) {
                 c = Hpack.toLower(c);
             }

Modified: tomcat/trunk/java/org/apache/coyote/http2/Hpack.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/Hpack.java?rev=1773306&r1=1773305&r2=1773306&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/Hpack.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http2/Hpack.java Thu Dec  8 22:19:41 
2016
@@ -204,11 +204,11 @@ final class Hpack {
     }
 
 
-    static byte toLower(byte b) {
-        if (b >= 'A' && b <= 'Z') {
-            return (byte) (b + LOWER_DIFF);
+    static char toLower(char c) {
+        if (c >= 'A' && c <= 'Z') {
+            return (char) (c + LOWER_DIFF);
         }
-        return b;
+        return c;
     }
 
     private Hpack() {}

Modified: tomcat/trunk/java/org/apache/coyote/http2/HpackEncoder.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/HpackEncoder.java?rev=1773306&r1=1773305&r2=1773306&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/HpackEncoder.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http2/HpackEncoder.java Thu Dec  8 
22:19:41 2016
@@ -214,7 +214,7 @@ class HpackEncoder {
         target.put((byte) 0); //to use encodeInteger we need to place the 
first byte in the buffer.
         Hpack.encodeInteger(target, headerName.length(), 7);
         for (int j = 0; j < headerName.length(); ++j) {
-            target.put(Hpack.toLower((byte) headerName.charAt(j)));
+            target.put((byte) Hpack.toLower(headerName.charAt(j)));
         }
 
     }

Modified: tomcat/trunk/java/org/apache/coyote/http2/LocalStrings.properties
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/LocalStrings.properties?rev=1773306&r1=1773305&r2=1773306&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/LocalStrings.properties (original)
+++ tomcat/trunk/java/org/apache/coyote/http2/LocalStrings.properties Thu Dec  
8 22:19:41 2016
@@ -32,6 +32,7 @@ frameType.checkPayloadSize=Payload size
 frameType.checkStream=Invalid frame type [{0}]
 
 hpack.integerEncodedOverTooManyOctets=HPACK variable length integer encoded 
over too many octets, max is {0}
+hpack.invalidCharacter=The Unicode character [{0}] at code point [{1}] cannot 
be encoded as it is outside the permitted range of 0 to 255.
 
 hpackdecoder.zeroNotValidHeaderTableIndex=Zero is not a valid header table 
index
 

Modified: tomcat/trunk/test/org/apache/coyote/http2/TestHpack.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/coyote/http2/TestHpack.java?rev=1773306&r1=1773305&r2=1773306&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/coyote/http2/TestHpack.java (original)
+++ tomcat/trunk/test/org/apache/coyote/http2/TestHpack.java Thu Dec  8 
22:19:41 2016
@@ -85,6 +85,39 @@ public class TestHpack {
         }
     }
 
-    // TODO: Write more complete tests
+    @Test
+    public void testHeaderValueBug60451() throws HpackException {
+        doTestHeaderValueBug60451("fooébar");
+    }
 
+    @Test
+    public void testHeaderValueFullRange() {
+        for (int i = 0; i < 256; i++) {
+            // Skip the control characters except VTAB
+            if (i == 9 || i > 31 && i < 127 || i > 127) {
+                try {
+                    doTestHeaderValueBug60451("foo" + 
Character.toString((char) i)  + "bar");
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    Assert.fail(e.getMessage() + "[" + i + "]");
+                }
+            }
+        }
+    }
+
+    private void doTestHeaderValueBug60451(String filename) throws 
HpackException {
+        String headerName = "Content-Disposition";
+        String headerValue = "attachment;filename=\"" + filename + "\"";
+        MimeHeaders headers = new MimeHeaders();
+        headers.setValue(headerName).setString(headerValue);
+        ByteBuffer output = ByteBuffer.allocate(512);
+        HpackEncoder encoder = new HpackEncoder(1024);
+        encoder.encode(headers, output);
+        output.flip();
+        MimeHeaders headers2 = new MimeHeaders();
+        HpackDecoder decoder = new HpackDecoder();
+        decoder.setHeaderEmitter(new HeadersListener(headers2));
+        decoder.decode(output);
+        Assert.assertEquals(headerValue, headers2.getHeader(headerName));
+    }
 }

Modified: tomcat/trunk/webapps/docs/changelog.xml
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1773306&r1=1773305&r2=1773306&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Thu Dec  8 22:19:41 2016
@@ -56,6 +56,12 @@
         Extract the common Acceptor code from each Endpoint into a new Acceptor
         class that is used by all Endpoints. (markt)
       </scode>
+      <fix>
+        <bug>60451</bug>: Correctly handle HTTP/2 header values that contain
+        characters with unicode code points in the range 128 to 255. Reject
+        with a clear error message HTTP/2 header values that contain characters
+        with unicode code points above 255. (markt)
+      </fix>
     </changelog>
   </subsection>
 </section>



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to