You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2007/06/13 21:50:24 UTC
svn commit: r547010 - in /jakarta/httpcomponents/httpcore/trunk: ./
module-nio/src/main/java/org/apache/http/impl/nio/
module-nio/src/main/java/org/apache/http/impl/nio/codecs/
module-nio/src/test/java/org/apache/http/impl/nio/codecs/
Author: olegk
Date: Wed Jun 13 12:50:22 2007
New Revision: 547010
URL: http://svn.apache.org/viewvc?view=rev&rev=547010
Log:
HTTPCORE-81: Maximum line length and maximum header counts parameters are now correctly enforced in both base and NIO modules
Contributed by Steffen Pingel <spingel at limewire.com>
Reviewed by Oleg Kalnichevski
Modified:
jakarta/httpcomponents/httpcore/trunk/RELEASE_NOTES.txt
jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/DefaultNHttpClientConnection.java
jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/DefaultNHttpServerConnection.java
jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/codecs/HttpMessageParser.java
jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/codecs/HttpRequestParser.java
jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/codecs/HttpResponseParser.java
jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/impl/nio/codecs/TestHttpMessageParser.java
Modified: jakarta/httpcomponents/httpcore/trunk/RELEASE_NOTES.txt
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/RELEASE_NOTES.txt?view=diff&rev=547010&r1=547009&r2=547010
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/RELEASE_NOTES.txt (original)
+++ jakarta/httpcomponents/httpcore/trunk/RELEASE_NOTES.txt Wed Jun 13 12:50:22 2007
@@ -1,5 +1,9 @@
Changes since 4.0 Alpha 4
+* [HTTPCORE-81]: Maximum line length and maximum header counts parameters are now
+ correctly enforced in both base and NIO modules.
+ Contributed by Steffen Pingel <spingel at limewire.com>
+
* Added HTTP client handler implementation that allocates fixed size content
buffers upon initialization and is capable of throttling the rate of I/O events
in order to make sure those content buffers do not get overflown.
Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/DefaultNHttpClientConnection.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/DefaultNHttpClientConnection.java?view=diff&rev=547010&r1=547009&r2=547010
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/DefaultNHttpClientConnection.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/DefaultNHttpClientConnection.java Wed Jun 13 12:50:22 2007
@@ -50,6 +50,7 @@
import org.apache.http.nio.reactor.EventMask;
import org.apache.http.nio.reactor.IOSession;
import org.apache.http.nio.util.ByteBufferAllocator;
+import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
public class DefaultNHttpClientConnection
@@ -66,7 +67,11 @@
if (responseFactory == null) {
throw new IllegalArgumentException("Response factory may not be null");
}
- this.responseParser = new HttpResponseParser(this.inbuf, responseFactory);
+ this.responseParser = new HttpResponseParser(
+ this.inbuf,
+ params.getIntParameter(HttpConnectionParams.MAX_LINE_LENGTH, -1),
+ params.getIntParameter(HttpConnectionParams.MAX_HEADER_COUNT, -1),
+ responseFactory);
this.hasBufferedInput = false;
this.hasBufferedOutput = false;
this.session.setBufferStatus(this);
Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/DefaultNHttpServerConnection.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/DefaultNHttpServerConnection.java?view=diff&rev=547010&r1=547009&r2=547010
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/DefaultNHttpServerConnection.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/DefaultNHttpServerConnection.java Wed Jun 13 12:50:22 2007
@@ -50,6 +50,7 @@
import org.apache.http.nio.reactor.EventMask;
import org.apache.http.nio.reactor.IOSession;
import org.apache.http.nio.util.ByteBufferAllocator;
+import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
public class DefaultNHttpServerConnection
@@ -66,7 +67,11 @@
if (requestFactory == null) {
throw new IllegalArgumentException("Request factory may not be null");
}
- this.requestParser = new HttpRequestParser(this.inbuf, requestFactory);
+ this.requestParser = new HttpRequestParser(
+ this.inbuf,
+ params.getIntParameter(HttpConnectionParams.MAX_LINE_LENGTH, -1),
+ params.getIntParameter(HttpConnectionParams.MAX_HEADER_COUNT, -1),
+ requestFactory);
}
public void resetInput() {
Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/codecs/HttpMessageParser.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/codecs/HttpMessageParser.java?view=diff&rev=547010&r1=547009&r2=547010
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/codecs/HttpMessageParser.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/codecs/HttpMessageParser.java Wed Jun 13 12:50:22 2007
@@ -58,7 +58,10 @@
private CharArrayBuffer lineBuf;
private final List headerBufs;
- public HttpMessageParser(final SessionInputBuffer buffer) {
+ private int maxLineLen;
+ private int maxHeaderCount;
+
+ public HttpMessageParser(final SessionInputBuffer buffer, int maxLineLen, int maxHeaderCount) {
super();
if (buffer == null) {
throw new IllegalArgumentException("Session input buffer may not be null");
@@ -67,6 +70,8 @@
this.state = READ_HEAD_LINE;
this.endOfStream = false;
this.headerBufs = new ArrayList();
+ this.maxLineLen = maxLineLen;
+ this.maxHeaderCount = maxHeaderCount;
}
public void reset() {
@@ -91,7 +96,7 @@
this.message = createMessage(this.lineBuf);
}
- private void parseHeader() {
+ private void parseHeader() throws IOException {
CharArrayBuffer current = this.lineBuf;
int count = this.headerBufs.size();
if ((this.lineBuf.charAt(0) == ' ' || this.lineBuf.charAt(0) == '\t') && count > 0) {
@@ -105,6 +110,9 @@
}
i++;
}
+ if (this.maxLineLen > 0 && previous.length() + 1 + current.length() - i > this.maxLineLen) {
+ throw new IOException("Maximum line length limit exceeded");
+ }
previous.append(' ');
previous.append(current, i, current.length() - i);
} else {
@@ -120,9 +128,14 @@
} else {
this.lineBuf.clear();
}
- if (!this.buffer.readLine(this.lineBuf, this.endOfStream)) {
+ boolean lineComplete = this.buffer.readLine(this.lineBuf, this.endOfStream);
+ if (this.maxLineLen > 0 && this.lineBuf.length() > this.maxLineLen) {
+ throw new IOException("Maximum line length limit exceeded");
+ }
+ if (!lineComplete) {
break;
}
+
switch (this.state) {
case READ_HEAD_LINE:
parseHeadLine();
@@ -130,6 +143,10 @@
break;
case READ_HEADERS:
if (this.lineBuf.length() > 0) {
+ if (this.maxHeaderCount > 0 && headerBufs.size() >= this.maxHeaderCount) {
+ throw new IOException("Maximum header count exceeded");
+ }
+
parseHeader();
} else {
this.state = COMPLETED;
Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/codecs/HttpRequestParser.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/codecs/HttpRequestParser.java?view=diff&rev=547010&r1=547009&r2=547010
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/codecs/HttpRequestParser.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/codecs/HttpRequestParser.java Wed Jun 13 12:50:22 2007
@@ -45,12 +45,20 @@
public HttpRequestParser(
final SessionInputBuffer buffer,
+ int maxLineLen,
+ int maxHeaderCount,
final HttpRequestFactory requestFactory) {
- super(buffer);
+ super(buffer, maxLineLen, maxHeaderCount);
if (requestFactory == null) {
throw new IllegalArgumentException("Request factory may not be null");
}
this.requestFactory = requestFactory;
+ }
+
+ public HttpRequestParser(
+ final SessionInputBuffer buffer,
+ final HttpRequestFactory requestFactory) {
+ this(buffer, -1, -1, requestFactory);
}
protected HttpMessage createMessage(final CharArrayBuffer buffer)
Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/codecs/HttpResponseParser.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/codecs/HttpResponseParser.java?view=diff&rev=547010&r1=547009&r2=547010
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/codecs/HttpResponseParser.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/impl/nio/codecs/HttpResponseParser.java Wed Jun 13 12:50:22 2007
@@ -45,12 +45,20 @@
public HttpResponseParser(
final SessionInputBuffer buffer,
+ int maxLineLen,
+ int maxHeaderCount,
final HttpResponseFactory responseFactory) {
- super(buffer);
+ super(buffer, maxLineLen, maxHeaderCount);
if (responseFactory == null) {
throw new IllegalArgumentException("Response factory may not be null");
}
this.responseFactory = responseFactory;
+ }
+
+ public HttpResponseParser(
+ final SessionInputBuffer buffer,
+ final HttpResponseFactory responseFactory) {
+ this(buffer, -1, -1, responseFactory);
}
protected HttpMessage createMessage(final CharArrayBuffer buffer)
Modified: jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/impl/nio/codecs/TestHttpMessageParser.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/impl/nio/codecs/TestHttpMessageParser.java?view=diff&rev=547010&r1=547009&r2=547010
==============================================================================
--- jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/impl/nio/codecs/TestHttpMessageParser.java (original)
+++ jakarta/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/impl/nio/codecs/TestHttpMessageParser.java Wed Jun 13 12:50:22 2007
@@ -31,6 +31,7 @@
package org.apache.http.impl.nio.codecs;
import java.io.ByteArrayInputStream;
+import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
@@ -46,8 +47,6 @@
import org.apache.http.HttpVersion;
import org.apache.http.impl.DefaultHttpRequestFactory;
import org.apache.http.impl.DefaultHttpResponseFactory;
-import org.apache.http.impl.nio.codecs.HttpMessageParser;
-import org.apache.http.impl.nio.codecs.HttpRequestParser;
import org.apache.http.impl.nio.reactor.SessionInputBuffer;
/**
@@ -320,6 +319,75 @@
fail("IllegalArgumentException should have been thrown");
} catch (IllegalArgumentException ex) {
// ignore
+ }
+ }
+
+ public void testLineLimitForStatus() throws Exception {
+ SessionInputBuffer inbuf = new SessionInputBuffer(1024, 128);
+ HttpRequestFactory requestFactory = new DefaultHttpRequestFactory();
+ HttpRequestParser requestParser = new HttpRequestParser(inbuf, 0, -1, requestFactory);
+
+ requestParser.fillBuffer(newChannel("GET /whatever HTTP/1.0\r\nHeader: one\r\n\r\n"));
+ requestParser.parse();
+ requestParser.reset();
+
+ requestParser = new HttpRequestParser(inbuf, 15, -1, requestFactory);
+ try {
+ requestParser.fillBuffer(newChannel("GET /loooooooooooooooong HTTP/1.0\r\nHeader: one\r\n\r\n"));
+ requestParser.parse();
+ fail("IOException should have been thrown");
+ } catch (IOException expected) {
+ }
+ }
+
+ public void testLineLimitForHeader() throws Exception {
+ SessionInputBuffer inbuf = new SessionInputBuffer(1024, 128);
+ HttpRequestFactory requestFactory = new DefaultHttpRequestFactory();
+ HttpRequestParser requestParser = new HttpRequestParser(inbuf, 0, -1, requestFactory);
+
+ requestParser.fillBuffer(newChannel("GET /whatever HTTP/1.0\r\nHeader: one\r\n\r\n"));
+ requestParser.parse();
+ requestParser.reset();
+
+ requestParser = new HttpRequestParser(inbuf, 15, -1, requestFactory);
+ requestParser.fillBuffer(newChannel("GET / HTTP/1.0\r\nHeader: 9012345\r\n\r\n"));
+ requestParser.parse();
+ requestParser.reset();
+ try {
+ requestParser.fillBuffer(newChannel("GET / HTTP/1.0\r\nHeader: 90123456\r\n\r\n"));
+ requestParser.parse();
+ fail("IOException should have been thrown");
+ } catch (IOException expected) {
+ }
+ }
+
+ public void testLineLimitForFoldedHeader() throws Exception {
+ SessionInputBuffer inbuf = new SessionInputBuffer(1024, 128);
+ HttpRequestFactory requestFactory = new DefaultHttpRequestFactory();
+ HttpRequestParser requestParser = new HttpRequestParser(inbuf, 15, 2, requestFactory);
+
+ try {
+ requestParser.fillBuffer(newChannel("GET / HTTP/1.0\r\nHeader: 9012345\r\n 23456789012345\r\n 23456789012345\r\n 23456789012345\r\n\r\n"));
+ requestParser.parse();
+ fail("IOException should have been thrown");
+ } catch (IOException expected) {
+ }
+ }
+
+ public void testMaxHeaderCount() throws Exception {
+ SessionInputBuffer inbuf = new SessionInputBuffer(1024, 128);
+ HttpRequestFactory requestFactory = new DefaultHttpRequestFactory();
+ HttpRequestParser requestParser = new HttpRequestParser(inbuf, -1, 2, requestFactory);
+
+ requestParser.fillBuffer(newChannel("GET /whatever HTTP/1.0\r\nHeader: one\r\nHeader: two\r\n\r\n"));
+ requestParser.parse();
+ requestParser.reset();
+
+ try {
+ requestParser.fillBuffer(newChannel("GET /whatever HTTP/1.0\r\nHeader: one\r\nHeader: two\r\nHeader: three\r\n\r\n"));
+ requestParser.parse();
+ fail("IOException should have been thrown");
+ } catch (IOException expected) {
}
}