Index: connectors/http11/src/java/org/apache/coyote/http11/Constants.java =================================================================== --- connectors/http11/src/java/org/apache/coyote/http11/Constants.java (revision 1378244) +++ connectors/http11/src/java/org/apache/coyote/http11/Constants.java (working copy) @@ -85,7 +85,12 @@ */ public static final byte COLON = (byte) ':'; + /** + * SEMI_COLON. + */ + public static final byte SEMI_COLON = (byte) ';'; + /** * 'A'. */ Index: connectors/http11/src/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java =================================================================== --- connectors/http11/src/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java (revision 1378244) +++ connectors/http11/src/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java (working copy) @@ -28,7 +28,8 @@ import org.apache.coyote.http11.InputFilter; /** - * Chunked input filter. + * Chunked input filter. Parses chunked data according to + * http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6.1
* * @author Remy Maucherat */ @@ -128,7 +129,7 @@ if (remaining <= 0) { if (!parseChunkHeader()) { - throw new IOException("Invalid chunk"); + throw new IOException("Invalid chunk header"); } if (endChunk) { parseEndChunk(); @@ -236,6 +237,14 @@ /** * Parse the header of a chunk. + * A chunk header can look like one of the following:
+ * A10CRLF
+ * F23;chunk-extension to be ignoredCRLF + * + *

+ * The letters before CRLF or ';' (whatever comes first) must be valid hex + * digits. We should not parse F23IAMGONNAMESSTHISUP34CRLF as a valid + * header according to the spec. */ protected boolean parseChunkHeader() throws IOException { @@ -243,6 +252,7 @@ int result = 0; boolean eol = false; boolean readDigit = false; + boolean trailer = false; while (!eol) { @@ -254,11 +264,19 @@ if (buf[pos] == Constants.CR) { } else if (buf[pos] == Constants.LF) { eol = true; - } else { - if (HexUtils.DEC[buf[pos]] != -1) { + } else if (buf[pos] == Constants.SEMI_COLON) { + trailer = true; + } else if (!trailer) { + //don't read data after the trailer + int charValue = HexUtils.getDec(buf[pos]); + if (charValue != -1) { readDigit = true; result *= 16; - result += HexUtils.DEC[buf[pos]]; + result += charValue; + } else { + //we shouldn't allow invalid, non hex characters + //in the chunked header + return false; } } Index: connectors/http11/src/java/org/apache/coyote/http11/Http11AprProcessor.java =================================================================== --- connectors/http11/src/java/org/apache/coyote/http11/Http11AprProcessor.java (revision 1378244) +++ connectors/http11/src/java/org/apache/coyote/http11/Http11AprProcessor.java (working copy) @@ -113,7 +113,7 @@ initializeFilters(); // Cause loading of HexUtils - int foo = HexUtils.DEC[0]; + HexUtils.getDec('0'); // Cause loading of FastHttpDateFormat FastHttpDateFormat.getCurrentDate(); @@ -1459,7 +1459,7 @@ int port = 0; int mult = 1; for (int i = valueL - 1; i > colonPos; i--) { - int charValue = HexUtils.DEC[(int) valueB[i + valueS]]; + int charValue = HexUtils.getDec(valueB[i + valueS]); if (charValue == -1) { // Invalid character error = true; Index: connectors/http11/src/java/org/apache/coyote/http11/Http11Processor.java =================================================================== --- connectors/http11/src/java/org/apache/coyote/http11/Http11Processor.java (revision 1378244) +++ connectors/http11/src/java/org/apache/coyote/http11/Http11Processor.java (working copy) @@ -111,7 +111,7 @@ initializeFilters(); // Cause loading of HexUtils - int foo = HexUtils.DEC[0]; + HexUtils.getDec('0'); } @@ -1420,7 +1420,7 @@ int port = 0; int mult = 1; for (int i = valueL - 1; i > colonPos; i--) { - int charValue = HexUtils.DEC[(int) valueB[i + valueS]]; + int charValue = HexUtils.getDec(valueB[i + valueS]); if (charValue == -1) { // Invalid character error = true; Index: connectors/jk/java/org/apache/coyote/ajp/AjpAprProcessor.java =================================================================== --- connectors/jk/java/org/apache/coyote/ajp/AjpAprProcessor.java (revision 1378244) +++ connectors/jk/java/org/apache/coyote/ajp/AjpAprProcessor.java (working copy) @@ -103,7 +103,7 @@ outputBuffer = ByteBuffer.allocateDirect(packetSize * 2); // Cause loading of HexUtils - int foo = HexUtils.DEC[0]; + HexUtils.getDec('0'); // Cause loading of HttpMessages HttpMessages.getMessage(200); @@ -935,7 +935,7 @@ int port = 0; int mult = 1; for (int i = valueL - 1; i > colonPos; i--) { - int charValue = HexUtils.DEC[(int) valueB[i + valueS]]; + int charValue = HexUtils.getDec(valueB[i + valueS]); if (charValue == -1) { // Invalid character error = true; Index: connectors/jk/java/org/apache/jk/common/HandlerRequest.java =================================================================== --- connectors/jk/java/org/apache/jk/common/HandlerRequest.java (revision 1378244) +++ connectors/jk/java/org/apache/jk/common/HandlerRequest.java (working copy) @@ -674,7 +674,7 @@ int port = 0; int mult = 1; for (int i = valueL - 1; i > colonPos; i--) { - int charValue = HexUtils.DEC[(int) valueB[i + valueS]]; + int charValue = HexUtils.getDec(valueB[i + valueS]); if (charValue == -1) { // Invalid character throw new CharConversionException("Invalid char in port: " + valueB[i + valueS]); Index: connectors/util/java/org/apache/tomcat/util/buf/HexUtils.java =================================================================== --- connectors/util/java/org/apache/tomcat/util/buf/HexUtils.java (revision 1378244) +++ connectors/util/java/org/apache/tomcat/util/buf/HexUtils.java (working copy) @@ -36,6 +36,7 @@ /** * Table for HEX to DEC byte translation. + * @deprecated Use {@link #getDec(int)} */ public static final int[] DEC = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -76,6 +77,15 @@ // --------------------------------------------------------- Static Methods + public static int getDec(int index){ + try { + return DEC[index]; + } catch (ArrayIndexOutOfBoundsException ex) { + return -1; + } + } + + /** * Convert a String of hexadecimal digits into the corresponding * byte array by encoding each two hexadecimal digits as a byte. @@ -154,21 +164,21 @@ // assert valid data int len; if(hex.length < 4 ) return 0; - if( DEC[hex[0]]<0 ) + if( getDec(hex[0])<0 ) throw new IllegalArgumentException(sm.getString("hexUtil.bad")); - len = DEC[hex[0]]; + len = getDec(hex[0]); len = len << 4; - if( DEC[hex[1]]<0 ) + if( getDec(hex[1])<0 ) throw new IllegalArgumentException(sm.getString("hexUtil.bad")); - len += DEC[hex[1]]; + len += getDec(hex[1]); len = len << 4; - if( DEC[hex[2]]<0 ) + if( getDec(hex[2])<0 ) throw new IllegalArgumentException(sm.getString("hexUtil.bad")); - len += DEC[hex[2]]; + len += getDec(hex[2]); len = len << 4; - if( DEC[hex[3]]<0 ) + if( getDec(hex[3])<0 ) throw new IllegalArgumentException(sm.getString("hexUtil.bad")); - len += DEC[hex[3]]; + len += getDec(hex[3]); return len; } Index: container/catalina/src/share/org/apache/catalina/util/HexUtils.java =================================================================== --- container/catalina/src/share/org/apache/catalina/util/HexUtils.java (revision 1378244) +++ container/catalina/src/share/org/apache/catalina/util/HexUtils.java (working copy) @@ -30,7 +30,10 @@ public final class HexUtils { // Code from Ajp11, from Apache's JServ - // Table for HEX to DEC byte translation + /** + * Table for HEX to DEC byte translation. + * @deprecated Use {@link #getDec(int)} + */ public static final int[] DEC = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -59,6 +62,18 @@ StringManager.getManager("org.apache.catalina.util"); + // --------------------------------------------------------- Static Methods + + + public static int getDec(int index){ + try { + return DEC[index]; + } catch (ArrayIndexOutOfBoundsException ex) { + return -1; + } + } + + /** * Convert a String of hexadecimal digits into the corresponding * byte array by encoding each two hexadecimal digits as a byte. @@ -137,21 +152,21 @@ // assert valid data int len; if(hex.length < 4 ) return 0; - if( DEC[hex[0]]<0 ) + if( getDec(hex[0])<0 ) throw new IllegalArgumentException(sm.getString("hexUtil.bad")); - len = DEC[hex[0]]; + len = getDec(hex[0]); len = len << 4; - if( DEC[hex[1]]<0 ) + if( getDec(hex[1])<0 ) throw new IllegalArgumentException(sm.getString("hexUtil.bad")); - len += DEC[hex[1]]; + len += getDec(hex[1]); len = len << 4; - if( DEC[hex[2]]<0 ) + if( getDec(hex[2])<0 ) throw new IllegalArgumentException(sm.getString("hexUtil.bad")); - len += DEC[hex[2]]; + len += getDec(hex[2]); len = len << 4; - if( DEC[hex[3]]<0 ) + if( getDec(hex[3])<0 ) throw new IllegalArgumentException(sm.getString("hexUtil.bad")); - len += DEC[hex[3]]; + len += getDec(hex[3]); return len; }