I have discovered and fixed several bugs in jakarta-tomcat-3.2.3, all in the HttpRequestAdapter.java source file. This same bug existed in version 3.2.2 also. I'm not sure how far back it goes, or whether it also exists in 4.0. The bugs manifest themselves when the URI for the HTTP request(including the request parameter list) exceeds 2048 characters. This prevents Tomcat from being useful for sites which have forms with lots of fields, for example, in which case the sumission of the form could cause a "POST" or "GET" request with a lot of parameters tacked onto the URI. This causes an ArrayIndexOutOfBoundsException due to some errors in src/org/apache/tomcat/service/http/HttpRequestAdapter.java which keep it from properly handling request lines longer than 2048 characters. I have attached the output of "diff -u" for this file, and have tested it with URIs over 12,000 characters in length. There are two methods affected: readNextRequest() and readHeaders(). Please integrate these changes into the next release of jakarta-tomcat, so that everyone can benefit from them. Thanks for the great software!!! Ron Cemer
--- jakarta-tomcat-3.2.3.HOLD/src/org/apache/tomcat/service/http/HttpRequestAdapter.java Tue Jul 17 09:57:50 2001 +++ jakarta-tomcat-3.2.3/src/org/apache/tomcat/service/http/HttpRequestAdapter.java + Wed Sep 19 19:10:05 2001 @@ -126,7 +126,29 @@ // stream - it works for the normal body but also for the HTTP // head. The limit is set after ( and if ) we have a content-length. - count = in.readLine(buf, 0, buf.length); +/// Replaced this line with the code block below to support requests of +/// arbitrary lengths. - Ron Cemer +/// count = in.readLine(buf, 0, buf.length); + count = 0; + while (true) { + int len = buf.length-count; + if (len > 0) { + len = in.readLine(buf, count, len); + if ( (len == -1) && (count == 0) ) { + count = -1; + break; + } + count += len; + if (len == 0 || buf[count-1] == '\n') { + break; + } + } + // overflowed buffer, so temporarily expand and continue + byte[] tmp = new byte[buf.length * 2]; + System.arraycopy(buf, 0, tmp, 0, buf.length); + buf = tmp; + } +/// End of replacement code. if (count < 0 ) { response.setStatus(HttpServletResponse.SC_BAD_REQUEST); @@ -166,19 +188,21 @@ if (len > 0) { len = in.readLine(buf, off, len); - if (len == -1) { String msg = sm1.getString("mimeHeader.connection.ioe"); throw new IOException (msg); } - } +/// } - off += len; +/// This code should be WITHIN the second "while (true)". - Ron Cemer + off += len; - if (len == 0 || buf[off-1] == '\n') { - break; + if (len == 0 || buf[off-1] == '\n') { + break; + } +/// } // overflowed buffer, so temporarily expand and continue @@ -191,8 +215,14 @@ } // strip off trailing "\r\n" - if (--off > start && buf[off-1] == '\r') { - --off; +/// if (--off > start && buf[off-1] == '\r') { +/// --off; +/// } +/// This is a less error-prone way of accomplishing the task. - Ron Cemer + if ( (off > start) && (buf[off-1] == '\n') ) { + off--; + if ( (off > start) && (buf[off-1] == '\r') ) + off--; } if (off == start) {