Bug 59912

Summary: CoyoteReader.readLine throws IO exception on multi line POST of exactly 8192 bytes
Product: Tomcat 8 Reporter: Peter Teunissen <Peter.Teunissen>
Component: CatalinaAssignee: Tomcat Developers Mailing List <dev>
Status: RESOLVED FIXED    
Severity: normal CC: Peter.Teunissen
Priority: P2    
Version: 8.0.33   
Target Milestone: ----   
Hardware: PC   
OS: Windows NT   
Attachments: Zip with fiddler trace, servlet Java source, web.xml

Description Peter Teunissen 2016-07-29 19:39:22 UTC
Created attachment 34080 [details]
Zip with fiddler trace, servlet Java source, web.xml

Tomcat 8.0.33 (also fails on 7.0.55)
JDK 1.8.0_66

Wrote a servlet that simply calls readLine() on the HttpServletRequest.getReader() and dumps the incoming lines.

When I do a POST that has at least two lines in the body, with a content-length of exactly 8192 bytes, the last readLine() call throws an IOException.

8191 works fine, 8193 works fine, but 8192 bombs.

java.io.IOException
	at org.apache.catalina.connector.InputBuffer.reset(InputBuffer.java:576)
	at org.apache.catalina.connector.CoyoteReader.reset(CoyoteReader.java:142)
	at org.apache.catalina.connector.CoyoteReader.readLine(CoyoteReader.java:200)
	at com.cerner.TestServlet.service(TestServlet.java:33)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
	at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:522)
	at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1095)
	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:672)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1502)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1458)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:745)

See attached servlet source, fiddler trace file.
Comment 1 Peter Teunissen 2016-07-29 20:14:26 UTC
Seems to be same (similar?) issue as bug 42727
Comment 2 Coty Sutherland 2016-07-29 20:19:42 UTC
Can you provide a data file to use that you can reliably reproduce this with? I tried creating a file of size 8192 (and using the request contents from the fiddler logging), but don't see any issues in 8.0.33 or 8.0.x-dev. I'm testing with the following using your servlet packaged into asf-test.war:

curl -is -X POST --data @test2.dat http://localhost:8080/asf-test/test
Comment 3 Peter Teunissen 2016-07-29 20:46:45 UTC
I tested this by replaying the transaction through fiddler.

When I hit it through CURL, it always posts is such away that in one call to readLine() we get all the data.

When submitted from fiddler, it does the first readLine(), then enters the loop to do additional readLines() and fails on the last:

Content-length:8192
Read-1:109 bytes  magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pret
Read-2:122 bytes ium uis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim
Read-2:124 bytes  justo, rhoncus ut, imperdiet a, venenatis vitae, justo. 

(many Read-2's)

ipsum aliquam libero, non adipiscing dolor urna a orci.
java.io.IOExceptionError caught:null
Size: 7938 Len:27 Request:!!! We had an error!!! null

	at org.apache.catalina.connector.InputBuffer.reset(InputBuffer.java:521)
	at org.apache.catalina.connector.CoyoteReader.reset(CoyoteReader.java:142)


Through CURL with an input file:

$ curl -is -X POST --data @test.log http://localhost:8080/coyrdr/test

Content-length:8192
Read-1:8192 bytes  magnis dis parturient 
--blablabla--
aliquam libero, non adipiscing dolor urna a orci. Nulla porta dolor. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Pelxxl
Reading-2 string=null
Comment 4 Peter Teunissen 2016-07-29 21:02:30 UTC
(In reply to Coty Sutherland from comment #2)
> Can you provide a data file to use that you can reliably reproduce this
> with? I tried creating a file of size 8192 (and using the request contents
> from the fiddler logging), but don't see any issues in 8.0.33 or 8.0.x-dev.
> I'm testing with the following using your servlet packaged into asf-test.war:
> 
> curl -is -X POST --data @test2.dat http://localhost:8080/asf-test/test

Found a way to reproduce with curl using --data-binary and a multi line input file. Keep tweaking the input until the servlet shows exactly Content-Length= 8192.

$ curl -is -X POST --data-binary @test.log http://localhost:8081/coyrdr/test
Comment 5 Mark Thomas 2016-08-10 11:29:47 UTC
Replaying with Fiddler I see the same problem with 9.0.x as well. Investigating...
Comment 6 Mark Thomas 2016-08-10 22:33:51 UTC
Thanks for the report and test case. This has been fixed in the following versions:
9.0.x for 9.0.0.M10 onwards
8.5.x for 8.5.5 onwards
8.0.x for 8.0.37 onwards
7.0.x for 7.0.71 onwards