Index: org/apache/commons/httpclient/HttpMethodBase.java
===================================================================
RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMethodBase.java,v
retrieving revision 1.194
diff -u -r1.194 HttpMethodBase.java
--- org/apache/commons/httpclient/HttpMethodBase.java 11 Dec 2003 22:54:18 -0000 1.194
+++ org/apache/commons/httpclient/HttpMethodBase.java 12 Dec 2003 10:59:23 -0000
@@ -1715,8 +1715,19 @@
LOG.trace("enter HttpMethodBase.readResponseHeaders(HttpState,"
+ "HttpConnection)");
+ final int headerLineLimit = getParams().
+ getIntParameter(HttpMethodParams.HTTP_HEADER_LINE_LIMIT, 4096);
+ final int headerLimit = getParams().
+ getIntParameter(HttpMethodParams.HTTP_HEADER_LIMIT, 1000);
+ final int headerValueLimit = getParams().
+ getIntParameter(HttpMethodParams.HTTP_HEADER_VALUE_LIMIT, 4096);
+
getResponseHeaderGroup().clear();
- Header[] headers = HttpParser.parseHeaders(conn.getResponseInputStream());
+ Header[] headers =
+ HttpParser.parseHeaders(
+ conn.getResponseInputStream(),
+ headerLineLimit, headerLimit, headerValueLimit);
+
if (Wire.enabled()) {
for (int i = 0; i < headers.length; i++) {
Wire.input(headers[i].toExternalForm());
Index: org/apache/commons/httpclient/HttpParser.java
===================================================================
RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpParser.java,v
retrieving revision 1.8
diff -u -r1.8 HttpParser.java
--- org/apache/commons/httpclient/HttpParser.java 15 Jul 2003 02:19:58 -0000 1.8
+++ org/apache/commons/httpclient/HttpParser.java 12 Dec 2003 10:59:23 -0000
@@ -76,6 +76,7 @@
*
* @author Michael Becke
* @author Oleg Kalnichevski
+ * @author Christian Kohlschuetter
*
* @since 2.0beta1
*/
@@ -102,15 +103,36 @@
* @return a byte array from the stream
*/
public static byte[] readRawLine(InputStream inputStream) throws IOException {
+ return readRawLine(inputStream, Integer.MAX_VALUE);
+ }
+
+ /**
+ * Return byte array from an (unchunked) input stream.
+ * Stop reading when "\n" terminator encountered
+ * or if the number of bytes read exceeds maxLen.
+ *
+ * @param inputStream the stream to read from
+ * @param the maximum number of bytes before "\n"
+ *
+ * @throws IOException if an I/O problem occurs
+ * @return a byte array from the stream
+ * @see #readRawLine(InputStream)
+ */
+ public static byte[] readRawLine(InputStream inputStream, int maxLen) throws IOException {
LOG.trace("enter HttpParser.readRawLine()");
ByteArrayOutputStream buf = new ByteArrayOutputStream();
int ch;
+ int n = 0;
while ((ch = inputStream.read()) >= 0) {
buf.write(ch);
+ n++;
if (ch == '\n') {
break;
}
+ if(n > maxLen) {
+ throw new HttpException("Line too long (> "+maxLen+" bytes)");
+ }
}
if (buf.size() == 0) {
return null;
@@ -129,10 +151,24 @@
* @throws IOException if an I/O problem occurs
* @return a line from the stream
*/
-
public static String readLine(InputStream inputStream) throws IOException {
+ return readLine(inputStream, Integer.MAX_VALUE);
+ }
+
+ /**
+ * Read up to "\n" and up to maxLen bytes
+ * from an (unchunked) input stream.
+ *
+ * @param inputStream the stream to read from
+ * @param the maximum number of bytes before "\n"
+ *
+ * @throws IOException if an I/O problem occurs
+ * @return a line from the stream
+ * @see #readLine(InputStream)
+ */
+ public static String readLine(InputStream inputStream, int maxLen) throws IOException {
LOG.trace("enter HttpParser.readLine()");
- byte[] rawdata = readRawLine(inputStream);
+ byte[] rawdata = readRawLine(inputStream, maxLen);
if (rawdata == null) {
return null;
}
@@ -155,6 +191,12 @@
* Parses headers from the given stream. Headers with the same name are not
* combined.
*
+ * The maximum line length is 4096 bytes/8-bit-characters.
+ * The maximum number of headers is 1000.
+ * The maximum header value length is 4096 characters.
+ *
+ * A HttpException is thrown if at least one of these limits is exceeded.
+ *
* @param is the stream to read headers from
*
* @return an array of headers in the order in which they were parsed
@@ -163,13 +205,43 @@
* @throws HttpException if there is an error parsing a header value
*/
public static Header[] parseHeaders(InputStream is) throws IOException, HttpException {
+ return parseHeaders(is, 4096, 1000, 4096);
+ }
+
+ /**
+ * Parses headers from the given stream. Headers with the same name are not
+ * combined, permitting a specific maximum line length, number of headers
+ * and header value length.
+ *
+ * A HttpException is thrown if at least one of the specified limits
+ * is exceeded.
+ *
+ * @param is the stream to read headers from
+ * @param maxLineLen Maximum line length (in bytes/8-bit characters)
+ * @param maxHeaders Maximum number of headers
+ * @param maxHeaderValueLength Maximum length of header values (in characters)
+ *
+ * @return an array of headers in the order in which they were parsed
+ *
+ * @throws IOException if an IO error occurs while reading from the stream
+ * @throws HttpException if there is an error parsing a header value
+ */
+ public static Header[] parseHeaders(
+ InputStream is,
+ int maxLineLen,
+ int maxHeaders,
+ int maxHeaderValueLength)
+ throws IOException, HttpException {
LOG.trace("enter HeaderParser.parseHeaders(HttpConnection, HeaderGroup)");
ArrayList headers = new ArrayList();
String name = null;
StringBuffer value = null;
for (; ;) {
- String line = HttpParser.readLine(is);
+ if(headers.size() > maxHeaders) {
+ throw new HttpException("Too many headers (> "+maxHeaders+")");
+ }
+ String line = HttpParser.readLine(is, maxLineLen);
if ((line == null) || (line.length() < 1)) {
break;
}
@@ -184,6 +256,9 @@
if (value != null) {
value.append(' ');
value.append(line.trim());
+ if(value.length() > maxHeaderValueLength) {
+ throw new HttpException("Header value too long (> "+maxHeaderValueLength+")");
+ }
}
} else {
// make sure we save the previous name,value pair if present
@@ -199,6 +274,9 @@
}
name = line.substring(0, colon).trim();
value = new StringBuffer(line.substring(colon + 1).trim());
+ if(value.length() > maxHeaderValueLength) {
+ throw new HttpException("Header value too long (> "+maxHeaderValueLength+")");
+ }
}
}
@@ -206,6 +284,9 @@
// make sure we save the last name,value pair if present
if (name != null) {
headers.add(new Header(name, value.toString()));
+ if(headers.size() > maxHeaders) {
+ throw new HttpException("Too many headers (> "+maxHeaders+")");
+ }
}
return (Header[]) headers.toArray(new Header[headers.size()]);
Index: org/apache/commons/httpclient/params/HttpMethodParams.java
===================================================================
RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/params/HttpMethodParams.java,v
retrieving revision 1.7
diff -u -r1.7 HttpMethodParams.java
--- org/apache/commons/httpclient/params/HttpMethodParams.java 11 Dec 2003 22:54:19 -0000 1.7
+++ org/apache/commons/httpclient/params/HttpMethodParams.java 12 Dec 2003 10:59:23 -0000
@@ -242,6 +242,46 @@
* This parameter expects a value of type {@link Integer}.
*/
public static final String STATUS_LINE_GARBAGE_LIMIT = "http.protocol.status-line-garbage-limit";
+
+ /**
+ * Defines the maximum length (in bytes) of a line which is part of a HTTP header.
+ *
+ * If the HTTP Header is folded into several lines, this parameter controls + * the maximum length for every single line. + *
+ * This parameter should be set to a reasonable value (4096 by default).
+ * Set this to Integer.MAX_VALUE to allow any arbitrary header
+ * length.
+ *
+ * This parameter should be set to a reasonable value (1000 by default).
+ * Set this to Integer.MAX_VALUE to allow any arbitrary number
+ * of headers.
+ *
+ * This parameter should be set to a reasonable value (4096 by default).
+ * Set this to Integer.MAX_VALUE to allow any arbitrary number
+ * of headers.
+ *