You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by bu...@apache.org on 2005/05/05 20:52:26 UTC
DO NOT REPLY [Bug 34769] New: -
ArrayIndexOutOfBoundsException occurs when reading more than 8192 bytes from the BufferedReader supplied by HttpServletRequest.getReader()
DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG�
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://issues.apache.org/bugzilla/show_bug.cgi?id=34769>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND�
INSERTED IN THE BUG DATABASE.
http://issues.apache.org/bugzilla/show_bug.cgi?id=34769
Summary: ArrayIndexOutOfBoundsException occurs when reading more
than 8192 bytes from the BufferedReader supplied by
HttpServletRequest.getReader()
Product: Tomcat 5
Version: 5.5.4
Platform: PC
OS/Version: Windows XP
Status: NEW
Severity: normal
Priority: P3
Component: Catalina:Modules
AssignedTo: tomcat-dev@jakarta.apache.org
ReportedBy: gdavis@spicer.com
Well...I can supply quite a bit of info, but I can't say you'll have an easy
time reproducing the problem.
First off, let me provide you with the exception that we experienced.
java.lang.ArrayIndexOutOfBoundsException
at java.lang.System.arraycopy(Native Method)
at org.apache.tomcat.util.buf.CharChunk.append(CharChunk.java:298)
at org.apache.tomcat.util.buf.B2CConverter.convert
(B2CConverter.java:97)
at org.apache.tomcat.util.buf.B2CConverter.convert
(B2CConverter.java:76)
at org.apache.catalina.connector.InputBuffer.realReadChars
(InputBuffer.java:339)
at org.apache.tomcat.util.buf.CharChunk.substract(CharChunk.java:384)
at org.apache.catalina.connector.InputBuffer.read(InputBuffer.java:350)
at org.apache.catalina.connector.CoyoteReader.read
(CoyoteReader.java:80)
at com.spicer.jdl.MatrixXMLSerializable.decodeMime64
(MatrixXMLSerializable.java:142)
at com.spicer.jdl.MatrixXMLSerializable.parseMime64
(MatrixXMLSerializable.java:523)
at com.spicer.jdl.MatrixXMLSerializable.decodeByteArrayRaw
(MatrixXMLSerializable.java:710)
at com.spicer.jdl.MatrixXMLSerializable.decodeByteArray
(MatrixXMLSerializable.java:641)
at com.spicer.jdl.MatrixXMLDispatch.dispatch_ClientWrapperServer
(MatrixXMLDispatch.java:109)
at com.spicer.jdl.MatrixXMLDispatch.dispatch(MatrixXMLDispatch.java:62)
at com.spicer.servlet.MatrixXMLServlet.doPost(Unknown Source)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:709)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter
(ApplicationFilterChain.java:237)
at org.apache.catalina.core.ApplicationFilterChain.doFilter
(ApplicationFilterChain.java:157)
at org.apache.catalina.core.StandardWrapperValve.invoke
(StandardWrapperValve.java:214)
at org.apache.catalina.core.StandardContextValve.invoke
(StandardContextValve.java:178)
at org.apache.catalina.core.StandardHostValve.invoke
(StandardHostValve.java:126)
at org.apache.catalina.valves.ErrorReportValve.invoke
(ErrorReportValve.java:105)
at org.apache.catalina.core.StandardEngineValve.invoke
(StandardEngineValve.java:107)
at org.apache.catalina.connector.CoyoteAdapter.service
(CoyoteAdapter.java:148)
at org.apache.coyote.http11.Http11Processor.process
(Http11Processor.java:825)
at
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnecti
on(Http11Protocol.java:731)
at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket
(PoolTcpEndpoint.java:526)
at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt
(LeaderFollowerWorkerThread.java:80)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run
(ThreadPool.java:684)
at java.lang.Thread.run(Thread.java:595)
This exception occurred in Tomcat 5.5.4 whenever we had a larger post to the
servlet.
We have a java based client-server product that uses a servlet when being
deployed for internet use. Essentially, the client converts the calls into an
XML stream which it posts to the servlet (called MatrixXMLServlet) that then
converts the data back into an RMI call for the server portion of the product.
This servlet has been in use, unchanged, for nearly 4 years and hasn't caused
an error until now. It works fine with versions of Tomcat before 5.0, but
doesn't with 5.5 (I'm not 100% sure about 5.0 so I'll leave it out).
Using the FAQ as a guide, I searched for solutions and/or others with the same
problem, but was unable to find anything. So, I traced through the Tomcat
source code to see if I could understand the problem...and I'm convinced (with
little doubt) that there is a Tomcat bug...but I'm not sure what causes the
classes to be set up this way. So...I'll describe what I found...maybe it
will help.
First of all, the doPost() in MatrixXMLServlet does a getReader() on the
HttpServletRequest it is passed, and this reader is then set in the
MatrixXMLSerializable object. Then, in the decodeMime64() method, we loop
reading one character at a time from the BufferedReader (as supplied by
getReader()) and process it until we exhaust the stream. But, on larger posts
(I think those greater than 8192 characters), we get the exception listed
above when trying to read that single character.
Now, in this case, the BufferedReader supplied is a CoyoteReader which in turn
has an InputBuffer, which in turn has a CharChunk, a ByteChunk, and a
B2CConverter. For a read, the CoyoteReader does a read on InputBuffer, which
then asks CharChunk for the character. The CharChunk returns the next
character that it has in its buffer, but if it has reached the end of what is
available it asks InputBuffer for x more characters (where x is the amount of
space left in its buffer).
Now...here is the problem number 1 ...rather than providing the CharChunk with
at most x characters (or resetting the CharChunk if x=0), the InputBuffer asks
B2CConverter to transfer everything that ByteChunk has in its buffer (and then
refills ByteChunk).
So...if there is not enough space left in the CharChunk buffer to add this
much data, it tries to accomodate by filling to the limit with what will fit,
flushing the buffer and then adding the remainder. But, this leads to the
problem we see, because of what the flush actually does (or more
precisely "doesn't do"). Essentially, in our case, the start and end pointers
are at the same place (which is why CharChunk asks for more data in the first
place) and so after filling to the end of the buffer, the flush actually does
nothing (except set a flag in the InputBuffer) and then trying to add the rest
of the data into the buffer causes it to go past the end of the buffer and
generates our exception. That is problem number 2.
BUT...if this 2nd insert into the CharChunk buffer doesn't cause the exception
we have, then you've lost the data from the 1st insert, because it has been
overwritten by the 2nd insert...thus losing data out of the input stream.
Okay...this is problem number 3.
One possible solution would be to allow the buffer in CharChunk to "wrap"
around the end...but then you have to be careful that you don't add more to
the start of the buffer than can fit, or you have another case of losing data
from the overlap of the 1st insert and the 2nd insert.
And...you can't simply reset the start pointer (in CharChunk) upon a flush,
because then you'd loose all the data from the 1st insert again...and that's a
no-no.
I think the whole thing needs to be examined a little more carefully.
I suspect that solving problem 1 (and also providing a way to "reset" the
CharChunk...perhaps when it requests x=0 more characters) would make the whole
thing work as desired.
Anyway...we have changed our code in MatrixXMLServlet so that instead of using
getReader(), we use getInputStream()...and using
HttpServletRequest.getCharacterEncoding(), we wrap the input stream inside an
InputStreamReader, and then wrap that inside a BufferedReader.
Thus, using this alternative way to read the inputstream eliminates the
problem for us.
Now...to post this bug, I tried to reproduce the problem with a small, and
simple, servlet that simply used the getReader() call and then consumed the
input stream one character at a time...and then generating sufficiently large
posts to exceed the 8K size. But, the problem didn't occur.
So...I don't know what must happen to exactly cause the setup we see inside
the CoyoteReader. We have a working solution now, and I can't afford anymore
time tracing and debugging Tomcat code...so I hope this is of some help to you.
If you have questions, feel free to ask and I'll answer to the best of my
knowledge.
Thanks.
Greg
--
Configure bugmail: http://issues.apache.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug, or are watching the assignee.
---------------------------------------------------------------------
To unsubscribe, e-mail: tomcat-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tomcat-dev-help@jakarta.apache.org