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