Index: module-nio/src/test/java/org/apache/http/impl/nio/codecs/TestHttpMessageParser.java =================================================================== --- module-nio/src/test/java/org/apache/http/impl/nio/codecs/TestHttpMessageParser.java (revision 546168) +++ module-nio/src/test/java/org/apache/http/impl/nio/codecs/TestHttpMessageParser.java (working copy) @@ -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,9 +47,10 @@ 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; +import org.apache.http.params.BasicHttpParams; +import org.apache.http.params.HttpConnectionParams; +import org.apache.http.params.HttpParams; /** * Simple tests for {@link HttpMessageParser}. @@ -323,4 +325,72 @@ } } + public void testLineLimitStatus() throws Exception { + HttpParams params = new BasicHttpParams(); + SessionInputBuffer inbuf = new SessionInputBuffer(1024, 128); + HttpRequestFactory requestFactory = new DefaultHttpRequestFactory(); + HttpRequestParser requestParser = new HttpRequestParser(inbuf, requestFactory); + + params.setIntParameter(HttpConnectionParams.MAX_LINE_LENGTH, 0); + requestParser.reset(params); + requestParser.fillBuffer(newChannel("GET /whatever HTTP/1.0\r\nHeader: one\r\n\r\n")); + requestParser.parse(); + requestParser.reset(); + + params.setIntParameter(HttpConnectionParams.MAX_LINE_LENGTH, 15); + requestParser.reset(params); + 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 testLineLimitHeader() throws Exception { + HttpParams params = new BasicHttpParams(); + SessionInputBuffer inbuf = new SessionInputBuffer(1024, 128); + HttpRequestFactory requestFactory = new DefaultHttpRequestFactory(); + HttpRequestParser requestParser = new HttpRequestParser(inbuf, requestFactory); + + params.setIntParameter(HttpConnectionParams.MAX_LINE_LENGTH, 0); + requestParser.reset(params); + requestParser.fillBuffer(newChannel("GET /whatever HTTP/1.0\r\nHeader: one\r\n\r\n")); + requestParser.parse(); + requestParser.reset(); + + params.setIntParameter(HttpConnectionParams.MAX_LINE_LENGTH, 15); + requestParser.reset(params); + 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 testHeaderLimit() throws Exception { + HttpParams params = new BasicHttpParams(); + SessionInputBuffer inbuf = new SessionInputBuffer(1024, 128); + HttpRequestFactory requestFactory = new DefaultHttpRequestFactory(); + HttpRequestParser requestParser = new HttpRequestParser(inbuf, requestFactory); + + params.setIntParameter(HttpConnectionParams.MAX_HEADER_COUNT, 2); + requestParser.reset(params); + + 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) { + } + } + } Index: module-nio/src/main/java/org/apache/http/impl/nio/codecs/HttpMessageParser.java =================================================================== --- module-nio/src/main/java/org/apache/http/impl/nio/codecs/HttpMessageParser.java (revision 546168) +++ module-nio/src/main/java/org/apache/http/impl/nio/codecs/HttpMessageParser.java (working copy) @@ -40,6 +40,8 @@ import org.apache.http.HttpMessage; import org.apache.http.ProtocolException; import org.apache.http.message.BufferedHeader; +import org.apache.http.params.HttpConnectionParams; +import org.apache.http.params.HttpParams; import org.apache.http.impl.nio.reactor.SessionInputBuffer; import org.apache.http.util.CharArrayBuffer; @@ -58,6 +60,10 @@ private CharArrayBuffer lineBuf; private final List headerBufs; + private int maxLineLen; + + private int maxHeaderCount; + public HttpMessageParser(final SessionInputBuffer buffer) { super(); if (buffer == null) { @@ -76,6 +82,11 @@ this.message = null; } + public void reset(final HttpParams params) { + this.maxLineLen = params.getIntParameter(HttpConnectionParams.MAX_LINE_LENGTH, -1); + this.maxHeaderCount = params.getIntParameter(HttpConnectionParams.MAX_HEADER_COUNT, -1); + } + public int fillBuffer(final ReadableByteChannel channel) throws IOException { int bytesRead = this.buffer.fill(channel); if (bytesRead == -1) { @@ -120,9 +131,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 +146,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; Index: module-nio/src/main/java/org/apache/http/impl/nio/DefaultNHttpClientConnection.java =================================================================== --- module-nio/src/main/java/org/apache/http/impl/nio/DefaultNHttpClientConnection.java (revision 546168) +++ module-nio/src/main/java/org/apache/http/impl/nio/DefaultNHttpClientConnection.java (working copy) @@ -67,6 +67,7 @@ throw new IllegalArgumentException("Response factory may not be null"); } this.responseParser = new HttpResponseParser(this.inbuf, responseFactory); + this.responseParser.reset(params); this.hasBufferedInput = false; this.hasBufferedOutput = false; this.session.setBufferStatus(this); Index: module-nio/src/main/java/org/apache/http/impl/nio/DefaultNHttpServerConnection.java =================================================================== --- module-nio/src/main/java/org/apache/http/impl/nio/DefaultNHttpServerConnection.java (revision 546168) +++ module-nio/src/main/java/org/apache/http/impl/nio/DefaultNHttpServerConnection.java (working copy) @@ -67,6 +67,7 @@ throw new IllegalArgumentException("Request factory may not be null"); } this.requestParser = new HttpRequestParser(this.inbuf, requestFactory); + this.requestParser.reset(params); } public void resetInput() {