https://issues.apache.org/bugzilla/show_bug.cgi?id=53119
Bug #: 53119 Summary: java.nio.BufferOverflowException in AjpAprProcessor.output() when AJP client disconnects Product: Tomcat 7 Version: 7.0.26 Platform: PC Status: NEW Severity: minor Priority: P2 Component: Connectors AssignedTo: dev@tomcat.apache.org ReportedBy: prei...@web.de Classification: Unclassified As reported on the users list [2] (note that I used Tomcat 7.0.27, but Bugzilla seems to have only 7.0.26): Hi all, some time ago, I wrote about a BufferOverflowException which I got sporadically on my Tomcat 7.0.21 [1], when using the AJP-APR-Connector. However, at that time I couldn't reproduce the exception. When I looked at this again today, I was able to create a client that sends an AJP message and aborts the connection, resulting in the BufferOverflowException in Tomcat. I was using Tomcat 7.0.27 with Tomcat Native 1.1.23, on Oracle JDK 1.7.0_03 and Windows 7 32-bit. To reproduce, 1. On the server side, create a web application containing a servlet which will generate some random data: @WebServlet("/index.html") public class MyTestServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { response.setContentType("text/plain"); response.setCharacterEncoding("utf-8"); byte[] bytesToWrite = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57}; // Try to write 1,000,000 bytes to the client. try (OutputStream out = response.getOutputStream()) { for (int i = 0; i < 100000; i++) { out.write(bytesToWrite); } } } catch (IOException ex) { // Ignore } } } Deploy the application as ROOT, so that the servlet will be reachable at "/". Configure Tomcat to have an AJP-APR connector listening on port 8009. 2. On the client side, create a program like this: public class AjpTester { public static void main(String[] args) throws IOException { byte[] ajpPacketBytes = { // JK_AJP13_FORWARD_REQUEST for "/" 0x12, 0x34, 0x00, 0x54, 0x02, 0x02, 0x00, 0x08, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, 0x00, 0x00, 0x01, 0x2f, 0x00, 0x00, 0x07, 0x31, 0x2e, 0x32, 0x2e, 0x33, 0x2e, 0x34, 0x00, 0x00, 0x07, 0x31, 0x2e, 0x32, 0x2e, 0x33, 0x2e, 0x34, 0x00, 0x00, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x00, 0x00, 0x50, 0x00, 0x00, 0x02, (byte)0xa0, 0x06, 0x00, 0x0a, 0x4b, 0x65, 0x65, 0x70, 0x2d, 0x41, 0x6c, 0x69, 0x76, 0x65, 0x00, (byte)0xa0, 0x0b, 0x00, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x00, (byte)0xff }; Socket s = new Socket("localhost", 8009); // connect to AJP port OutputStream sout = s.getOutputStream(); InputStream sin = s.getInputStream(); sout.write(ajpPacketBytes); // request Url "/" // Read between 10,000 and 11,023 bytes, then exit the JVM byte[] buf = new byte[1024]; int read; int bytesRead = 0; while ((read = sin.read(buf)) > 0) { bytesRead += read; if (bytesRead >= 10000) { System.exit(1); } } } } The client will send an JK_AJP13_FORWARD_REQUEST message which requests URL "/" and sends "Connection: keep-alive" and "Host: localhost" headers. 3. Tomcat will display this exception: Apr 20, 2012 10:57:08 PM org.apache.coyote.ajp.AjpAprProcessor process Schwerwiegend: Error processing request java.nio.BufferOverflowException at java.nio.DirectByteBuffer.put(DirectByteBuffer.java:357) at org.apache.coyote.ajp.AjpAprProcessor.output(AjpAprProcessor.java:285) at org.apache.coyote.ajp.AbstractAjpProcessor$SocketOutputBuffer.doWrite(AbstractAjpProcessor.java:1119) at org.apache.coyote.Response.doWrite(Response.java:504) at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:383) at org.apache.tomcat.util.buf.ByteChunk.flushBuffer(ByteChunk.java:462) at org.apache.catalina.connector.OutputBuffer.doFlush(OutputBuffer.java:334) at org.apache.catalina.connector.OutputBuffer.close(OutputBuffer.java:283) at org.apache.catalina.connector.Response.finishResponse(Response.java:511) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:434) at org.apache.coyote.ajp.AjpAprProcessor.process(AjpAprProcessor.java:197) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:565) at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:1812) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603) at java.lang.Thread.run(Thread.java:722) I guess the exception itself is harmless, but it may fill up log files, if clients disconnect frequently while receiving data. Note that before that exception occurs, a regular "ClientAbortException: java.io.IOException: Failed to send AJP message" is thrown by org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:388). The exception occurs neither with AJP-BIO nor with AJP-NIO. [1] http://markmail.org/message/zogi3tfbz2kyw3jg [2] http://markmail.org/message/ntejdw36pfhlqodr -- Configure bugmail: https://issues.apache.org/bugzilla/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- You are the assignee for the bug. --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org