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; }